voidzero-dev / voidzero-dev/oxc-angular-compiler
fix(defer): emit lazy dependencies for components used only inside @defer blocks
还没有人认领这个 Issue。
- 主要语言
- Rust
- 星标
- 228
- 派生
- 20
- 平均合并
- 1 天 15 小时
- 30 天内合并 PR
- 36
描述
Summary
Angular's @defer block is supposed to lazy-load any standalone component that appears only inside it — the user gets import().then(m => m.X) instead of an eager import at the top of the file. OXC currently emits these references through the regular dependencies factory, so @defer parses correctly but does not actually defer: the deferred component lands in the initial bundle and the lazy boundary is lost.
This is the default ngc behavior and is not opt-in via @Component.deferredImports — the recent bb2735b commit added the explicit-deferredImports path but the implicit detection is still missing.
Reference behavior
ngc at packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts:2344-2475 (collectDeferredSymbols / surrounding logic):
- Walks the component's template AST and collects every standalone import (
scope.directives,scope.pipes). - For each import, checks whether all references appear inside
DeferredBlocknodes — if so, the import is added toallDeferredDecls. - Routes those imports through
DeferBlockDepsEmitMode.PerComponent(orPerBlockfor fine-grained mode), producing lazyimport().then(...)resolvers instead of regular dependency entries. - The normal
dependenciesfactory is built from the non-deferred imports only.
Test that demonstrates the gap (in napi/angular-compiler/test/analog-compat/component.spec.ts:3262):
import { Component } from '@angular/core';
import { LazyCmp } from './lazy';
@Component({
selector: 'app-parent',
imports: [LazyCmp],
template: '@defer { <app-lazy/> }',
})
export class Parent {}
Expected output (matching ngc):
ɵcmp = ɵɵdefineComponent({
...,
dependencies: ɵɵgetComponentDepsFactory(Parent, []),
deferBlockDependencies: [() => import('./lazy').then(m => m.LazyCmp)],
});
Current OXC output:
ɵcmp = ɵɵdefineComponent({
...,
dependencies: ɵɵgetComponentDepsFactory(Parent, [LazyCmp]), // eager
});
Required work
- Defer-only detection — extend the existing template walk in
crates/oxc_angular_compiler/src/component/defer_resolver.rsto flag eachimports: [...]entry that is referenced only insideDeferredBlockAST nodes. - Route to lazy emit — currently
defer_resolver.rsonly handles@Component.deferredImports. Generalize it to also accept implicitly-deferred imports from step 1. - Emit
deferBlockDependencies— wire the lazyimport().then(m => m.X)resolver into thedefineComponentemit. Use original export name (not local alias) — seenapi/angular-compiler/test/analog-compat/component.spec.ts:3284for the aliased-import case. - Default-import shape —
m.defaultrather thanm.Xfor default-imported components — covered bynapi/angular-compiler/test/analog-compat/component.spec.ts:3312.
Tests
The four currently-failing tests under @defer dependency import shape in component.spec.ts (3262, 3284, 3312, plus the @defer inside @switch/@case cases at 1764-area) cover the matrix.
Reference
- ngc impl:
packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts:1312(DeferBlockDepsEmitMode.PerComponent),:2344-2475(allDeferredDeclscollection) - DefersBlock AST:
packages/compiler/src/render3/r3_ast.ts - OXC defer entry:
crates/oxc_angular_compiler/src/component/defer_resolver.rs(added in #307) - Related upstream commit:
bb2735b feat(defer): emit lazy resolver and async metadata for @Component.deferredImports (#307)— explicit-deferredImports path; this issue covers the implicit case
贡献指南
这个仓库没有索引到贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 crates/oxc_angular_compiler/src/component/defer_resolver.rs 开始,将其现有的 explicit-deferredImports 处理与 handler.ts:2344-2475 中 ngc 的 collectDeferredSymbols 逻辑进行比较。运行 napi/angular-compiler/test/analog-compat/component.spec.ts 中 @defer 依赖导入形式的测试用例,包括别名、default-import 和嵌套 @switch 的用例。完成的标准是:仅用于 defer 的导入会生成具有正确 lazy export 形式的 deferBlockDependencies,而常规依赖会排除它们。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- angular, rust, typescript
- 领域
- compilers, frontend, testing-qa
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 冷清
- 描述清晰度
- 描述清楚
- 新手友好度
- 56/100