dce-edge
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDCE + Edge
DCE + Edge
Use this skill when changing conditional paths, Node-only imports, or edge/runtime branching.
require()当你需要修改条件式路径、仅Node.js可用的导入,或Edge/运行时分支逻辑时,可以参考本技能。
require()DCE-Safe require()
Pattern
require()DCE安全的require()
模式
require()Webpack only DCEs a when it sits inside the dead branch of an whose condition DefinePlugin can evaluate at compile time.
require()if/elsets
// CORRECT - webpack can eliminate the dead branch
if (process.env.__NEXT_USE_NODE_STREAMS) {
require('node:stream')
} else {
// web path
}What does NOT work:
- Early-return/throw guards: webpack doesn't do control-flow analysis for throws/returns, so the is still traced.
require() - Bare without
if: works for inlineelsespecifiers but NOT fornode:*that pulls a new file into the module graph.require('./some-module')
Always test edge changes with on (has edge routes), not with which skips the full webpack compilation.
pnpm test-start-webpacktest/e2e/app-dir/app/standalone.test.tsNEXT_SKIP_ISOLATE=1Webpack仅会对位于if/else分支中、且条件可被DefinePlugin在编译时求值的死分支内的进行死代码消除(DCE)。
require()ts
// CORRECT - webpack can eliminate the dead branch
if (process.env.__NEXT_USE_NODE_STREAMS) {
require('node:stream')
} else {
// web path
}以下写法无效:
- 提前返回/抛出异常的保护逻辑:webpack不会对抛出/返回语句进行控制流分析,因此仍会被追踪到。
require() - 无else分支的单独if语句:对于内联的标识符有效,但对于会将新文件拉入模块图的
node:*无效。require('./some-module')
测试Edge相关修改时,请始终使用运行(包含Edge路由),不要使用,因为它会跳过完整的webpack编译流程。
pnpm test-start-webpacktest/e2e/app-dir/app/standalone.test.tsNEXT_SKIP_ISOLATE=1TypeScript + DCE Interaction
TypeScript与DCE的交互
Use (not two independent blocks) when assigning a variable conditionally on . TypeScript cannot prove exhaustiveness across and will error with "variable used before being assigned". The pattern satisfies both TypeScript (definite assignment) and webpack DCE.
if/elseifprocess.env.Xif (flag) { x = a }; if (!flag) { x = b }if/else当根据条件为变量赋值时,请使用if/else(而非两个独立的if块)。TypeScript无法在这种写法中证明赋值的穷尽性,会抛出“变量在赋值前被使用”的错误。if/else模式既能满足TypeScript的确定赋值要求,又能适配webpack的DCE机制。
process.env.Xif (flag) { x = a }; if (!flag) { x = b }Compile-Time Switcher Pattern
编译时切换器模式
Platform-specific code (node vs web) can use a single switcher module that conditionally s either or into a typed variable, then re-exports the shared runtime API as named exports. Keep the branch as so DefinePlugin can dead-code-eliminate the unused . Keep shared types canonical in , with importing them via and the switcher re-exporting types as needed. Examples: and .
.tsrequire().node.ts.web.tsif/elserequire().node.ts.web.tsimport typestream-ops.tsdebug-channel-server.ts针对平台特定的代码(Node.js vs Web),可以使用单个.ts切换器模块,通过条件式将或导入到一个类型化变量中,然后将共享的运行时API作为命名导出重新导出。请保持分支为if/else结构,以便DefinePlugin可以对未使用的进行死代码消除。将共享类型定义在中作为标准版本,通过导入这些类型,切换器模块按需重新导出类型。示例:和。
require().node.ts.web.tsrequire().node.ts.web.tsimport typestream-ops.tsdebug-channel-server.tsNEXT_RUNTIME
Is Not a Feature Flag
NEXT_RUNTIMENEXT_RUNTIME
并非功能标志
NEXT_RUNTIMEIn user-project webpack server compilers, is inlined to . Guarding Node-only paths with does not prune anything. For feature-gated codepaths, guard on the real feature define (e.g. ).
process.env.NEXT_RUNTIME'nodejs'require('node:*')NEXT_RUNTIME === 'nodejs'process.env.__NEXT_USE_NODE_STREAMS在用户项目的webpack服务端编译器中,会被内联为。使用来保护仅Node.js可用的路径不会剔除任何代码。对于功能 gated 的代码路径,请使用真实的功能定义(如)作为判断条件。
process.env.NEXT_RUNTIME'nodejs'NEXT_RUNTIME === 'nodejs'require('node:*')process.env.__NEXT_USE_NODE_STREAMSEdge Runtime Constraints
Edge运行时约束
Edge routes do NOT use pre-compiled runtime bundles. They are compiled by the user's webpack/Turbopack, so controls DCE. Feature flags that gate imports must be forced to for edge builds in (), otherwise webpack will try to resolve etc. and fail.
define-env.tsnode:*falsedefine-env.tsisEdgeServer ? false : flagValuenode:streamEdge路由不使用预编译的运行时包,它们由用户的webpack/Turbopack编译,因此控制着DCE流程。用于限制导入的功能标志必须在中强制设为false以适配Edge构建(写法如),否则webpack会尝试解析等模块并失败。
define-env.tsnode:*define-env.tsisEdgeServer ? false : flagValuenode:streamapp-page.ts
Template Gotchas
app-page.tsapp-page.ts
模板注意事项
app-page.ts- is a build template compiled by the user's bundler. Any
app-page.tsin this file is traced by webpack/turbopack atrequire()time. You cannot require internal modules with relative paths because they won't be resolvable from the user's project. Instead, export new helpers fromnext buildand access them viaentry-base.tsin the template.entryBase.* - Template helpers should stay out of . If
RenderResultneeds a Node-stream-only utility, prefer a small dedicated helper module inapp-page.ts(with DCE-safeserver/stream-utils/+if/else).require()
- 是一个由用户打包工具编译的构建模板。该文件中的任何
app-page.ts都会在require()时被webpack/turbopack追踪。你不能使用相对路径导入内部模块,因为这些模块在用户项目中无法被解析。相反,请从next build导出新的工具函数,并在模板中通过entry-base.ts访问它们。entryBase.* - 模板工具函数应避免出现在中。如果
RenderResult需要仅Node.js流可用的工具,请优先使用app-page.ts中的小型专用工具模块(配合DCE安全的if/else +server/stream-utils/模式)。require()
Verification
验证方式
- Validate edge bundling regressions with
pnpm test-start-webpack test/e2e/app-dir/app/standalone.test.ts - For module-resolution/build-graph fixes, verify without
NEXT_SKIP_ISOLATE=1
- 使用验证Edge打包是否出现回归问题
pnpm test-start-webpack test/e2e/app-dir/app/standalone.test.ts - 对于模块解析/构建图修复,请在不使用的情况下进行验证
NEXT_SKIP_ISOLATE=1
Related Skills
相关技能
- - flag wiring (config/schema/define-env/runtime env)
$flags - - entry-base boundaries and vendored React
$react-vendoring - - reproduction and verification workflow
$runtime-debug
- - 标志配置(config/schema/define-env/runtime env)
$flags - - entry-base边界与 vendored React
$react-vendoring - - 复现与验证工作流
$runtime-debug