mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
fix custom assetFileNames
issue (#12449)
* fix custom assetFileNames issue * fix error * fix asset name * handle edge cases fo multiple asset dirs * add tests * format * add changeset * improve changeset * add missing files for tests * Update neat-papayas-brake.md improve changeset
This commit is contained in:
parent
350b3da9cf
commit
e6b8017239
7 changed files with 43 additions and 32 deletions
5
.changeset/neat-papayas-brake.md
Normal file
5
.changeset/neat-papayas-brake.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes an issue where the custom `assetFileNames` configuration caused assets to be incorrectly moved to the server directory instead of the client directory, resulting in 404 errors when accessed from the client side.
|
|
@ -211,7 +211,7 @@ class AstroBuilder {
|
||||||
key: keyPromise,
|
key: keyPromise,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { internals, ssrOutputChunkNames, contentFileNames } = await viteBuild(opts);
|
const { internals, ssrOutputChunkNames, ssrOutputAssetNames, contentFileNames } = await viteBuild(opts);
|
||||||
|
|
||||||
const hasServerIslands = this.settings.serverIslandNameMap.size > 0;
|
const hasServerIslands = this.settings.serverIslandNameMap.size > 0;
|
||||||
// Error if there are server islands but no adapter provided.
|
// Error if there are server islands but no adapter provided.
|
||||||
|
@ -219,7 +219,7 @@ class AstroBuilder {
|
||||||
throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands);
|
throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands);
|
||||||
}
|
}
|
||||||
|
|
||||||
await staticBuild(opts, internals, ssrOutputChunkNames, contentFileNames);
|
await staticBuild(opts, internals, ssrOutputChunkNames, ssrOutputAssetNames, contentFileNames);
|
||||||
|
|
||||||
// Write any additionally generated assets to disk.
|
// Write any additionally generated assets to disk.
|
||||||
this.timer.assetsStart = performance.now();
|
this.timer.assetsStart = performance.now();
|
||||||
|
|
|
@ -104,21 +104,26 @@ export async function viteBuild(opts: StaticBuildOptions) {
|
||||||
// For static builds, the SSR output won't be needed anymore after page generation.
|
// For static builds, the SSR 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.
|
// We keep track of the names here so we only remove these specific files when finished.
|
||||||
const ssrOutputChunkNames: string[] = [];
|
const ssrOutputChunkNames: string[] = [];
|
||||||
|
const ssrOutputAssetNames: string[] = [];
|
||||||
for (const output of ssrOutputs) {
|
for (const output of ssrOutputs) {
|
||||||
for (const chunk of output.output) {
|
for (const chunk of output.output) {
|
||||||
if (chunk.type === 'chunk') {
|
if (chunk.type === 'chunk') {
|
||||||
ssrOutputChunkNames.push(chunk.fileName);
|
ssrOutputChunkNames.push(chunk.fileName);
|
||||||
}
|
}
|
||||||
|
if (chunk.type === 'asset') {
|
||||||
|
ssrOutputAssetNames.push(chunk.fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { internals, ssrOutputChunkNames, contentFileNames };
|
return { internals, ssrOutputChunkNames, ssrOutputAssetNames, contentFileNames };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function staticBuild(
|
export async function staticBuild(
|
||||||
opts: StaticBuildOptions,
|
opts: StaticBuildOptions,
|
||||||
internals: BuildInternals,
|
internals: BuildInternals,
|
||||||
ssrOutputChunkNames: string[],
|
ssrOutputChunkNames: string[],
|
||||||
|
ssrOutputAssetNames: string[],
|
||||||
contentFileNames?: string[],
|
contentFileNames?: string[],
|
||||||
) {
|
) {
|
||||||
const { settings } = opts;
|
const { settings } = opts;
|
||||||
|
@ -131,7 +136,7 @@ export async function staticBuild(
|
||||||
settings.timer.start('Server generate');
|
settings.timer.start('Server generate');
|
||||||
await generatePages(opts, internals);
|
await generatePages(opts, internals);
|
||||||
await cleanStaticOutput(opts, internals);
|
await cleanStaticOutput(opts, internals);
|
||||||
await ssrMoveAssets(opts);
|
await ssrMoveAssets(opts, ssrOutputAssetNames);
|
||||||
settings.timer.end('Server generate');
|
settings.timer.end('Server generate');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,33 +417,26 @@ export async function copyFiles(fromFolder: URL, toFolder: URL, includeDotfiles
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ssrMoveAssets(opts: StaticBuildOptions) {
|
async function ssrMoveAssets(opts: StaticBuildOptions, ssrOutputAssetNames: string[]) {
|
||||||
opts.logger.info('build', 'Rearranging server assets...');
|
opts.logger.info('build', 'Rearranging server assets...');
|
||||||
const serverRoot =
|
const serverRoot =
|
||||||
opts.settings.buildOutput === 'static'
|
opts.settings.buildOutput === 'static'
|
||||||
? opts.settings.config.build.client
|
? opts.settings.config.build.client
|
||||||
: opts.settings.config.build.server;
|
: opts.settings.config.build.server;
|
||||||
const clientRoot = opts.settings.config.build.client;
|
const clientRoot = opts.settings.config.build.client;
|
||||||
const assets = opts.settings.config.build.assets;
|
if (ssrOutputAssetNames.length > 0) {
|
||||||
const serverAssets = new URL(`./${assets}/`, appendForwardSlash(serverRoot.toString()));
|
await Promise.all(
|
||||||
const clientAssets = new URL(`./${assets}/`, appendForwardSlash(clientRoot.toString()));
|
ssrOutputAssetNames.map(async function moveAsset(filename) {
|
||||||
const files = await glob(`**/*`, {
|
const currentUrl = new URL(filename, appendForwardSlash(serverRoot.toString()));
|
||||||
cwd: fileURLToPath(serverAssets),
|
const clientUrl = new URL(filename, appendForwardSlash(clientRoot.toString()));
|
||||||
});
|
const dir = new URL(path.parse(clientUrl.href).dir);
|
||||||
|
// It can't find this file because the user defines a custom path
|
||||||
if (files.length > 0) {
|
// that includes the folder paths in `assetFileNames`
|
||||||
await Promise.all(
|
if (!fs.existsSync(dir)) await fs.promises.mkdir(dir, { recursive: true });
|
||||||
files.map(async function moveAsset(filename) {
|
return fs.promises.rename(currentUrl, clientUrl);
|
||||||
const currentUrl = new URL(filename, appendForwardSlash(serverAssets.toString()));
|
}),
|
||||||
const clientUrl = new URL(filename, appendForwardSlash(clientAssets.toString()));
|
);
|
||||||
const dir = new URL(path.parse(clientUrl.href).dir);
|
removeEmptyDirs(fileURLToPath(serverRoot));
|
||||||
// It can't find this file because the user defines a custom path
|
|
||||||
// that includes the folder paths in `assetFileNames
|
|
||||||
if (!fs.existsSync(dir)) await fs.promises.mkdir(dir, { recursive: true });
|
|
||||||
return fs.promises.rename(currentUrl, clientUrl);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
removeEmptyDirs(fileURLToPath(serverAssets));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import assert from 'node:assert/strict';
|
||||||
import { before, describe, it } from 'node:test';
|
import { before, describe, it } from 'node:test';
|
||||||
import { loadFixture } from './test-utils.js';
|
import { loadFixture } from './test-utils.js';
|
||||||
|
|
||||||
describe('custom the assets name function', () => {
|
describe('custom assets name function', () => {
|
||||||
/** @type {import('./test-utils').Fixture} */
|
/** @type {import('./test-utils').Fixture} */
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
|
@ -14,9 +14,15 @@ describe('custom the assets name function', () => {
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('It cant find this file cause the node throws an error if the users custom a path that includes the folder path', async () => {
|
it('should load CSS file from custom client assets path', async () => {
|
||||||
const csslength = await fixture.readFile('client/assets/css/a.css');
|
const files = await fixture.readdir('/client/assets/css');
|
||||||
/** @type {Set<string>} */
|
const cssFile = files.find((file) => file === 'a.css');
|
||||||
assert.equal(!!csslength, true);
|
assert.ok(cssFile, 'Expected CSS file to exist at client/assets/css/a.css');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load image file from custom client assets path', async () => {
|
||||||
|
const files = await fixture.readdir('/client/imgAssets');
|
||||||
|
const imgFile = files.find((file) => file === 'penguin1.jpg');
|
||||||
|
assert.ok(imgFile, 'Expected image file to exist at client/imgAssets/penguin1.jpg');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,14 +18,14 @@ export default defineConfig({
|
||||||
const { ext, dir, base } = path.parse(option.name);
|
const { ext, dir, base } = path.parse(option.name);
|
||||||
|
|
||||||
if (ext == ".css") return path.join(dir, "assets/css", 'a.css');
|
if (ext == ".css") return path.join(dir, "assets/css", 'a.css');
|
||||||
return "assets/img/[name].[ext]";
|
return "imgAssets/[name].[ext]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
assets: 'assets'
|
assets: 'assetsDir'
|
||||||
},
|
},
|
||||||
output: "server",
|
output: "server",
|
||||||
adapter: node({
|
adapter: node({
|
||||||
|
|
BIN
packages/astro/test/fixtures/custom-assets-name/src/images/penguin1.jpg
vendored
Normal file
BIN
packages/astro/test/fixtures/custom-assets-name/src/images/penguin1.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
const title = 'My App';
|
const title = 'My App';
|
||||||
|
import p1Url from '../images/penguin1.jpg';
|
||||||
---
|
---
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
@ -8,6 +9,7 @@ const title = 'My App';
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>{title}</h1>
|
<h1>{title}</h1>
|
||||||
|
<img src={p1Url.src}/>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue