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

Preserve generating routes that end with .mjs #9374

Merged
merged 2 commits into from
Dec 8, 2023
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/shiny-glasses-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes an issue where prerendered route paths that end with `.mjs` were removed from the final build
4 changes: 2 additions & 2 deletions packages/astro/src/core/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ class AstroBuilder {
viteConfig,
};

const { internals } = await viteBuild(opts);
await staticBuild(opts, internals);
const { internals, ssrOutputChunkNames } = await viteBuild(opts);
await staticBuild(opts, internals, ssrOutputChunkNames);

// Write any additionally generated assets to disk.
this.timer.assetsStart = performance.now();
Expand Down
18 changes: 2 additions & 16 deletions packages/astro/src/core/build/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Plugin as VitePlugin } from 'vite';
import type { Plugin as VitePlugin, Rollup } from 'vite';
import type { BuildInternals } from './internal.js';
import type { StaticBuildOptions, ViteBuildReturn } from './types.js';

Expand Down Expand Up @@ -68,28 +68,14 @@ export function createPluginContainer(options: StaticBuildOptions, internals: Bu
};
},

async runPostHook(ssrReturn: ViteBuildReturn, clientReturn: ViteBuildReturn | null) {
async runPostHook(ssrOutputs: Rollup.RollupOutput[], clientOutputs: Rollup.RollupOutput[]) {
const mutations = new Map<
string,
{
targets: BuildTarget[];
code: string;
}
>();
const ssrOutputs: RollupOutputArray = [];
const clientOutputs: RollupOutputArray = [];

if (Array.isArray(ssrReturn)) {
ssrOutputs.push(...ssrReturn);
} else if ('output' in ssrReturn) {
ssrOutputs.push(ssrReturn);
}

if (Array.isArray(clientReturn)) {
clientOutputs.push(...clientReturn);
} else if (clientReturn && 'output' in clientReturn) {
clientOutputs.push(clientReturn);
}

const mutate: MutateChunk = (chunk, targets, newCode) => {
chunk.code = newCode;
Expand Down
57 changes: 36 additions & 21 deletions packages/astro/src/core/build/static-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { RESOLVED_RENDERERS_MODULE_ID } from './plugins/plugin-renderers.js';
import { RESOLVED_SPLIT_MODULE_ID, RESOLVED_SSR_VIRTUAL_MODULE_ID } from './plugins/plugin-ssr.js';
import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.js';
import type { StaticBuildOptions } from './types.js';
import { encodeName, getTimeStat } from './util.js';
import { encodeName, getTimeStat, viteBuildReturnToRollupOutputs } from './util.js';

export async function viteBuild(opts: StaticBuildOptions) {
const { allPages, settings } = opts;
Expand Down Expand Up @@ -103,7 +103,9 @@ export async function viteBuild(opts: StaticBuildOptions) {
// Run client build first, so the assets can be fed into the SSR rendered version.
const clientOutput = await clientBuild(opts, internals, clientInput, container);

await runPostBuildHooks(container, ssrOutput, clientOutput);
const ssrOutputs = viteBuildReturnToRollupOutputs(ssrOutput);
const clientOutputs = viteBuildReturnToRollupOutputs(clientOutput ?? []);
await runPostBuildHooks(container, ssrOutputs, clientOutputs);

settings.timer.end('Client build');

Expand All @@ -113,23 +115,38 @@ export async function viteBuild(opts: StaticBuildOptions) {
teardown();
}

return { internals };
// For static builds, the SSR output output won't be needed anymore after page generation.
// We keep track of the names here so we only remove these specific files when finished.
const ssrOutputChunkNames: string[] = [];
for (const output of ssrOutputs) {
for (const chunk of output.output) {
if (chunk.type === 'chunk') {
ssrOutputChunkNames.push(chunk.fileName);
}
}
}

return { internals, ssrOutputChunkNames };
}

export async function staticBuild(opts: StaticBuildOptions, internals: BuildInternals) {
export async function staticBuild(
opts: StaticBuildOptions,
internals: BuildInternals,
ssrOutputChunkNames: string[]
) {
const { settings } = opts;
switch (true) {
case settings.config.output === 'static': {
settings.timer.start('Static generate');
await generatePages(opts, internals);
await cleanServerOutput(opts);
await cleanServerOutput(opts, ssrOutputChunkNames);
settings.timer.end('Static generate');
return;
}
case isServerLikeOutput(settings.config): {
settings.timer.start('Server generate');
await generatePages(opts, internals);
await cleanStaticOutput(opts, internals);
await cleanStaticOutput(opts, internals, ssrOutputChunkNames);
opts.logger.info(null, `\n${bgMagenta(black(' finalizing server assets '))}\n`);
await ssrMoveAssets(opts);
settings.timer.end('Server generate');
Expand Down Expand Up @@ -324,10 +341,10 @@ async function clientBuild(

async function runPostBuildHooks(
container: AstroBuildPluginContainer,
ssrReturn: Awaited<ReturnType<typeof ssrBuild>>,
clientReturn: Awaited<ReturnType<typeof clientBuild>>
ssrOutputs: vite.Rollup.RollupOutput[],
clientOutputs: vite.Rollup.RollupOutput[]
) {
const mutations = await container.runPostHook(ssrReturn, clientReturn);
const mutations = await container.runPostHook(ssrOutputs, clientOutputs);
const config = container.options.settings.config;
const build = container.options.settings.config.build;
for (const [fileName, mutation] of mutations) {
Expand All @@ -347,7 +364,11 @@ async function runPostBuildHooks(
* For each statically prerendered page, replace their SSR file with a noop.
* This allows us to run the SSR build only once, but still remove dependencies for statically rendered routes.
*/
async function cleanStaticOutput(opts: StaticBuildOptions, internals: BuildInternals) {
async function cleanStaticOutput(
opts: StaticBuildOptions,
internals: BuildInternals,
ssrOutputChunkNames: string[]
) {
const allStaticFiles = new Set();
for (const pageData of eachPageData(internals)) {
if (pageData.route.prerender) {
Expand All @@ -361,10 +382,8 @@ async function cleanStaticOutput(opts: StaticBuildOptions, internals: BuildInter
const out = ssr
? opts.settings.config.build.server
: getOutDirWithinCwd(opts.settings.config.outDir);
// The SSR output is all .mjs files, the client output is not.
const files = await glob('**/*.mjs', {
cwd: fileURLToPath(out),
});
// The SSR output chunks for Astro are all .mjs files
const files = ssrOutputChunkNames.filter((f) => f.endsWith('.mjs'));

if (files.length) {
await eslexer.init;
Expand Down Expand Up @@ -394,14 +413,10 @@ async function cleanStaticOutput(opts: StaticBuildOptions, internals: BuildInter
}
}

async function cleanServerOutput(opts: StaticBuildOptions) {
async function cleanServerOutput(opts: StaticBuildOptions, ssrOutputChunkNames: string[]) {
const out = getOutDirWithinCwd(opts.settings.config.outDir);
// The SSR output is all .mjs files, the client output is not.
const files = await glob('**/*.mjs', {
cwd: fileURLToPath(out),
// Important! Also cleanup dotfiles like `node_modules/.pnpm/**`
dot: true,
});
// The SSR output chunks for Astro are all .mjs files
const files = ssrOutputChunkNames.filter((f) => f.endsWith('.mjs'));
if (files.length) {
// Remove all the SSR generated .mjs files
await Promise.all(
Expand Down
14 changes: 14 additions & 0 deletions packages/astro/src/core/build/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Rollup } from 'vite';
import type { AstroConfig } from '../../@types/astro.js';
import type { ViteBuildReturn } from './types.js';

export function getTimeStat(timeStart: number, timeEnd: number) {
const buildTime = timeEnd - timeStart;
Expand Down Expand Up @@ -52,3 +54,15 @@ export function encodeName(name: string): string {

return name;
}

export function viteBuildReturnToRollupOutputs(
viteBuildReturn: ViteBuildReturn
): Rollup.RollupOutput[] {
const result: Rollup.RollupOutput[] = [];
if (Array.isArray(viteBuildReturn)) {
result.push(...viteBuildReturn);
} else if ('output' in viteBuildReturn) {
result.push(viteBuildReturn);
}
return result;
}
7 changes: 7 additions & 0 deletions packages/astro/test/astro-basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@ describe('Astro basics', () => {
expect($('body > :nth-child(5)').prop('outerHTML')).to.equal('<textarea>textarea</textarea>');
});

it('Generates pages that end with .mjs', async () => {
const content1 = await fixture.readFile('/get-static-paths-with-mjs/example.mjs');
expect(content1).to.be.ok;
const content2 = await fixture.readFile('/get-static-paths-with-mjs/example.js');
expect(content2).to.be.ok;
});

describe('preview', () => {
it('returns 200 for valid URLs', async () => {
const result = await fixture.fetch('/');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function getStaticPaths() {
return [
{ params: { file: 'example.mjs' } },
{ params: { file: 'example.js' } },
];
}

export function GET() {
return new Response('console.log("fileContent");')
}
Loading