0
Fork 0
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:
Florian Lefebvre 2024-03-04 17:48:01 +01:00 committed by GitHub
parent 347d3629b8
commit 992537e79f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 42 additions and 34 deletions

View 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`).

View file

@ -15,10 +15,8 @@ import {
getPageDataByComponent,
mergeInlineCss,
} from './internal.js';
import {
ASTRO_PAGE_RESOLVED_MODULE_ID,
getVirtualModulePageNameFromPath,
} from './plugins/plugin-pages.js';
import { ASTRO_PAGE_MODULE_ID, ASTRO_PAGE_RESOLVED_MODULE_ID } from './plugins/plugin-pages.js';
import { getVirtualModulePageNameFromPath } from './plugins/util.js';
import { RESOLVED_SPLIT_MODULE_ID } from './plugins/plugin-ssr.js';
import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.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
// 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
const filePath = this.internals.entrySpecifierToBundleMap.get(moduleSpecifier);
if (filePath) {

View file

@ -1,4 +1,3 @@
import { extname } from 'node:path';
import type { Plugin as VitePlugin } from 'vite';
import { routeIsRedirect } from '../../redirects/index.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 { StaticBuildOptions } from '../types.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_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) {
const name = getVirtualModulePageNameFromPath(path);
const name = getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path);
return '\x00' + name;
}
@ -43,7 +26,7 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V
if (routeIsRedirect(pageData.route)) {
continue;
}
inputs.add(getVirtualModulePageNameFromPath(path));
inputs.add(getVirtualModulePageNameFromPath(ASTRO_PAGE_MODULE_ID, path));
}
return addRollupInput(options, Array.from(inputs));

View file

@ -44,20 +44,20 @@ export function extendManualChunks(outputOptions: OutputOptions, hooks: ExtendMa
export const ASTRO_PAGE_EXTENSION_POST_PATTERN = '@_@';
/**
* 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.
* Prevents Rollup from triggering other plugins in the process by masking the extension (hence the virtual file).
*
* 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 path
*/
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);
return `${virtualModulePrefix}${path.replace(
extension,
extension.replace('.', ASTRO_PAGE_EXTENSION_POST_PATTERN)
)}`;
return virtualModulePrefix +
(extension.startsWith('.')
? path.slice(0, -extension.length) + extension.replace('.', ASTRO_PAGE_EXTENSION_POST_PATTERN)
: path);
}
/**

View file

@ -3,14 +3,18 @@ import { before, describe, it } from 'node:test';
import { load as cheerioLoad } from 'cheerio';
import testAdapter from './test-adapter.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', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
before(async () => {
const root = './fixtures/ssr-dynamic/';
fixture = await loadFixture({
root: './fixtures/ssr-dynamic/',
root,
output: 'server',
integrations: [
{
@ -21,6 +25,18 @@ describe('Dynamic pages in SSR', () => {
pattern: '/path-alias/[id]',
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');
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');
});
});