Server polyfills are not user-controllable: no way to opt out of `@angular/platform-server/init` or add server-only polyfills
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- angular, typescript
- Lĩnh vực
- build-system
Hướng nghiên cứu
Start with application-code-bundle.ts at createServerPolyfillBundleOptions and trace how options.polyfills is consumed in options.ts, execute-build.ts, dev-server/vite/index.ts, and browser-esbuild. The issue proposes a normalization step and separate browser and server lists; check the existing normalization patterns and add the server polyfills spec mentioned under “Anything else relevant?”. Done means the object form works while array form preserves current behavior, with tests covering the server bundle.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Command
build, serve
Description
@angular/build:application derives the server polyfills list entirely on its own and offers no option to change it. In createServerPolyfillBundleOptions (application-code-bundle.ts#L164-L184):
zone.js/node(orzone.jsonplatform: 'neutral') is added when the browserpolyfillslist containszone.js,@angular/localize/initis added when the browser list contains it,@angular/platform-server/initis always added.
So the browser polyfills list is fully explicit, and the server polyfills list is fully implicit. Two concrete gaps follow from that:
1. There is no opt-out of the init global patch
@angular/platform-server/init is a side-effectful module whose only job is Object.assign(globalThis, domino.impl) plus globalThis.KeyboardEvent = domino.impl.Event. The framework introduced it as something an app may import before bootstrap for code that touches DOM globals at module-evaluation time (angular/angular#40559). Most apps do not need it: platform-server runs the identical shim itself in DominoAdapter.makeCurrent() → setDomTypes() on every platform init, so for everything that runs after bootstrap the init patch is redundant and is overwritten on the first render anyway.
Since v15 the CLI adds it to every server build with no way to say no. Evidence that people need the opt-out:
- The framework's own SSR benchmarks patch
@angular/buildto strip theplatform-server/initimport frompolyfills.server.mjs(modules/ssr-benchmarks/README.mdin angular/angular), and themain.server.tsthere notes thatɵENABLE_DOM_EMULATION"won't prevent the monkey patching of DOM apis as this is introduced by the CLI". - Anyone running the server bundle outside Node with a real DOM (the benchmark case, or
ENABLE_DOM_EMULATION: false) gets Domino's classes forced ontoglobalThisregardless. - Apps that want to keep
globalThisclean on the server (noHTMLElement,Node,Event, … leaking into third-party code that feature-detects the environment withtypeof window/typeof HTMLElement) have no option either.
Measured on a default ng new --ssr app (details in #34514): the init module costs ~235 kB on disk, ~1.1 MB of retained heap for the life of the process and ~7 ms of startup, while the Object.assign itself is negligible (~7 KB, 0.03 ms). Prerendered and SSR output are byte-identical with and without it.
2. There is nowhere to put a server-only polyfill
The ssr.platform option's own description says "Please note that this feature does not provide polyfills for Node.js modules." With platform: 'neutral' (Cloudflare Workers and similar), users are expected to bring polyfills themselves, yet the only polyfills option feeds the browser bundle. Today a server-only polyfill has to be imported manually at the top of main.server.ts, where it runs after zone.js and init and after any shared chunks.
Describe the solution you'd like
Let polyfills take either the current array or a browser/server object, mirroring the existing outputPath shape (string | { base, browser, server, media }):
"polyfills": ["zone.js"] // today, unchanged
"polyfills": {
"browser": ["zone.js"],
"server": ["zone.js/node", "@angular/platform-server/init"]
}
Semantics:
- Array form keeps today's behaviour exactly:
browser= the array,server= derived as now (zone.js/node, localize,init). Non-breaking; no migration needed. - An explicit
serverlist is the server polyfills list, the same way the browser list already is: the builder adds nothing on top. To drop theinitglobal patch, omit it. To keep today's output, list it. Theng new/ssrschematics can emit the explicit form so new projects see what they get. isZonelessAppis evaluated per list (browser list for the browser bundle, server list for the server bundle), sozone.jsvszone.js/nodeand the async/await support flags fall out naturally.getEsBuildCommonPolyfillsOptionsand thepolyfills.serverbundle are unchanged; only the input list is. Normalization follows the existingnormalizeOptimization/normalizeSourceMapspattern (a smallnormalizePolyfillsinoptions.ts, folding in the string-to-array shim thatbrowser-esbuildstill relies on).- Consumers that read
options.polyfillsand would switch to.browser/.server:application-code-bundle.ts(browser bundle, server bundle,isZonelessAppchecks),execute-build.ts(top-level-await hint),dev-server/vite/index.ts(es2016target), andbrowser-esbuild's string handling.
This solves both gaps with one option and no new concept: server polyfills become as explicit as browser polyfills.
I am happy to implement this and open the PR once the shape is agreed; the single-copy fix in #34516 is independent of it and already covers the duplicate.
Describe alternatives you've considered
A boolean under ssr, next to ssr.platform, which already shapes the server polyfill list (zone.js vs zone.js/node), the createRequire banner and the xhr2 external:
"ssr": { "entry": "src/server.ts", "platform": "node", "domShims": false }
One if around line 184. It only addresses gap 1, and the name needs care so it is not confused with the framework's private ɵENABLE_DOM_EMULATION, which controls the adapter and does not affect the global shims.
Leaving it manual: users who want init could import it in main.server.ts as the v12 schematic did. That would be a breaking change for apps that rely on the implicit import, and it still leaves gap 2.
Not an alternative, but related: the same unconditional init import is also why the server build currently ships two copies of Domino (#34514). That has a bundling-level fix that does not need this option; this request is about control, not about the duplicate.
Anything else relevant?
- No spec or e2e currently asserts anything about
polyfills.server.mjs,zone.js/nodeor@angular/platform-server/init;tests/options/polyfills_spec.tsonly coversdist/browser/polyfills.js. Either solution should add a server polyfills spec. - The webpack server builder only adds
initwhen@angular/platform-serveris installed (isPackageInstalledinwebpack/configs/common.ts); the esbuild path has no equivalent guard. - Repro and measurements: https://github.com/ChristopherPHolder/ng-double-domino
- Ngôn ngữ chính
- TypeScript
- Star
- 27k
- Fork
- 11.8k
- Merge trung bình
- 1 ngày 5 giờ
- Pull request đã merge (30 ngày)
- 276
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của angular/angular-cli
-
Can't use an array of hostnames in --allowedHosts cli parameter in @angular/build:dev-serverĐang mởarea: @angular/build gemini-triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
angular/angular-cli#33955 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area: @angular/cli gemini-triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
angular/angular-cli#33055 · 1 bình luận · 3 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area: @angular/build
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 55/100
angular/angular-cli#34574 · 2 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Angular SSR prerender params allow build-time SSRF, credential leaks, and open redirectsCó thể đã có người làm @SkyZeroZx đã nhận hôm nay. Đang mởarea: @angular/ssr
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
angular/angular-cli#34569 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Tailwind CSS v4 classes in new or moved files are not picked up by ng serve until another rebuildCó thể đã có người làm @MeAkib đã nhận 8 ngày trước. Đang mởarea: @angular/build
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
angular/angular-cli#34446 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của angular/angular-cli
Issue tương tự
-
area:plugins area:security area:skills bug has repro
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
anthropics/claude-code#105911 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
openspec-apply-change skill: when blocked, may select a ready artifact unrelated to missingArtifactsĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Fission-AI/OpenSpec#2165 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
🐞 bug 🧐 unconfirmed
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
Tencent/tdesign-vue-next#7032 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
gnosis/gnosis_vpn#661 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
content-freshness: staleOwnedContent doc comments still say 'complete receipt' (follow-up to #7912)Đang mởtriage:bug-verified
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 92/100
Maintainer thường phản hồi trong vòng 1 ngày