Skip to content

fix(@angular-devkit/build-angular): normalize asset source locations in Vite-based development server #26556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export async function* serveWithVite(
assetFiles.clear();
if (result.assetFiles) {
for (const asset of result.assetFiles) {
assetFiles.set('/' + normalizePath(asset.destination), asset.source);
assetFiles.set('/' + normalizePath(asset.destination), normalizePath(asset.source));
}
}

Expand Down
59 changes: 59 additions & 0 deletions tests/legacy-cli/e2e/tests/commands/serve/assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import assert from 'node:assert';
import { randomUUID } from 'node:crypto';
import { mkdir, rm, writeFile } from 'node:fs/promises';
import { ngServe, updateJsonFile } from '../../../utils/project';
import { getGlobalVariable } from '../../../utils/env';

export default async function () {
const outsideDirectoryName = `../outside-${randomUUID()}`;

await updateJsonFile('angular.json', (json) => {
json.projects['test-project'].architect.build.options.assets = [
'src/favicon.ico',
'src/assets',
// Ensure assets located outside the workspace root work with the dev server
{ 'input': outsideDirectoryName, 'glob': '**/*', 'output': './outside' },
];
});

await mkdir(outsideDirectoryName);
try {
await writeFile(`${outsideDirectoryName}/some-asset.xyz`, 'XYZ');

const port = await ngServe();

let response = await fetch(`http://localhost:${port}/favicon.ico`);
assert.strictEqual(response.status, 200, 'favicon.ico response should be ok');

response = await fetch(`http://localhost:${port}/outside/some-asset.xyz`);
assert.strictEqual(response.status, 200, 'outside/some-asset.xyz response should be ok');
assert.strictEqual(await response.text(), 'XYZ', 'outside/some-asset.xyz content is wrong');

// A non-existent HTML file request with accept header should fallback to the index HTML
response = await fetch(`http://localhost:${port}/does-not-exist.html`, {
headers: { accept: 'text/html' },
});
assert.strictEqual(
response.status,
200,
'non-existent file response should fallback and be ok',
);
assert.match(
await response.text(),
/<app-root/,
'non-existent file response should fallback and contain html',
);

// Vite will incorrectly fallback in all non-existent cases so skip last test case
// TODO: Remove conditional when Vite handles this case
if (getGlobalVariable('argv')['esbuild']) {
return;
}

// A non-existent file without an html accept header should not be found.
response = await fetch(`http://localhost:${port}/does-not-exist.png`);
assert.strictEqual(response.status, 404, 'non-existent file response should be not found');
} finally {
await rm(outsideDirectoryName, { force: true, recursive: true });
}
}