Skip to content
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 script injection during build #12392

Merged
merged 16 commits into from
Nov 14, 2024
5 changes: 5 additions & 0 deletions .changeset/slimy-pets-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fix issue where shared entrypoints in injectRoute() remove client-side scripts in SSR builds.
apatel369 marked this conversation as resolved.
Show resolved Hide resolved
32 changes: 13 additions & 19 deletions packages/astro/src/core/build/plugins/plugin-hoisted-scripts.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type { BuildOptions, Rollup, Plugin as VitePlugin } from 'vite';
import type { AstroSettings } from '../../../@types/astro.js';
import { viteID } from '../../util.js';
import type { BuildInternals } from '../internal.js';
import { getPageDataByViteID } from '../internal.js';
import { getPageDatasByHoistedScriptId } from '../internal.js';
import type { AstroBuildPlugin } from '../plugin.js';
import type { StaticBuildOptions } from '../types.js';
import { shouldInlineAsset } from './util.js';
Expand All @@ -12,7 +11,7 @@
}

export function vitePluginHoistedScripts(
settings: AstroSettings,

Check notice on line 14 in packages/astro/src/core/build/plugins/plugin-hoisted-scripts.ts

View workflow job for this annotation

GitHub Actions / Lint

lint/correctness/noUnusedFunctionParameters

This parameter is unused.

Check notice on line 14 in packages/astro/src/core/build/plugins/plugin-hoisted-scripts.ts

View workflow job for this annotation

GitHub Actions / Lint

lint/correctness/noUnusedVariables

This parameter is unused.
internals: BuildInternals,
): VitePlugin {
let assetsInlineLimit: NonNullable<BuildOptions['assetsInlineLimit']>;
Expand Down Expand Up @@ -73,23 +72,18 @@
shouldInlineAsset(output.code, output.fileName, assetsInlineLimit);
let removeFromBundle = false;
const facadeId = output.facadeModuleId!;
const pages = internals.hoistedScriptIdToPagesMap.get(facadeId)!;
for (const pathname of pages) {
const vid = viteID(new URL('.' + pathname, settings.config.root));
const pageInfo = getPageDataByViteID(internals, vid);
if (pageInfo) {
if (canBeInlined) {
pageInfo.hoistedScript = {
type: 'inline',
value: output.code,
};
removeFromBundle = true;
} else {
pageInfo.hoistedScript = {
type: 'external',
value: id,
};
}
for (const pageData of getPageDatasByHoistedScriptId(internals, facadeId)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you noticed from the Github bot comments, settings isn't used anymore, so we can remove it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed. Thanks.

if (canBeInlined) {
pageData.hoistedScript = {
type: 'inline',
value: output.code,
};
removeFromBundle = true;
} else {
pageData.hoistedScript = {
type: 'external',
value: id,
};
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
---
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Routing</title>
</head>
<body>
<h1>to-inject.astro</h1>
</body>
</html>
<h1>to-inject.astro</h1>
<script>
console.log('to-inject.astro');
</script>
26 changes: 24 additions & 2 deletions packages/astro/test/reuse-injected-entrypoint.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ const routes = [
description: 'matches /injected-a to to-inject.astro',
url: '/injected-a',
h1: 'to-inject.astro',
scriptContent: 'console.log("to-inject.astro");',
},
{
description: 'matches /injected-b to to-inject.astro',
url: '/injected-b',
h1: 'to-inject.astro',
scriptContent: 'console.log("to-inject.astro");',
},
{
description: 'matches /dynamic-a/id-1 to [id].astro',
Expand Down Expand Up @@ -60,7 +62,7 @@ describe('Reuse injected entrypoint', () => {
await fixture.build();
});

routes.forEach(({ description, url, fourOhFour, h1, p, htmlMatch }) => {
routes.forEach(({ description, url, fourOhFour, h1, p, htmlMatch, scriptContent }) => {
const isEndpoint = htmlMatch && !h1 && !p;

it(description, async () => {
Expand All @@ -85,6 +87,15 @@ describe('Reuse injected entrypoint', () => {
if (htmlMatch) {
assert.equal(html, htmlMatch);
}

if (scriptContent) {
const scriptTags = $('script[type="module"]').toArray();
const scriptFound = scriptTags.some((script) => {
const scriptText = $(script).text();
return scriptText.includes(scriptContent.trim());
});
assert(scriptFound, `Expected script content to be injected in SSG ${url}`);
}
});
});
});
Expand All @@ -105,7 +116,7 @@ describe('Reuse injected entrypoint', () => {
await devServer.stop();
});

routes.forEach(({ description, url, fourOhFour, h1, p, htmlMatch }) => {
routes.forEach(({ description, url, fourOhFour, h1, p, htmlMatch, scriptContent }) => {
// checks URLs as written above
it(description, async () => {
const html = await fixture.fetch(url).then((res) => res.text());
Expand All @@ -127,6 +138,17 @@ describe('Reuse injected entrypoint', () => {
if (htmlMatch) {
assert.equal(html, htmlMatch);
}

if (scriptContent) {
const scriptTags = $('script[type="module"]').toArray();
const scriptFound = scriptTags.some((script) => {
const scriptSrc = $(script).attr('src');
return (
scriptSrc && scriptSrc.includes('/to-inject.astro?astro&type=script&index=0&lang.ts')
);
});
assert(scriptFound, `Expected script content to be injected in dev ${url}`);
}
});
});
});
Expand Down
Loading