Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/twelve-sloths-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes build errors on platforms with skew protection enabled (e.g. Vercel, Netlify) for inter-chunk Javascript using dynamic imports
7 changes: 5 additions & 2 deletions packages/astro/src/core/build/plugins/plugin-chunk-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ export function pluginChunkImports(options: StaticBuildOptions): VitePlugin | un
let rewritten = code;
for (let i = relativeImports.length - 1; i >= 0; i--) {
const imp = relativeImports[i];
// imp.s and imp.e are the start/end offsets of the module specifier (without quotes)
rewritten = rewritten.slice(0, imp.e) + '?' + queryString + rewritten.slice(imp.e);
// imp.s and imp.e are the start/end offsets of the module specifier.
// Static imports: e points after the specifier text, before the quote.
// Dynamic string imports: e points after the closing quote.
const insertAt = imp.d > -1 ? imp.e - 1 : imp.e;
rewritten = rewritten.slice(0, insertAt) + '?' + queryString + rewritten.slice(insertAt);
}

return { code: rewritten, map: null };
Expand Down
33 changes: 25 additions & 8 deletions packages/astro/test/asset-query-params.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,29 +173,46 @@ describe('Asset Query Parameters in Inter-Chunk JS Imports', () => {
const scripts = $('script[src]');
assert.ok(scripts.length > 0, 'Should have at least one external script');

let foundRelativeImport = false;
let foundStaticImport = false;
let foundDynamicImport = false;
// Read all client JS files and check inter-chunk imports have query params
const jsFiles = await fixture.glob('client/**/*.js');
for (const file of jsFiles) {
const code = await fixture.readFile(`/${file}`);
// Match relative imports: from"./chunk.js", from "./chunk.js", import("./chunk.js")
const allImports = [
// Match static imports: from "./chunk.js", from "./chunk.js"
const staticImports = [
...code.matchAll(/(from\s*["'])(\.\.?\/[^"']+\.(?:js|mjs)(?:\?[^"']*)?)(["'])/g),
];
// Match dynamic imports: import("./chunk.js")
const dynamicImports = [
...code.matchAll(/(import\s*\(\s*["'])(\.\.?\/[^"']+\.(?:js|mjs)(?:\?[^"']*)?)(["'])/g),
];
for (const match of allImports) {
foundRelativeImport = true;
for (const match of staticImports) {
foundStaticImport = true;
const importPath = match[2];
assert.match(
importPath,
/\?dpl=test-deploy-id/,
`Inter-chunk import should include assetQueryParams: ${match[0]}`,
`Static inter-chunk import should include assetQueryParams: ${match[0]}`,
);
}
for (const match of dynamicImports) {
foundDynamicImport = true;
const importPath = match[2];
assert.match(
importPath,
/\?dpl=test-deploy-id/,
`Dynamic inter-chunk import should include assetQueryParams: ${match[0]}`,
);
}
}
assert.ok(
foundRelativeImport,
'Expected at least one relative inter-chunk import in client JS files',
foundStaticImport,
'Expected at least one static relative inter-chunk import in client JS files',
);
assert.ok(
foundDynamicImport,
'Expected at least one dynamic relative inter-chunk import in client JS files',
);
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div id="dynamic-loader">Dynamic Loader</div>
<script>
const { greet, MESSAGES } = await import('./shared.js');
const el = document.getElementById('dynamic-loader');
if (el) el.textContent = greet('Dynamic') + ' ' + MESSAGES.loading;
</script>
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
---
import CounterA from '../components/CounterA.astro';
import CounterB from '../components/CounterB.astro';
import DynamicLoader from '../components/DynamicLoader.astro';
---
<html>
<head><title>Chunk Imports Test</title></head>
<body>
<CounterA />
<CounterB />
<DynamicLoader />
</body>
</html>
Loading