0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

Handle builds with outDir outside of cwd (#4736)

This commit is contained in:
Bjorn Lu 2022-09-14 21:24:35 +08:00 committed by GitHub
parent a36d51d433
commit 13ca686ea1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 5 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Handle builds with outDir outside of current working directory

View file

@ -1,8 +1,10 @@
import npath from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
import type { AstroConfig, RouteType } from '../../@types/astro';
import { appendForwardSlash } from '../../core/path.js';
const STATUS_CODE_PAGES = new Set(['/404', '/500']);
const FALLBACK_OUT_DIR_NAME = './.astro/';
function getOutRoot(astroConfig: AstroConfig): URL {
return new URL('./', astroConfig.outDir);
@ -59,3 +61,16 @@ export function getOutFile(
}
}
}
/**
* Ensures the `outDir` is within `process.cwd()`. If not it will fallback to `<cwd>/.astro`.
* This is used for static `ssrBuild` so the output can access node_modules when we import
* the output files. A hardcoded fallback dir is fine as it would be cleaned up after build.
*/
export function getOutDirWithinCwd(outDir: URL): URL {
if (fileURLToPath(outDir).startsWith(process.cwd())) {
return outDir;
} else {
return new URL(FALLBACK_OUT_DIR_NAME, pathToFileURL(process.cwd() + npath.sep));
}
}

View file

@ -28,7 +28,7 @@ import { createLinkStylesheetElementSet, createModuleScriptsSet } from '../rende
import { createRequest } from '../request.js';
import { matchRoute } from '../routing/match.js';
import { getOutputFilename } from '../util.js';
import { getOutFile, getOutFolder } from './common.js';
import { getOutDirWithinCwd, getOutFile, getOutFolder } from './common.js';
import { eachPageData, getPageDataByComponent, sortedCSS } from './internal.js';
import type { PageBuildData, SingleFileBuiltModule, StaticBuildOptions } from './types';
import { getTimeStat } from './util.js';
@ -103,7 +103,7 @@ export async function generatePages(opts: StaticBuildOptions, internals: BuildIn
const ssr = opts.astroConfig.output === 'server';
const serverEntry = opts.buildConfig.serverEntry;
const outFolder = ssr ? opts.buildConfig.server : opts.astroConfig.outDir;
const outFolder = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.astroConfig.outDir);
const ssrEntryURL = new URL('./' + serverEntry + `?time=${Date.now()}`, outFolder);
const ssrEntry = await import(ssrEntryURL.toString());
const builtPaths = new Set<string>();

View file

@ -10,6 +10,7 @@ import { runHookBuildSetup } from '../../integrations/index.js';
import { PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
import type { ViteConfigWithSSR } from '../create-vite';
import { info } from '../logger/core.js';
import { getOutDirWithinCwd } from './common.js';
import { generatePages } from './generate.js';
import { trackPageData } from './internal.js';
import type { PageBuildData, StaticBuildOptions } from './types';
@ -110,7 +111,7 @@ Learn more: https://docs.astro.build/en/guides/server-side-rendering/
async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, input: Set<string>) {
const { astroConfig, viteConfig } = opts;
const ssr = astroConfig.output === 'server';
const out = ssr ? opts.buildConfig.server : astroConfig.outDir;
const out = ssr ? opts.buildConfig.server : getOutDirWithinCwd(astroConfig.outDir);
const viteBuildConfig: ViteConfigWithSSR = {
...viteConfig,
@ -245,13 +246,19 @@ async function clientBuild(
}
async function cleanSsrOutput(opts: StaticBuildOptions) {
const out = getOutDirWithinCwd(opts.astroConfig.outDir);
// Clean out directly if the outDir is outside of root
if (out.toString() !== opts.astroConfig.outDir.toString()) {
await fs.promises.rm(out, { recursive: true });
return;
}
// The SSR output is all .mjs files, the client output is not.
const files = await glob('**/*.mjs', {
cwd: fileURLToPath(opts.astroConfig.outDir),
cwd: fileURLToPath(out),
});
await Promise.all(
files.map(async (filename) => {
const url = new URL(filename, opts.astroConfig.outDir);
const url = new URL(filename, out);
await fs.promises.rm(url);
})
);