Skip to content

Commit 2657dcc

Browse files
authored
Merge pull request #7982 from maiieul/fix-manualChunks-merging
fix: over-preloading due to inaccurate bundle-graph static import graph
2 parents e35ee3c + 76e7f0e commit 2657dcc

File tree

7 files changed

+201
-154
lines changed

7 files changed

+201
-154
lines changed

.changeset/clean-bears-cough.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@builder.io/qwik': minor
3+
---
4+
5+
FIX: Qwik now leverages Rollup's new `output.onlyExplicitManualChunks` feature, which improves preloading performance and reduces cache invalidation for a snappier user experience.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@
149149
"prettier-plugin-tailwindcss": "0.6.14",
150150
"pretty-quick": "4.2.2",
151151
"prompts": "2.4.2",
152-
"rollup": ">= 4.39.0",
152+
"rollup": ">= 4.52.0",
153153
"semver": "7.7.2",
154154
"simple-git-hooks": "2.13.1",
155155
"snoop": "1.0.4",

packages/qwik/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"dependencies": {
2828
"csstype": "^3.1.3",
2929
"launch-editor": "^2.11.1",
30-
"rollup": ">= ^4.39.0"
30+
"rollup": ">= ^4.52.0"
3131
},
3232
"devDependencies": {
3333
"@builder.io/qwik": "workspace:^",

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

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { Rollup } from 'vite';
2-
32
import type {
43
Diagnostic,
54
EntryStrategy,
@@ -18,6 +17,7 @@ import {
1817
type QwikPlugin,
1918
type QwikPluginOptions,
2019
} from './plugin';
20+
import { findDepPkgJsonPath } from './utils';
2121

2222
type QwikRollupPluginApi = {
2323
getOptimizer: () => Optimizer;
@@ -76,7 +76,7 @@ export function qwikRollup(qwikRollupOpts: QwikRollupPluginOptions = {}): any {
7676
},
7777

7878
outputOptions(rollupOutputOpts) {
79-
return normalizeRollupOutputOptionsObject(qwikPlugin, rollupOutputOpts, false);
79+
return normalizeRollupOutputOptionsObject(qwikPlugin, rollupOutputOpts, false) as any;
8080
},
8181

8282
async buildStart() {
@@ -127,35 +127,37 @@ export function qwikRollup(qwikRollupOpts: QwikRollupPluginOptions = {}): any {
127127
return rollupPlugin;
128128
}
129129

130-
export function normalizeRollupOutputOptions(
130+
export async function normalizeRollupOutputOptions(
131131
qwikPlugin: QwikPlugin,
132132
rollupOutputOpts: Rollup.OutputOptions | Rollup.OutputOptions[] | undefined,
133133
useAssetsDir: boolean,
134134
outDir?: string
135-
): Rollup.OutputOptions | Rollup.OutputOptions[] {
135+
): Promise<Rollup.OutputOptions | Rollup.OutputOptions[]> {
136136
if (Array.isArray(rollupOutputOpts)) {
137137
// make sure at least one output is present in every case
138138
if (!rollupOutputOpts.length) {
139139
rollupOutputOpts.push({});
140140
}
141141

142-
return rollupOutputOpts.map((outputOptsObj) => ({
143-
...normalizeRollupOutputOptionsObject(qwikPlugin, outputOptsObj, useAssetsDir),
144-
dir: outDir || outputOptsObj.dir,
145-
}));
142+
return await Promise.all(
143+
rollupOutputOpts.map(async (outputOptsObj) => ({
144+
...(await normalizeRollupOutputOptionsObject(qwikPlugin, outputOptsObj, useAssetsDir)),
145+
dir: outDir || outputOptsObj.dir,
146+
}))
147+
);
146148
}
147149

148150
return {
149-
...normalizeRollupOutputOptionsObject(qwikPlugin, rollupOutputOpts, useAssetsDir),
151+
...(await normalizeRollupOutputOptionsObject(qwikPlugin, rollupOutputOpts, useAssetsDir)),
150152
dir: outDir || rollupOutputOpts?.dir,
151153
};
152154
}
153155

154-
export function normalizeRollupOutputOptionsObject(
156+
export async function normalizeRollupOutputOptionsObject(
155157
qwikPlugin: QwikPlugin,
156158
rollupOutputOptsObj: Rollup.OutputOptions | undefined,
157159
useAssetsDir: boolean
158-
): Rollup.OutputOptions {
160+
): Promise<Rollup.OutputOptions> {
159161
const outputOpts: Rollup.OutputOptions = { ...rollupOutputOptsObj };
160162
const opts = qwikPlugin.getOptions();
161163
const optimizer = qwikPlugin.getOptimizer();
@@ -253,6 +255,34 @@ export function normalizeRollupOutputOptionsObject(
253255
*/
254256
outputOpts.hoistTransitiveImports = false;
255257

258+
// V2 official release TODO: remove below checks and just keep `outputOpts.onlyExplicitManualChunks = true;`
259+
const userPkgJsonPath = await findDepPkgJsonPath(optimizer.sys, 'rollup', optimizer.sys.cwd());
260+
if (userPkgJsonPath) {
261+
try {
262+
const fs: typeof import('fs') = await optimizer.sys.dynamicImport('node:fs');
263+
const pkgJsonStr = await fs.promises.readFile(userPkgJsonPath, 'utf-8');
264+
const pkgJson = JSON.parse(pkgJsonStr);
265+
const version = String(pkgJson?.version || '');
266+
const [major, minor, patch] = version.split('.').map((n: string) => parseInt(n, 10)) as [
267+
number,
268+
number,
269+
number,
270+
];
271+
const isGte452 =
272+
Number.isFinite(major) &&
273+
(major > 4 || (major === 4 && (minor > 52 || (minor === 52 && (patch || 0) >= 0))));
274+
if (isGte452) {
275+
outputOpts.onlyExplicitManualChunks = true;
276+
} else {
277+
console.warn(
278+
`⚠️ We detected that you're using a Rollup version prior to 4.52.0 (${version}). For the latest and greatest, we recommend to let Vite install the latest version for you, or manually install the latest version of Rollup in your project if that doesn't work. It will enable the new Rollup \`outputOpts.onlyExplicitManualChunks\` feature flag, which improves preloading performance and reduces cache invalidation for a snappier user experience.`
279+
);
280+
}
281+
} catch {
282+
// If we cannot determine the installed Rollup version, avoid warning
283+
}
284+
}
285+
256286
return outputOpts;
257287
}
258288

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { OptimizerSystem } from '../types';
2+
3+
export async function findDepPkgJsonPath(sys: OptimizerSystem, dep: string, parent: string) {
4+
const fs: typeof import('fs') = await sys.dynamicImport('node:fs');
5+
let root = parent;
6+
while (root) {
7+
const pkg = sys.path.join(root, 'node_modules', dep, 'package.json');
8+
try {
9+
await fs.promises.access(pkg);
10+
// use 'node:fs' version to match 'vite:resolve' and avoid realpath.native quirk
11+
// https://github.com/sveltejs/vite-plugin-svelte/issues/525#issuecomment-1355551264
12+
return fs.promises.realpath(pkg);
13+
} catch {
14+
//empty
15+
}
16+
const nextRoot = sys.path.dirname(root);
17+
if (nextRoot === root) {
18+
break;
19+
}
20+
root = nextRoot;
21+
}
22+
return undefined;
23+
}

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

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
import { createRollupError, normalizeRollupOutputOptions } from './rollup';
3333
import { VITE_DEV_CLIENT_QS, configureDevServer, configurePreviewServer } from './vite-dev-server';
3434
import { parseId } from './vite-utils';
35+
import { findDepPkgJsonPath } from './utils';
3536

3637
const DEDUPE = [QWIK_CORE_ID, QWIK_JSX_RUNTIME_ID, QWIK_JSX_DEV_RUNTIME_ID];
3738

@@ -345,7 +346,7 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
345346
const origOnwarn = updatedViteConfig.build!.rollupOptions?.onwarn;
346347
updatedViteConfig.build!.rollupOptions = {
347348
input: opts.input,
348-
output: normalizeRollupOutputOptions(
349+
output: await normalizeRollupOutputOptions(
349350
qwikPlugin,
350351
viteConfig.build?.rollupOptions?.output,
351352
useAssetsDir,
@@ -752,28 +753,6 @@ export async function render(document, rootNode, opts) {
752753
}`;
753754
}
754755

755-
async function findDepPkgJsonPath(sys: OptimizerSystem, dep: string, parent: string) {
756-
const fs: typeof import('fs') = await sys.dynamicImport('node:fs');
757-
let root = parent;
758-
while (root) {
759-
const pkg = sys.path.join(root, 'node_modules', dep, 'package.json');
760-
try {
761-
await fs.promises.access(pkg);
762-
// use 'node:fs' version to match 'vite:resolve' and avoid realpath.native quirk
763-
// https://github.com/sveltejs/vite-plugin-svelte/issues/525#issuecomment-1355551264
764-
return fs.promises.realpath(pkg);
765-
} catch {
766-
//empty
767-
}
768-
const nextRoot = sys.path.dirname(root);
769-
if (nextRoot === root) {
770-
break;
771-
}
772-
root = nextRoot;
773-
}
774-
return undefined;
775-
}
776-
777756
const findQwikRoots = async (
778757
sys: OptimizerSystem,
779758
packageJsonDir: string

0 commit comments

Comments
 (0)