--- title: Prefer Statically Analyzable Paths impact: HIGH impactDescription: 避免意外打包大范围文件和文件追踪范围扩大 tags: bundle, nextjs, vite, webpack, rollup, esbuild, path --- ## 优先使用可静态分析的路径 构建工具在构建时能明确识别导入路径和文件系统路径时效果最佳。如果实际路径隐藏在变量中,或者通过过于动态的方式拼接路径,构建工具要么被迫包含大量可能的文件,要么发出警告称无法分析该导入,要么扩大文件追踪范围以确保安全。 应优先使用显式的映射表或字面量路径,使可访问文件集合保持窄小且可预测。无论你是用 `import()` 选择模块,还是在服务器/构建代码中读取文件,这条规则同样适用。 当静态分析范围变得过大时,代价是实实在在的: - 更大的服务端打包体积 - 更慢的构建速度 - 更差的冷启动性能 - 更多的内存占用 ### 导入路径 **错误做法(打包工具无法判断可能导入什么):** ```ts const PAGE_MODULES = { home: './pages/home', settings: './pages/settings', } as const const Page = await import(PAGE_MODULES[pageName]) ``` **正确做法(使用显式的允许模块映射表):** ```ts const PAGE_MODULES = { home: () => import('./pages/home'), settings: () => import('./pages/settings'), } as const const Page = await PAGE_MODULES[pageName]() ``` ### 文件系统路径 **错误做法(即使是 2 值的枚举,仍然将最终路径隐藏于静态分析之外):** ```ts const baseDir = path.join(process.cwd(), 'content/' + contentKind) ``` **正确做法(在调用处让每条最终路径成为字面量):** ```ts const baseDir = kind === ContentKind.Blog ? path.join(process.cwd(), 'content/blog') : path.join(process.cwd(), 'content/docs') ``` 在 Next.js 服务端代码中,这一点对输出文件追踪同样重要。`path.join(process.cwd(), someVar)` 可能会扩大追踪文件集合,因为 Next.js 会静态分析 `import`、`require` 和 `fs` 的用法。 参考链接:[Next.js output](https://nextjs.org/docs/app/api-reference/config/next-config-js/output)、[Next.js dynamic imports](https://nextjs.org/learn/seo/dynamic-imports)、[Vite features](https://vite.dev/guide/features.html)、[esbuild API](https://esbuild.github.io/api/)、[Rollup dynamic import vars](https://www.npmjs.com/package/@rollup/plugin-dynamic-import-vars)、[Webpack dependency management](https://webpack.js.org/guides/dependency-management/)