动态导入需用静态字符串路径以支持tree shaking;避免变量拼接、模糊glob和副作用代码;配合构建工具配置可提升摇树效果。

动态导入(import())本身是异步的、运行时求值的,因此天然 不参与静态分析和 Tree Shaking。但你可以通过合理设计导入路径、避免字符串拼接、配合构建工具配置,让动态导入“尽量友好”——既保留按需加载优势,又不主动阻断模块依赖图的可分析性。
确保导入路径是静态可解析的字面量
Tree Shaking 依赖构建工具(如 Webpack、Vite、Rollup)在构建期识别哪些导出未被使用。若 import() 的参数是变量或表达式,工具无法推断目标模块,会保守地保留所有可能用到的代码,甚至整个 chunk。
- ✅ 好:路径是字符串字面量,且结构固定
import('./utils/dateFormatter.js')
构建工具能准确识别并单独打包这些模块,后续仍可对它们内部做 Tree Shaking(只要它们自身使用静态 export/import)。
- ❌ 避免:路径含变量、模板拼接或条件逻辑
import('./' + type + '/handler.js')
import(condition ? './a.js' : './b.js')
这类写法会让构建工具无法确定实际加载哪个模块,通常会把所有匹配的候选模块(甚至整个目录)打包进一个 chunk,并禁用对其内部的摇树优化。
避免在动态导入中引入宽泛的上下文(Context Modules)
像 Webpack 的 require.context 或 Vite 中误用 import.meta.glob 不当,容易触发“上下文导入”,导致大量未使用的模块被包含。
- ✅ 推荐:显式列出需动态加载的模块,或用
import.meta.glob的精确模式
const modules = import.meta.glob('./pages/*.vue', { eager: false })
注意:{ eager: false } 生成的是懒加载函数,不会立即引入;构建工具仍能分别分析每个 .vue 文件的导出使用情况。
- ❌ 慎用:模糊 glob 模式或递归上下文
require.context('./', true, /\.spec\.js$/)
导出内容保持“可摇”:动态模块内部也要用静态导出
动态导入的模块本身若使用 export default 或命名导出,且调用方只解构/调用其中一部分,构建工具仍可剔除未引用的导出 —— 前提是该模块没有副作用(如顶层执行语句、直接修改全局等)。
- ✅ 动态模块应干净、无副作用
export const add = (a, b) => a + b
export const multiply = (a, b) => a * b
export default { add, multiply } // 可被安全摇掉未用部分
- ❌ 避免在动态模块中执行不可忽略的副作用
console.log('Logger initialized')
export function log() { ... }
这种模块会被视为“有副作用”,即使你只用了 log,构建工具也不敢删掉初始化语句,也无法安全摇树。
配合构建工具配置,显式标记无副作用
对于确实无副作用但被误判的模块(例如纯函数工具库),可通过配置辅助工具判断:
- Webpack:在
module.rules中为对应文件添加parser.sideEffects: false - Vite/Rollup:在
package.json中声明"sideEffects": false或["*.css"]
这能让工具更激进地摇掉未使用的动态导入模块中的未引用导出。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











