summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/chatty-peas-warn.md5
-rw-r--r--packages/astro/src/core/build/generate.ts8
-rw-r--r--packages/astro/src/core/path.ts8
-rw-r--r--packages/astro/src/vite-plugin-astro-server/index.ts18
-rw-r--r--packages/astro/test/static-build.test.js15
5 files changed, 51 insertions, 3 deletions
diff --git a/.changeset/chatty-peas-warn.md b/.changeset/chatty-peas-warn.md
new file mode 100644
index 000000000..bda91dda0
--- /dev/null
+++ b/.changeset/chatty-peas-warn.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Adds subpath to assets/scripts when statically generating
diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts
index 36c25546c..4bac5ae29 100644
--- a/packages/astro/src/core/build/generate.ts
+++ b/packages/astro/src/core/build/generate.ts
@@ -11,7 +11,7 @@ import type {
} from '../../@types/astro';
import type { BuildInternals } from '../../core/build/internal.js';
import { debug, info } from '../logger/core.js';
-import { prependForwardSlash, removeLeadingForwardSlash } from '../../core/path.js';
+import { joinPaths, prependForwardSlash, removeLeadingForwardSlash } from '../../core/path.js';
import type { RenderOptions } from '../../core/render/core';
import { BEFORE_HYDRATION_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
import { call as callEndpoint } from '../endpoint/index.js';
@@ -176,7 +176,11 @@ async function generatePath(
debug('build', `Generating: ${pathname}`);
- const site = astroConfig.site;
+ // If a base path was provided, append it to the site URL. This ensures that
+ // all injected scripts and links are referenced relative to the site and subpath.
+ const site = astroConfig.base && astroConfig.base !== './'
+ ? joinPaths(astroConfig.site?.toString() || 'http://localhost/', astroConfig.base)
+ : astroConfig.site;
const links = createLinkStylesheetElementSet(linkIds.reverse(), site);
const scripts = createModuleScriptElementWithSrcSet(hoistedId ? [hoistedId] : [], site);
diff --git a/packages/astro/src/core/path.ts b/packages/astro/src/core/path.ts
index 177723177..e499c8c5a 100644
--- a/packages/astro/src/core/path.ts
+++ b/packages/astro/src/core/path.ts
@@ -38,3 +38,11 @@ export function startsWithDotSlash(path: string) {
export function isRelativePath(path: string) {
return startsWithDotDotSlash(path) || startsWithDotSlash(path);
}
+
+function isString(path: unknown): path is string {
+ return typeof path === 'string' || path instanceof String;
+}
+
+export function joinPaths(...paths: (string | undefined)[]) {
+ return paths.filter(isString).map(trimSlashes).join('/');
+} \ No newline at end of file
diff --git a/packages/astro/src/vite-plugin-astro-server/index.ts b/packages/astro/src/vite-plugin-astro-server/index.ts
index 485f16282..3d8529fee 100644
--- a/packages/astro/src/vite-plugin-astro-server/index.ts
+++ b/packages/astro/src/vite-plugin-astro-server/index.ts
@@ -111,6 +111,24 @@ async function handle404Response(
if (pathname === '/' && !pathname.startsWith(devRoot)) {
html = subpathNotUsedTemplate(devRoot, pathname);
} else {
+ // HACK: redirect without the base path for assets in publicDir
+ const redirectTo =
+ req.method === 'GET'
+ && config.base && config.base !== './'
+ && pathname.startsWith(config.base)
+ && pathname.replace(config.base, '/');
+
+ if (redirectTo && redirectTo !== '/') {
+ const response = new Response(null, {
+ status: 302,
+ headers: {
+ Location: redirectTo,
+ },
+ });
+ await writeWebResponse(res, response);
+ return;
+ }
+
html = notFoundTemplate({
statusCode: 404,
title: 'Not found',
diff --git a/packages/astro/test/static-build.test.js b/packages/astro/test/static-build.test.js
index 3ed593ace..b2c9d9d47 100644
--- a/packages/astro/test/static-build.test.js
+++ b/packages/astro/test/static-build.test.js
@@ -6,6 +6,11 @@ function addLeadingSlash(path) {
return path.startsWith('/') ? path : '/' + path;
}
+function removeBasePath(path) {
+ // `/subpath` is defined in the test fixture's Astro config
+ return path.replace('/subpath', '')
+}
+
/**
* @typedef {import('../src/core/logger/core').LogMessage} LogMessage
*/
@@ -90,7 +95,15 @@ describe('Static build', () => {
const links = $('link[rel=stylesheet]');
for (const link of links) {
const href = $(link).attr('href');
- const data = await fixture.readFile(addLeadingSlash(href));
+
+ /**
+ * The link should be built with the config's `base` included
+ * as a subpath.
+ *
+ * The test needs to verify that the file will be found once the `/dist`
+ * output is deployed to a subpath in production by ignoring the subpath here.
+ */
+ const data = await fixture.readFile(removeBasePath(addLeadingSlash(href)));
if (expected.test(data)) {
return true;
}