Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): serve assets from the provided `s…
Browse files Browse the repository at this point in the history
…erve-path`

When the `serve-path` option is used assets are now correctly servered from this location.

Closes #26509

(cherry picked from commit 150a2e7)
  • Loading branch information
alan-agius4 committed Nov 28, 2023
1 parent 27e7c2e commit 7455fdc
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 13 deletions.
Expand Up @@ -18,7 +18,9 @@ describeServeBuilder(
(harness, setupTarget, isViteRun) => {
describe('option: "servePath"', () => {
beforeEach(async () => {
setupTarget(harness);
setupTarget(harness, {
assets: ['src/assets'],
});

// Application code is not needed for these tests
await harness.writeFile('src/main.ts', 'console.log("foo");');
Expand Down Expand Up @@ -96,6 +98,23 @@ describeServeBuilder(
expect(result?.success).toBeTrue();
expect(await response?.text()).toContain('<title>');
});

it('serves assets at specified path when option is used', async () => {
await harness.writeFile('src/assets/test.txt', 'hello world!');

harness.useTarget('serve', {
...BASE_OPTIONS,
servePath: 'test',
});

const { result, response } = await executeOnceAndFetch(harness, '/test/assets/test.txt', {
// fallback processing requires an accept header
request: { headers: { accept: 'text/html' } },
});

expect(result?.success).toBeTrue();
expect(await response?.text()).toContain('hello world');
});
});
},
);
Expand Up @@ -439,6 +439,7 @@ export async function setupServer(
css: {
devSourcemap: true,
},
// Vite will normalize the `base` option by adding a leading and trailing forward slash.
base: serverOptions.servePath,
resolve: {
mainFields: ['es2020', 'browser', 'module', 'main'],
Expand Down Expand Up @@ -568,15 +569,15 @@ export async function setupServer(

// Parse the incoming request.
// The base of the URL is unused but required to parse the URL.
const pathname = pathnameWithoutServePath(req.url, serverOptions);
const pathname = pathnameWithoutBasePath(req.url, server.config.base);
const extension = extname(pathname);

// Rewrite all build assets to a vite raw fs URL
const assetSourcePath = assets.get(pathname);
if (assetSourcePath !== undefined) {
// The encoding needs to match what happens in the vite static middleware.
// ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
req.url = `/@fs/${encodeURI(assetSourcePath)}`;
req.url = `${server.config.base}@fs/${encodeURI(assetSourcePath)}`;
next();

return;
Expand Down Expand Up @@ -674,7 +675,7 @@ export async function setupServer(

// Parse the incoming request.
// The base of the URL is unused but required to parse the URL.
const pathname = pathnameWithoutServePath(req.url, serverOptions);
const pathname = pathnameWithoutBasePath(req.url, server.config.base);

if (pathname === '/' || pathname === `/index.html`) {
const rawHtml = outputFiles.get('/index.html')?.contents;
Expand Down Expand Up @@ -785,17 +786,14 @@ async function loadViteClientCode(file: string) {
return contents;
}

function pathnameWithoutServePath(url: string, serverOptions: NormalizedDevServerOptions): string {
function pathnameWithoutBasePath(url: string, basePath: string): string {
const parsedUrl = new URL(url, 'http://localhost');
let pathname = decodeURIComponent(parsedUrl.pathname);
if (serverOptions.servePath && pathname.startsWith(serverOptions.servePath)) {
pathname = pathname.slice(serverOptions.servePath.length);
if (pathname[0] !== '/') {
pathname = '/' + pathname;
}
}
const pathname = decodeURIComponent(parsedUrl.pathname);

return pathname;
// slice(basePath.length - 1) to retain the trailing slash
return basePath !== '/' && pathname.startsWith(basePath)
? pathname.slice(basePath.length - 1)
: pathname;
}

type ViteEsBuildPlugin = NonNullable<
Expand Down

0 comments on commit 7455fdc

Please sign in to comment.