Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

@angular/build: lazy routes get no SSR modulepreload hints when the app's tsconfig is not at the workspace root (ɵentryName relative to basePath, chunk map relative to workspace root)

未关闭
#34,369 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
25/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
typescript
领域
build-system

调研方向

The mismatch sits between packages/angular/build/src/tools/angular/transformers/lazy-routes-transformer.ts (around line 151, where ɵentryName is made relative to basePath) and packages/angular/build/src/utils/server-rendering/manifest.ts (around line 262, where entryPointToBrowserMapping is keyed by esbuild's entryPoint, relative to absWorkingDir). Reproduce with the issue's steps, where the tsconfig sits in projects/site/, and confirm that preload is empty in angular-app-manifest.mjs. Done means both sides use the same base, so routes get modulepreload hints regardless of tsconfig location, and the existing workspace-root case still passes its tests.

由索引模型根据 Issue 内容生成。

描述

area: @angular/build
Command

build

Is this a regression?
  • Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was

No response

Description

When an application's tsconfig.app.json is not at the workspace root, SSR adds no <link rel="modulepreload"> for any lazy route. That includes the CLI's own multi-project layout (ng generate application puts it in projects/<name>/) and every Nx workspace. The routes are written in the shape lazyRoutesTransformer recognises, and the pages render correctly. Only the hints are missing, and nothing warns about it.

Cause. The two sides of the lookup use different base directories:

  • lazyRoutesTransformer stamps ɵentryName as a path relative to compilerOptions.basePath (lazy-routes-transformer.ts#L151). The compiler sets basePath to the directory of the tsconfig, here projects/site.
  • generateLazyLoadedFilesMappings keys entryPointToBrowserMapping by esbuild's entryPoint (manifest.ts#L262). That path is relative to absWorkingDir, which is the workspace root (application-code-bundle.ts#L631).

So the stamp reads src/app/home/home.ts and the key reads projects/site/src/app/home/home.ts. appendPreloadToMetadata finds nothing and every route's preload stays empty. When the tsconfig is at the workspace root, as in a default ng new, the two bases happen to coincide, which is probably why this has gone unnoticed.

projects/site/tsconfig.app.json ɵentryName in the server bundle preload in angular-app-manifest.mjs route hints in index.html / pricing/index.html
as generated src/app/home/home.ts none 0 / 0
"angularCompilerOptions": { "basePath": "." } added projects/site/src/app/home/home.ts on both routes 1 / 1 (the route's own chunk)

Workaround. "angularCompilerOptions": { "basePath": "." } in the app's tsconfig. It works only because the value is read raw and resolved against the process cwd, and the build happens to run from the workspace root.

Expected. Route hints do not depend on where the tsconfig lives. One option is for the transformer to stamp paths relative to the workspace root, which the builder already knows, instead of relative to basePath.

Real-world impact. In our Nx workspace (22 lazy routes, @nx/angular:application, which delegates to buildApplication unchanged), no route had ever received a hint. With the workaround every route does. On the home page, the shell route's chunk finishes 5.8 s earlier in throttled Lighthouse runs (mobile, devtools throttling, 8× CPU, 5 runs), and TTI drops by 1.3 s.

Minimal Reproduction
npx -p @angular/[email protected] ng new ws --create-application=false --skip-git --package-manager=npm --defaults --ai-config=none
cd ws
npx ng generate application site --ssr --routing --style=css --skip-tests --defaults

projects/site/src/app/app.routes.ts

import { Routes } from '@angular/router';

export const routes: Routes = [
  { path: '', loadComponent: () => import('./home/home').then((m) => m.Home) },
  {
    path: 'pricing',
    loadComponent: () => import('./pricing/pricing').then((m) => m.Pricing),
  },
];

projects/site/src/app/home/home.ts (and pricing/pricing.ts, the same with Pricing)

import { Component } from '@angular/core';

@Component({ selector: 'app-home', template: '<h1>Home</h1>' })
export class Home {}
npx ng build site
grep -c '"preload"' dist/site/server/angular-app-manifest.mjs                    # 0
grep -o '<link rel="modulepreload"[^>]*>' dist/site/browser/index.html           # only the shared initial chunk
grep -rhoE 'entryName:"[^"]*"' dist/site/server/*.mjs                           # src/app/home/home.ts, src/app/pricing/pricing.ts

Then add "angularCompilerOptions": { "basePath": "." } to projects/site/tsconfig.app.json and build again. Both routes get preload, each page gets its own chunk's hint, and the stamps become projects/site/src/app/….

Exception or Error
None. The build succeeds and the pages render; only the lazy-route modulepreload hints are missing.
Your Environment
Angular CLI       : 22.2.3
Angular           : 22.2.3
Node.js           : 24.20.0
Package Manager   : npm 11.19.0
Operating System  : darwin arm64

@angular/build            22.2.3
@angular/cli              22.2.3
@angular/common           22.2.3
@angular/compiler         22.2.3
@angular/compiler-cli     22.2.3
@angular/core             22.2.3
@angular/platform-browser 22.2.3
@angular/platform-server  22.2.3
@angular/router           22.2.3
@angular/ssr              22.2.3
typescript                6.0.3
Anything else relevant?

Also observed on 22.2.1, in our Nx workspace. The transformer's relative(basePath, …) is unchanged since it was introduced in 8d7a51dfc ("feat(@angular/ssr): add modulepreload for lazy-loaded routes").

主要语言
TypeScript
星标
27k
派生
11.8k
平均合并
1 天 3 小时
30 天内合并 PR
193

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

angular/angular-cli 的其他 Issue

查看 angular/angular-cli 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。