Skip to content

Commit

Permalink
Preserve generating routes that end with .mjs (#9374)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy authored Dec 8, 2023
1 parent 26f7023 commit 65ddb02
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 39 deletions.
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");')
}

0 comments on commit 65ddb02

Please sign in to comment.