Skip to content

Commit 3ed9cd0

Browse files
authored
Merge pull request #8019 from QwikDev/v2-fixes
fix: small fixes for v2
2 parents 2153e74 + cb8fd84 commit 3ed9cd0

File tree

8 files changed

+172
-94
lines changed

8 files changed

+172
-94
lines changed

packages/docs/src/repl/bundler/rollup-plugins.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ export const replResolver = (
6969
if (pkgName === '/build') {
7070
return `/node_modules/@qwik.dev/core/build`;
7171
}
72-
if (!pkgName || pkgName === '/jsx-runtime' || pkgName === '/jsx-dev-runtime') {
72+
if (
73+
!pkgName ||
74+
pkgName === '/jsx-runtime' ||
75+
pkgName === '/jsx-dev-runtime' ||
76+
pkgName === '/internal'
77+
) {
7378
return resolveQwik('/dist/core.mjs');
7479
}
7580
if (pkgName === '/server') {

packages/docs/vite.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ export default defineConfig(() => {
138138
optimizeDeps: {
139139
entries: ['./src/routes/**/index.tsx', './src/routes/**/layout.tsx'],
140140
exclude: [
141+
'@modular-forms/qwik',
142+
'@qwik-ui/headless',
143+
'qwik-image',
141144
// optimizing breaks the wasm import
142145
'@rolldown/browser',
143146
],

packages/qwik/src/core/client/process-vnode-data.unit.tsx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,52 @@ describe('processVnodeData', () => {
211211
});
212212
});
213213

214+
describe('emitVNodeSeparators', () => {
215+
it('should encode binary correctly', () => {
216+
expect(emitVNodeSeparators(0, 1)).toBe(VNodeDataSeparator.ADVANCE_1_CH);
217+
expect(emitVNodeSeparators(0, 2)).toBe(VNodeDataSeparator.ADVANCE_2_CH);
218+
expect(emitVNodeSeparators(0, 4)).toBe(VNodeDataSeparator.ADVANCE_4_CH);
219+
expect(emitVNodeSeparators(0, 8)).toBe(VNodeDataSeparator.ADVANCE_8_CH);
220+
expect(emitVNodeSeparators(0, 16)).toBe(VNodeDataSeparator.ADVANCE_16_CH);
221+
expect(emitVNodeSeparators(0, 32)).toBe(VNodeDataSeparator.ADVANCE_32_CH);
222+
expect(emitVNodeSeparators(0, 64)).toBe(VNodeDataSeparator.ADVANCE_64_CH);
223+
expect(emitVNodeSeparators(0, 128)).toBe(VNodeDataSeparator.ADVANCE_128_CH);
224+
expect(emitVNodeSeparators(0, 256)).toBe(VNodeDataSeparator.ADVANCE_256_CH);
225+
expect(emitVNodeSeparators(0, 512)).toBe(VNodeDataSeparator.ADVANCE_512_CH);
226+
expect(emitVNodeSeparators(0, 1024)).toBe(VNodeDataSeparator.ADVANCE_1024_CH);
227+
expect(emitVNodeSeparators(0, 2048)).toBe(VNodeDataSeparator.ADVANCE_2048_CH);
228+
expect(emitVNodeSeparators(0, 4096)).toBe(VNodeDataSeparator.ADVANCE_4096_CH);
229+
expect(emitVNodeSeparators(0, 8192)).toBe(VNodeDataSeparator.ADVANCE_8192_CH);
230+
});
231+
it('should encode combinations correctly', () => {
232+
expect(emitVNodeSeparators(0, 3)).toBe(
233+
VNodeDataSeparator.ADVANCE_2_CH + VNodeDataSeparator.ADVANCE_1_CH
234+
);
235+
expect(emitVNodeSeparators(0, 7)).toBe(
236+
VNodeDataSeparator.ADVANCE_4_CH +
237+
VNodeDataSeparator.ADVANCE_2_CH +
238+
VNodeDataSeparator.ADVANCE_1_CH
239+
);
240+
expect(emitVNodeSeparators(0, 15)).toBe(
241+
VNodeDataSeparator.ADVANCE_8_CH +
242+
VNodeDataSeparator.ADVANCE_4_CH +
243+
VNodeDataSeparator.ADVANCE_2_CH +
244+
VNodeDataSeparator.ADVANCE_1_CH
245+
);
246+
expect(emitVNodeSeparators(0, 4097)).toBe(
247+
VNodeDataSeparator.ADVANCE_4096_CH + VNodeDataSeparator.ADVANCE_1_CH
248+
);
249+
expect(emitVNodeSeparators(0, 8193)).toBe(
250+
VNodeDataSeparator.ADVANCE_8192_CH + VNodeDataSeparator.ADVANCE_1_CH
251+
);
252+
expect(emitVNodeSeparators(0, 16385)).toBe(
253+
VNodeDataSeparator.ADVANCE_8192_CH +
254+
VNodeDataSeparator.ADVANCE_8192_CH +
255+
VNodeDataSeparator.ADVANCE_1_CH
256+
);
257+
});
258+
});
259+
214260
const qContainerPaused = { [QContainerAttr]: QContainerValue.RESUMED };
215261
const qContainerHtml = { [QContainerAttr]: QContainerValue.HTML };
216262
function process(html: string): ClientContainer[] {
@@ -261,12 +307,13 @@ function encodeVNode(data: Record<number, string> = {}) {
261307
return `<script type="qwik/vnode">${result}</script>`;
262308
}
263309

310+
// Keep in sync with ssr-container.ts
264311
function emitVNodeSeparators(lastSerializedIdx: number, elementIdx: number): string {
265312
let result = '';
266313
let skipCount = elementIdx - lastSerializedIdx;
267314
// console.log('emitVNodeSeparators', lastSerializedIdx, elementIdx, skipCount);
268315
while (skipCount != 0) {
269-
if (skipCount > 4096) {
316+
if (skipCount >= 8192) {
270317
result += VNodeDataSeparator.ADVANCE_8192_CH;
271318
skipCount -= 8192;
272319
} else {

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

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,20 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
136136
if (!internalOptimizer) {
137137
internalOptimizer = await createOptimizer(optimizerOptions);
138138
lazyNormalizePath = makeNormalizePath(internalOptimizer.sys);
139-
try {
140-
// only try once, don't spam the console
141-
if (maybeFs === undefined) {
142-
maybeFs = await internalOptimizer.sys.dynamicImport('node:fs');
139+
if (
140+
internalOptimizer.sys.env !== 'browsermain' &&
141+
internalOptimizer.sys.env !== 'webworker'
142+
) {
143+
try {
144+
// only try once, don't spam the console
145+
if (maybeFs === undefined) {
146+
maybeFs = await internalOptimizer.sys.dynamicImport('node:fs');
147+
}
148+
} catch {
149+
// eslint-disable-next-line no-console
150+
console.log('node:fs not available, disabling automatic manifest reading');
151+
maybeFs = null;
143152
}
144-
} catch {
145-
// eslint-disable-next-line no-console
146-
console.log('node:fs not available, disabling automatic manifest reading');
147-
maybeFs = null;
148153
}
149154
}
150155
};
@@ -709,14 +714,6 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
709714
return null;
710715
};
711716

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-
720717
let transformCount = 0;
721718
const transform = async function (
722719
ctx: Rollup.PluginContext,
@@ -743,7 +740,7 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
743740
const dir = parsedPathId.dir;
744741
const base = parsedPathId.base;
745742
const ext = parsedPathId.ext.toLowerCase();
746-
if (ext in TRANSFORM_EXTS || TRANSFORM_REGEX.test(pathId) || isOptimizedQwikDep(id, code)) {
743+
if (ext in TRANSFORM_EXTS || TRANSFORM_REGEX.test(pathId)) {
747744
/** Strip client|server code from qwik server|client, but not in lib/test */
748745
const strip = opts.target === 'client' || opts.target === 'ssr';
749746
debug(

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import type { OptimizerSystem } from '../types';
22

33
export async function findDepPkgJsonPath(sys: OptimizerSystem, dep: string, parent: string) {
4+
if (sys.env === 'browsermain' || sys.env === 'webworker') {
5+
return undefined;
6+
}
47
const fs: typeof import('fs') = await sys.dynamicImport('node:fs');
58
let root = parent;
69
while (root) {

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

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -408,25 +408,25 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
408408
},
409409

410410
transform(code, id, transformOpts) {
411-
const shouldTransformFile = fileFilter(id, 'transform');
412-
const isStringImportId = id.includes('?raw');
413-
if (isVirtualId(id) || !shouldTransformFile || isStringImportId) {
414-
return null;
415-
}
416411
if (
417412
id.includes('.vite/deps/') &&
418413
code.slice(0, 5000).includes('qwik') &&
419414
/import[^\n]*qwik[^\n]*\n/.test(code)
420415
) {
421416
const relPath = rootDir && id.startsWith(rootDir) ? id.slice(rootDir.length) : id;
422417
throw new Error(
423-
`\n==============\n` +
424-
`This dependency was pre-bundled by Vite, but it seems to use Qwik, which needs processing by the optimizer.\n` +
425-
`Please add the original modulename to the "optimizeDeps.exclude" array in your Vite config:\n` +
426-
`${relPath}\n` +
427-
`==============\n`
418+
`\n\n==============\n\n` +
419+
`⚠️ IMPORTANT: This dependency was pre-bundled by Vite, but it seems to use Qwik, which needs processing by the optimizer.\n\n` +
420+
`👉 Please add the original modulename to the "optimizeDeps.exclude" array in your Vite config\n` +
421+
`👉 ${relPath}\n\n` +
422+
`==============\n\n`
428423
);
429424
}
425+
const shouldTransformFile = fileFilter(id, 'transform');
426+
const isStringImportId = id.includes('?raw');
427+
if (isVirtualId(id) || !shouldTransformFile || isStringImportId) {
428+
return null;
429+
}
430430

431431
return qwikPlugin.transform(this, code, id, transformOpts);
432432
},
@@ -663,11 +663,30 @@ async function checkExternals() {
663663
configResolved: (config) => {
664664
rootDir = config.root;
665665
},
666+
// Attempt to mark the Qwik dependencies as non-optimizeable
667+
config: {
668+
order: 'post',
669+
async handler(config) {
670+
const toExclude = [];
671+
const externals = [config.ssr?.noExternal, config.environments?.ssr?.resolve?.noExternal]
672+
.flat()
673+
.filter((t) => typeof t === 'string');
674+
const optimizeDepsExclude = config.optimizeDeps?.exclude ?? [];
675+
for (const dep of externals) {
676+
if (!optimizeDepsExclude.includes(dep)) {
677+
if (await isQwikDep(dep, config.root || process.cwd())) {
678+
toExclude.push(dep);
679+
}
680+
}
681+
}
682+
return { optimizeDeps: { exclude: toExclude } };
683+
},
684+
},
666685
// We check all SSR build lookups for external Qwik deps
667686
resolveId: {
668687
order: 'pre',
669688
async handler(source, importer, options) {
670-
if (!options.ssr || /^([./]|node:|[^a-z])/.test(source) || seen.has(source)) {
689+
if (!options.ssr || /^([./]|node:|[^a-z@])/i.test(source) || seen.has(source)) {
671690
return;
672691
}
673692
const packageName = (
@@ -679,22 +698,27 @@ async function checkExternals() {
679698
// technically we should check for each importer, but this is ok
680699
seen.add(source);
681700
seen.add(packageName);
682-
const result = await this.resolve(packageName, importer, { ...options, skipSelf: true });
683-
if (result?.external) {
684-
// Qwik deps should not be external
685-
if (await isQwikDep(packageName, importer ? path.dirname(importer) : rootDir)) {
686-
// TODO link to docs
687-
throw new Error(
688-
`\n==============\n` +
689-
`${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` +
690-
`Please add the package to "ssr.noExternal[]" as well as "optimizeDeps.exclude[]" in the Vite config. \n` +
691-
`==============\n`
692-
);
701+
try {
702+
const result = await this.resolve(packageName, importer, { ...options, skipSelf: true });
703+
if (result?.external) {
704+
// Qwik deps should not be external
705+
if (await isQwikDep(packageName, importer ? path.dirname(importer) : rootDir)) {
706+
// TODO link to docs
707+
throw new Error(
708+
`\n==============\n` +
709+
`${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` +
710+
`Please add the package to "ssr.noExternal[]" as well as "optimizeDeps.exclude[]" in the Vite config. \n` +
711+
`==============\n`
712+
);
713+
}
693714
}
694-
}
695-
if (packageName === source) {
696-
// We already resolved it, so return that result
697-
return result;
715+
if (packageName === source) {
716+
// We already resolved it, so return that result
717+
return result;
718+
}
719+
} catch {
720+
/* ignore, let vite figure it out */
721+
return;
698722
}
699723
},
700724
},

packages/qwik/src/server/ssr-container.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,11 +1001,12 @@ class SSRContainer extends _SharedContainer implements ISSRContainer {
10011001
}
10021002
}
10031003

1004+
// Keep in sync with process-vnode-data.unit.ts
10041005
private emitVNodeSeparators(lastSerializedIdx: number, elementIdx: number): number {
10051006
let skipCount = elementIdx - lastSerializedIdx;
10061007
// console.log('emitVNodeSeparators', lastSerializedIdx, elementIdx, skipCount);
10071008
while (skipCount != 0) {
1008-
if (skipCount > 4096) {
1009+
if (skipCount >= 8192) {
10091010
this.write(VNodeDataSeparator.ADVANCE_8192_CH);
10101011
skipCount -= 8192;
10111012
} else {

0 commit comments

Comments
 (0)