Skip to content

Commit ceaa368

Browse files
committed
fix(vite): better dev build error detection
1 parent a97dcf1 commit ceaa368

File tree

8 files changed

+67
-17
lines changed

8 files changed

+67
-17
lines changed

.changeset/bright-cloths-film.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
Fix: Better configuration of Vite's optimizeDeps, preventing false duplication warnings, and verifying that Qwik dependencies are not in optimizeDeps.

packages/qwik-router/src/adapters/shared/vite/index.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export function viteAdapter(opts: ViteAdapterPluginOptions) {
2020
let renderModulePath: string | null = null;
2121
let qwikRouterConfigModulePath: string | null = null;
2222
let isSsrBuild = false;
23+
let viteCommand: string | undefined;
2324
const outputEntries: string[] = [];
2425

2526
const plugin: Plugin<never> = {
@@ -40,6 +41,7 @@ export function viteAdapter(opts: ViteAdapterPluginOptions) {
4041

4142
configResolved(config) {
4243
isSsrBuild = !!config.build.ssr;
44+
viteCommand = config.command;
4345

4446
if (isSsrBuild) {
4547
qwikRouterPlugin = config.plugins.find(
@@ -72,17 +74,19 @@ export function viteAdapter(opts: ViteAdapterPluginOptions) {
7274
buildStart() {
7375
if (isSsrBuild && opts.ssg !== null) {
7476
const { srcDir } = qwikVitePlugin!.api!.getOptions()!;
75-
// TODO don't rely on entry points for SSG, somehow
76-
this.emitFile({
77-
id: '@qwik-router-config',
78-
type: 'chunk',
79-
fileName: '@qwik-router-config.js',
80-
});
81-
this.emitFile({
82-
id: `${srcDir}/entry.ssr`,
83-
type: 'chunk',
84-
fileName: 'entry.ssr.js',
85-
});
77+
if (viteCommand === 'build' && serverOutDir && srcDir) {
78+
// TODO don't rely on entry points for SSG, somehow
79+
this.emitFile({
80+
id: '@qwik-router-config',
81+
type: 'chunk',
82+
fileName: '@qwik-router-config.js',
83+
});
84+
this.emitFile({
85+
id: `${srcDir}/entry.ssr`,
86+
type: 'chunk',
87+
fileName: 'entry.ssr.js',
88+
});
89+
}
8690
}
8791
},
8892
generateBundle(_, bundles) {

packages/qwik-router/src/buildtime/vite/dev-middleware.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ export const makeRouterDevMiddleware =
5353
return;
5454
}
5555

56+
// We'll be reloading the Qwik module, that's fine, don't let it warn
57+
(globalThis as any).__qwik = undefined;
5658
// Now we can stream the render
5759
const { createQwikRouter } = (await server.ssrLoadModule(
5860
'@qwik.dev/router/middleware/node'

packages/qwik-router/src/buildtime/vite/plugin.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ function qwikRouterPlugin(userOpts?: QwikRouterVitePluginOptions): any {
9999
`${routesDir}/**/layout*`,
100100
`${serverPluginsDir}/plugin@*`,
101101
],
102+
// These need processing by the optimizer during dev
102103
exclude: [
103104
QWIK_ROUTER,
104105
QWIK_ROUTER_CONFIG_ID,

packages/qwik/src/core/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ import { version } from './version';
55
if ((globalThis as any).__qwik) {
66
console.error(
77
`==============================================\n` +
8-
`Qwik version ${(globalThis as any).__qwik} already imported while importing ${version}. Verify external vs bundled imports etc. This can lead to issues due to duplicated shared structures.\n` +
8+
`Qwik version ${(globalThis as any).__qwik} already imported while importing ${version}.\n` +
9+
`This can lead to issues due to duplicated shared structures.\n` +
10+
`Verify that the Qwik libraries you're using are in "resolve.noExternal[]" and in "optimizeDeps.exclude".\n` +
911
`==============================================\n`
1012
);
1113
}
1214
(globalThis as any).__qwik = version;
1315

16+
if (import.meta.hot) {
17+
import.meta.hot.dispose(() => {
18+
(globalThis as any).__qwik = undefined;
19+
});
20+
}
21+
1422
//////////////////////////////////////////////////////////////////////////////////////////
1523
// Developer Core API
1624
//////////////////////////////////////////////////////////////////////////////////////////

packages/qwik/src/optimizer/src/plugins/plugin.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,14 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
709709
return null;
710710
};
711711

712+
/** Optimized deps can contain Qwik libraries, process them too */
713+
const isOptimizedQwikDep = (id: string, code: string) => {
714+
if (devServer && id.includes('.vite/deps/') && code.slice(0, 10000).includes('qwik')) {
715+
return true;
716+
}
717+
return false;
718+
};
719+
712720
let transformCount = 0;
713721
const transform = async function (
714722
ctx: Rollup.PluginContext,
@@ -735,7 +743,7 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
735743
const dir = parsedPathId.dir;
736744
const base = parsedPathId.base;
737745
const ext = parsedPathId.ext.toLowerCase();
738-
if (ext in TRANSFORM_EXTS || TRANSFORM_REGEX.test(pathId)) {
746+
if (ext in TRANSFORM_EXTS || TRANSFORM_REGEX.test(pathId) || isOptimizedQwikDep(id, code)) {
739747
/** Strip client|server code from qwik server|client, but not in lib/test */
740748
const strip = opts.target === 'client' || opts.target === 'ssr';
741749
debug(

packages/qwik/src/optimizer/src/plugins/vite.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,16 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
245245
QWIK_JSX_DEV_RUNTIME_ID,
246246
QWIK_BUILD_ID,
247247
QWIK_CLIENT_MANIFEST_ID,
248-
// v1 imports, they are removed during transform but vite doesn't know that
249248
'@builder.io/qwik',
250-
'@builder.io/qwik-city',
251249
],
250+
// Enforce scanning our input even when overridden later
251+
entries:
252+
input &&
253+
(typeof input === 'string'
254+
? [input]
255+
: typeof input === 'object'
256+
? Object.values(input)
257+
: input),
252258
},
253259
build: {
254260
modulePreload: false,
@@ -402,6 +408,20 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
402408
if (id.startsWith('\0') || !fileFilter(id, 'transform') || id.includes('?raw')) {
403409
return null;
404410
}
411+
if (
412+
id.includes('.vite/deps/') &&
413+
code.slice(0, 5000).includes('qwik') &&
414+
/import[^\n]*qwik[^\n]*\n/.test(code)
415+
) {
416+
const relPath = rootDir && id.startsWith(rootDir) ? id.slice(rootDir.length) : id;
417+
throw new Error(
418+
`\n==============\n` +
419+
`This dependency was pre-bundled by Vite, but it seems to use Qwik, which needs processing by the optimizer.\n` +
420+
`Please add the original modulename to the "optimizeDeps.exclude" array in your Vite config:\n` +
421+
`${relPath}\n` +
422+
`==============\n`
423+
);
424+
}
405425

406426
return qwikPlugin.transform(this, code, id, transformOpts);
407427
},
@@ -660,7 +680,10 @@ async function checkExternals() {
660680
if (await isQwikDep(packageName, importer ? path.dirname(importer) : rootDir)) {
661681
// TODO link to docs
662682
throw new Error(
663-
`\n==============\n${packageName} is being treated as an external dependency, but it should be included in the server bundle, because it uses Qwik.\nPlease add the package to "ssr.noExternal" in the Vite config. \n==============`
683+
`\n==============\n` +
684+
`${packageName} is being treated as an external dependency, but it should be included in the server bundle, because it uses Qwik and it needs to be processed by the optimizer.\n` +
685+
`Please add the package to "ssr.noExternal[]" as well as "optimizeDeps.exclude[]" in the Vite config. \n` +
686+
`==============\n`
664687
);
665688
}
666689
}

packages/qwik/src/optimizer/src/plugins/vite.unit.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ const excludeDeps = [
5353
'@qwik.dev/core/build',
5454
'@qwik-client-manifest',
5555
'@builder.io/qwik',
56-
'@builder.io/qwik-city',
5756
];
5857

5958
const getPlugin = (opts: QwikVitePluginOptions | undefined) =>

0 commit comments

Comments
 (0)