-
Notifications
You must be signed in to change notification settings - Fork 4.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Vite issues with SolidStart #16052
Changes from all commits
aaa2c02
92e5405
81e5f04
48871b4
075d202
25edeb1
5f13aae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { candidate, css, fetchStyles, js, json, retryAssertion, test, ts } from '../utils' | ||
|
||
const WORKSPACE = { | ||
'package.json': json` | ||
{ | ||
"type": "module", | ||
"dependencies": { | ||
"@solidjs/start": "^1", | ||
"solid-js": "^1", | ||
"vinxi": "^0", | ||
"@tailwindcss/vite": "workspace:^", | ||
"tailwindcss": "workspace:^" | ||
} | ||
} | ||
`, | ||
'jsconfig.json': json` | ||
{ | ||
"compilerOptions": { | ||
"jsx": "preserve", | ||
"jsxImportSource": "solid-js" | ||
} | ||
} | ||
`, | ||
'app.config.js': ts` | ||
import { defineConfig } from '@solidjs/start/config' | ||
import tailwindcss from '@tailwindcss/vite' | ||
|
||
export default defineConfig({ | ||
vite: { | ||
plugins: [tailwindcss()], | ||
}, | ||
}) | ||
`, | ||
'src/entry-server.jsx': js` | ||
// @refresh reload | ||
import { createHandler, StartServer } from '@solidjs/start/server' | ||
|
||
export default createHandler(() => ( | ||
<StartServer | ||
document={({ assets, children, scripts }) => ( | ||
<html lang="en"> | ||
<head>{assets}</head> | ||
<body> | ||
<div id="app">{children}</div> | ||
{scripts} | ||
</body> | ||
</html> | ||
)} | ||
/> | ||
)) | ||
`, | ||
'src/entry-client.jsx': js` | ||
// @refresh reload | ||
import { mount, StartClient } from '@solidjs/start/client' | ||
|
||
mount(() => <StartClient />, document.getElementById('app')) | ||
`, | ||
'src/app.jsx': js` | ||
import './app.css' | ||
export default function App() { | ||
return <h1 class="underline">Hello world!</h1> | ||
} | ||
`, | ||
'src/app.css': css`@import 'tailwindcss';`, | ||
} | ||
|
||
test( | ||
'dev mode', | ||
{ | ||
fs: WORKSPACE, | ||
}, | ||
async ({ fs, spawn, expect }) => { | ||
let process = await spawn('pnpm vinxi dev', { | ||
env: { | ||
TEST: 'false', // VERY IMPORTANT OTHERWISE YOU WON'T GET OUTPUT | ||
NODE_ENV: 'development', | ||
}, | ||
}) | ||
|
||
let url = '' | ||
await process.onStdout((m) => { | ||
let match = /Local:\s*(http.*)\//.exec(m) | ||
if (match) url = match[1] | ||
return Boolean(url) | ||
}) | ||
|
||
await retryAssertion(async () => { | ||
let css = await fetchStyles(url) | ||
expect(css).toContain(candidate`underline`) | ||
}) | ||
|
||
await retryAssertion(async () => { | ||
await fs.write( | ||
'src/app.jsx', | ||
js` | ||
import './app.css' | ||
export default function App() { | ||
return <h1 class="underline font-bold">Hello world!</h1> | ||
} | ||
`, | ||
) | ||
|
||
let css = await fetchStyles(url) | ||
expect(css).toContain(candidate`underline`) | ||
expect(css).toContain(candidate`font-bold`) | ||
}) | ||
}, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,7 +63,7 @@ export default function tailwindcss(): Plugin[] { | |
) | ||
}) | ||
|
||
function scanFile(id: string, content: string, extension: string, isSSR: boolean) { | ||
function scanFile(id: string, content: string, extension: string) { | ||
for (let dependency of IGNORED_DEPENDENCIES) { | ||
// We validated that Vite IDs always use posix style path separators, even on Windows. | ||
// In dev build, Vite precompiles dependencies | ||
|
@@ -83,26 +83,16 @@ export default function tailwindcss(): Plugin[] { | |
} | ||
|
||
if (updated) { | ||
invalidateAllRoots(isSSR) | ||
invalidateAllRoots() | ||
} | ||
} | ||
|
||
function invalidateAllRoots(isSSR: boolean) { | ||
function invalidateAllRoots() { | ||
for (let server of servers) { | ||
let updates: Update[] = [] | ||
for (let [id, root] of roots.entries()) { | ||
for (let [id] of roots.entries()) { | ||
let module = server.moduleGraph.getModuleById(id) | ||
if (!module) { | ||
// Note: Removing this during SSR is not safe and will produce | ||
// inconsistent results based on the timing of the removal and | ||
// the order / timing of transforms. | ||
if (!isSSR) { | ||
Comment on lines
-96
to
-99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not 100% sure why this is safe to do this unconditionally. Is it just because we are never removing any There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're no longer calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm being a dumb dumb, carry on. |
||
// It is safe to remove the item here since we're iterating on a copy | ||
// of the keys. | ||
roots.delete(id) | ||
} | ||
continue | ||
} | ||
if (!module) continue | ||
|
||
roots.get(id).requiresRebuild = false | ||
server.moduleGraph.invalidateModule(module) | ||
|
@@ -113,7 +103,6 @@ export default function tailwindcss(): Plugin[] { | |
timestamp: Date.now(), | ||
}) | ||
} | ||
|
||
if (updates.length > 0) { | ||
server.hot.send({ type: 'update', updates }) | ||
} | ||
|
@@ -210,12 +199,15 @@ export default function tailwindcss(): Plugin[] { | |
|
||
// Scan all non-CSS files for candidates | ||
transformIndexHtml(html, { path }) { | ||
scanFile(path, html, 'html', isSSR) | ||
// SolidStart emits HTML chunks with an undefined path and the html content of `\`. | ||
if (!path) return | ||
|
||
scanFile(path, html, 'html') | ||
}, | ||
transform(src, id, options) { | ||
let extension = getExtension(id) | ||
if (isPotentialCssRootFile(id)) return | ||
scanFile(id, src, extension, options?.ssr ?? false) | ||
scanFile(id, src, extension) | ||
}, | ||
}, | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍