64 lines
2.5 KiB
Markdown
64 lines
2.5 KiB
Markdown
---
|
|
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/)
|