Skip to content

Commit

Permalink
fix: lightningcss fails with html-proxy (#13776)
Browse files Browse the repository at this point in the history
Co-authored-by: Arnaud Barré <arnaud.barre@carbometrix.com>
  • Loading branch information
Marabyte and ArnaudBarre committed Jul 24, 2023
1 parent 883089c commit 6b56094
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 8 deletions.
4 changes: 4 additions & 0 deletions packages/vite/src/node/plugins/css.ts
Expand Up @@ -2183,6 +2183,10 @@ async function compileLightningCSS(
if (filePath === filename) {
return src
}
// This happens with html-proxy (#13776)
if (!filePath.endsWith('.css')) {
return src
}
return fs.readFileSync(toAbsolute(filePath), 'utf-8')
},
async resolve(id, from) {
Expand Down
@@ -0,0 +1,13 @@
import { describe, expect, test } from 'vitest'
import { port } from './serve'
import { getColor, page } from '~utils'

const url = `http://localhost:${port}`

describe('injected inline style', () => {
test('injected inline style is present', async () => {
await page.goto(url)
const el = await page.$('.ssr-proxy')
expect(await getColor(el)).toBe('coral')
})
})
38 changes: 38 additions & 0 deletions playground/css-lightningcss-proxy/__tests__/serve.ts
@@ -0,0 +1,38 @@
// this is automatically detected by playground/vitestSetup.ts and will replace
// the default e2e test serve behavior

import path from 'node:path'
import kill from 'kill-port'
import { hmrPorts, ports, rootDir } from '~utils'

export const port = ports['css/lightningcss-proxy']

export async function serve(): Promise<{ close(): Promise<void> }> {
await kill(port)

const { createServer } = await import(path.resolve(rootDir, 'server.js'))
const { app, vite } = await createServer(
rootDir,
hmrPorts['css/lightningcss-proxy'],
)

return new Promise((resolve, reject) => {
try {
const server = app.listen(port, () => {
resolve({
// for test teardown
async close() {
await new Promise((resolve) => {
server.close(resolve)
})
if (vite) {
await vite.close()
}
},
})
})
} catch (e) {
reject(e)
}
})
}
5 changes: 5 additions & 0 deletions playground/css-lightningcss-proxy/index.html
@@ -0,0 +1,5 @@
<!--[inline-css]-->
<div class="wrapper">
<p>Injected inline style with SSR Proxy</p>
<p class="ssr-proxy">This should be coral</p>
</div>
15 changes: 15 additions & 0 deletions playground/css-lightningcss-proxy/package.json
@@ -0,0 +1,15 @@
{
"name": "@vitejs/test-css-lightningcss-proxy",
"private": true,
"type": "module",
"scripts": {
"dev": "node server",
"serve": "NODE_ENV=production node server",
"debug": "node --inspect-brk server",
"preview": "vite preview"
},
"devDependencies": {
"lightningcss": "^1.21.5",
"express": "^4.18.2"
}
}
89 changes: 89 additions & 0 deletions playground/css-lightningcss-proxy/server.js
@@ -0,0 +1,89 @@
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import express from 'express'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const isTest = process.env.VITEST

const DYNAMIC_STYLES = `
<style>
.ssr-proxy {
color: coral;
}
</style>
`

export async function createServer(root = process.cwd(), hmrPort) {
const resolve = (p) => path.resolve(__dirname, p)

const app = express()

/**
* @type {import('vite').ViteDevServer}
*/
const vite = await (
await import('vite')
).createServer({
root,
logLevel: isTest ? 'error' : 'info',
css: {
transformer: 'lightningcss',
lightningcss: {
drafts: { nesting: true },
},
},
server: {
middlewareMode: true,
watch: {
// During tests we edit the files too fast and sometimes chokidar
// misses change events, so enforce polling for consistency
usePolling: true,
interval: 100,
},
hmr: {
port: hmrPort,
},
},
appType: 'custom',
})
// use vite's connect instance as middleware
app.use(vite.middlewares)

app.use('*', async (req, res, next) => {
try {
let [url] = req.originalUrl.split('?')
if (url.endsWith('/')) url += 'index.html'

if (url.startsWith('/favicon.ico')) {
return res.status(404).end('404')
}

const htmlLoc = resolve(`.${url}`)
let template = fs.readFileSync(htmlLoc, 'utf-8')

template = template.replace('<!--[inline-css]-->', DYNAMIC_STYLES)

// Force calling transformIndexHtml with url === '/', to simulate
// usage by ecosystem that was recommended in the SSR documentation
// as `const url = req.originalUrl`
const html = await vite.transformIndexHtml('/', template)

res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
} catch (e) {
vite && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)
}
})

return { app, vite }
}

if (!isTest) {
createServer().then(({ app }) =>
app.listen(5173, () => {
console.log('http://localhost:5173')
}),
)
}
2 changes: 2 additions & 0 deletions playground/test-utils.ts
Expand Up @@ -35,6 +35,7 @@ export const ports = {
'css/postcss-caching': 5005,
'css/postcss-plugins-different-dir': 5006,
'css/dynamic-import': 5007,
'css/lightningcss-proxy': 5008,
}
export const hmrPorts = {
'optimize-missing-deps': 24680,
Expand All @@ -43,6 +44,7 @@ export const hmrPorts = {
'ssr-html': 24683,
'ssr-noexternal': 24684,
'ssr-pug': 24685,
'css/lightningcss-proxy': 24686,
}

const hexToNameMap: Record<string, string> = {}
Expand Down
25 changes: 17 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6b56094

Please sign in to comment.