mirror of
https://github.com/withastro/astro.git
synced 2024-12-30 22:03:56 -05:00
fix(astro): static entrypoints build with path with several '.astro' (#10302)
* fix(astro): static entrypoints build with path with several '.astro' * feat: improve replacement logic * fix: logic * chore: improve changeset * chore: move test * Update util.ts * Update .changeset/stale-ducks-protect.md Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev> --------- Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
This commit is contained in:
parent
347d3629b8
commit
992537e79f
5 changed files with 42 additions and 34 deletions
5
.changeset/stale-ducks-protect.md
Normal file
5
.changeset/stale-ducks-protect.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"astro": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes an issue that causes static entrypoints build to fail because of the path in certain conditions. Specifically, it failed if the path had an extension (like `.astro`, `.mdx` etc) and such extension would be also within the path (like `./.astro/index.astro`).
|
|
@ -15,10 +15,8 @@ import {
|
||||||
getPageDataByComponent,
|
getPageDataByComponent,
|
||||||
mergeInlineCss,
|
mergeInlineCss,
|
||||||
} from './internal.js';
|
} from './internal.js';
|
||||||
import {
|
import { ASTRO_PAGE_MODULE_ID, ASTRO_PAGE_RESOLVED_MODULE_ID } from './plugins/plugin-pages.js';
|
||||||
ASTRO_PAGE_RESOLVED_MODULE_ID,
|
import { getVirtualModulePageNameFromPath } from './plugins/util.js';
|
||||||
getVirtualModulePageNameFromPath,
|
|
||||||
} from './plugins/plugin-pages.js';
|
|
||||||
import { RESOLVED_SPLIT_MODULE_ID } from './plugins/plugin-ssr.js';
|
import { RESOLVED_SPLIT_MODULE_ID } from './plugins/plugin-ssr.js';
|
||||||
import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.js';
|
import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.js';
|
||||||
import type { PageBuildData, StaticBuildOptions } from './types.js';
|
import type { PageBuildData, StaticBuildOptions } from './types.js';
|
||||||
|
@ -215,7 +213,7 @@ export class BuildPipeline extends Pipeline {
|
||||||
// The values of the map are the actual `.mjs` files that are generated during the build
|
// The values of the map are the actual `.mjs` files that are generated during the build
|
||||||
|
|
||||||
// Here, we take the component path and transform it in the virtual module name
|
// Here, we take the component path and transform it in the virtual module name
|
||||||
const moduleSpecifier = getVirtualModulePageNameFromPath(path);
|
const moduleSpecifier = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path);
|
||||||
// We retrieve the original JS module
|
// We retrieve the original JS module
|
||||||
const filePath = this.internals.entrySpecifierToBundleMap.get(moduleSpecifier);
|
const filePath = this.internals.entrySpecifierToBundleMap.get(moduleSpecifier);
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { extname } from 'node:path';
|
|
||||||
import type { Plugin as VitePlugin } from 'vite';
|
import type { Plugin as VitePlugin } from 'vite';
|
||||||
import { routeIsRedirect } from '../../redirects/index.js';
|
import { routeIsRedirect } from '../../redirects/index.js';
|
||||||
import { addRollupInput } from '../add-rollup-input.js';
|
import { addRollupInput } from '../add-rollup-input.js';
|
||||||
|
@ -6,29 +5,13 @@ import { type BuildInternals, eachPageFromAllPages } from '../internal.js';
|
||||||
import type { AstroBuildPlugin } from '../plugin.js';
|
import type { AstroBuildPlugin } from '../plugin.js';
|
||||||
import type { StaticBuildOptions } from '../types.js';
|
import type { StaticBuildOptions } from '../types.js';
|
||||||
import { RENDERERS_MODULE_ID } from './plugin-renderers.js';
|
import { RENDERERS_MODULE_ID } from './plugin-renderers.js';
|
||||||
import { ASTRO_PAGE_EXTENSION_POST_PATTERN, getPathFromVirtualModulePageName } from './util.js';
|
import { getPathFromVirtualModulePageName, getVirtualModulePageNameFromPath } from './util.js';
|
||||||
|
|
||||||
export const ASTRO_PAGE_MODULE_ID = '@astro-page:';
|
export const ASTRO_PAGE_MODULE_ID = '@astro-page:';
|
||||||
export const ASTRO_PAGE_RESOLVED_MODULE_ID = '\0' + ASTRO_PAGE_MODULE_ID;
|
export const ASTRO_PAGE_RESOLVED_MODULE_ID = '\0' + ASTRO_PAGE_MODULE_ID;
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. We add a fixed prefix, which is used as virtual module naming convention;
|
|
||||||
* 2. We replace the dot that belongs extension with an arbitrary string.
|
|
||||||
*
|
|
||||||
* @param path
|
|
||||||
*/
|
|
||||||
export function getVirtualModulePageNameFromPath(path: string) {
|
|
||||||
// we mask the extension, so this virtual file
|
|
||||||
// so rollup won't trigger other plugins in the process
|
|
||||||
const extension = extname(path);
|
|
||||||
return `${ASTRO_PAGE_MODULE_ID}${path.replace(
|
|
||||||
extension,
|
|
||||||
extension.replace('.', ASTRO_PAGE_EXTENSION_POST_PATTERN)
|
|
||||||
)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getVirtualModulePageIdFromPath(path: string) {
|
export function getVirtualModulePageIdFromPath(path: string) {
|
||||||
const name = getVirtualModulePageNameFromPath(path);
|
const name = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path);
|
||||||
return '\x00' + name;
|
return '\x00' + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +26,7 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V
|
||||||
if (routeIsRedirect(pageData.route)) {
|
if (routeIsRedirect(pageData.route)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
inputs.add(getVirtualModulePageNameFromPath(path));
|
inputs.add(getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
return addRollupInput(options, Array.from(inputs));
|
return addRollupInput(options, Array.from(inputs));
|
||||||
|
|
|
@ -44,20 +44,20 @@ export function extendManualChunks(outputOptions: OutputOptions, hooks: ExtendMa
|
||||||
export const ASTRO_PAGE_EXTENSION_POST_PATTERN = '@_@';
|
export const ASTRO_PAGE_EXTENSION_POST_PATTERN = '@_@';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1. We add a fixed prefix, which is used as virtual module naming convention;
|
* Prevents Rollup from triggering other plugins in the process by masking the extension (hence the virtual file).
|
||||||
* 2. We replace the dot that belongs extension with an arbitrary string.
|
*
|
||||||
|
* 1. We add a fixed prefix, which is used as virtual module naming convention
|
||||||
|
* 2. If the path has an extension (at the end of the path), we replace the dot that belongs to the extension with an arbitrary string.
|
||||||
*
|
*
|
||||||
* @param virtualModulePrefix
|
* @param virtualModulePrefix
|
||||||
* @param path
|
* @param path
|
||||||
*/
|
*/
|
||||||
export function getVirtualModulePageNameFromPath(virtualModulePrefix: string, path: string) {
|
export function getVirtualModulePageNameFromPath(virtualModulePrefix: string, path: string) {
|
||||||
// we mask the extension, so this virtual file
|
|
||||||
// so rollup won't trigger other plugins in the process
|
|
||||||
const extension = extname(path);
|
const extension = extname(path);
|
||||||
return `${virtualModulePrefix}${path.replace(
|
return virtualModulePrefix +
|
||||||
extension,
|
(extension.startsWith('.')
|
||||||
extension.replace('.', ASTRO_PAGE_EXTENSION_POST_PATTERN)
|
? path.slice(0, -extension.length) + extension.replace('.', ASTRO_PAGE_EXTENSION_POST_PATTERN)
|
||||||
)}`;
|
: path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,14 +3,18 @@ import { before, describe, it } from 'node:test';
|
||||||
import { load as cheerioLoad } from 'cheerio';
|
import { load as cheerioLoad } from 'cheerio';
|
||||||
import testAdapter from './test-adapter.js';
|
import testAdapter from './test-adapter.js';
|
||||||
import { loadFixture } from './test-utils.js';
|
import { loadFixture } from './test-utils.js';
|
||||||
|
import { dirname } from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||||
|
|
||||||
describe('Dynamic pages in SSR', () => {
|
describe('Dynamic pages in SSR', () => {
|
||||||
/** @type {import('./test-utils').Fixture} */
|
/** @type {import('./test-utils').Fixture} */
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
const root = './fixtures/ssr-dynamic/';
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
root: './fixtures/ssr-dynamic/',
|
root,
|
||||||
output: 'server',
|
output: 'server',
|
||||||
integrations: [
|
integrations: [
|
||||||
{
|
{
|
||||||
|
@ -21,6 +25,18 @@ describe('Dynamic pages in SSR', () => {
|
||||||
pattern: '/path-alias/[id]',
|
pattern: '/path-alias/[id]',
|
||||||
entrypoint: './src/pages/api/products/[id].js',
|
entrypoint: './src/pages/api/products/[id].js',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const entrypoint = fileURLToPath(
|
||||||
|
new URL(`${root}.astro/test.astro`, import.meta.url)
|
||||||
|
);
|
||||||
|
console.log(entrypoint)
|
||||||
|
mkdirSync(dirname(entrypoint), { recursive: true });
|
||||||
|
writeFileSync(entrypoint, '<h1>Index</h1>');
|
||||||
|
|
||||||
|
injectRoute({
|
||||||
|
pattern: '/test',
|
||||||
|
entrypoint,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -80,4 +96,10 @@ describe('Dynamic pages in SSR', () => {
|
||||||
const favicon = await matchRoute('/favicon.ico');
|
const favicon = await matchRoute('/favicon.ico');
|
||||||
assert.equal(favicon, undefined);
|
assert.equal(favicon, undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('injectRoute entrypoint should not fail build if containing the extension several times in the path', async () => {
|
||||||
|
const html = await fetchHTML('/test');
|
||||||
|
const $ = cheerioLoad(html);
|
||||||
|
assert.equal($('h1').text(), 'Index');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue