Webpack的核心作用是解析模块图并按需构建执行逻辑,而非简单打包;它静态分析import/require生成依赖图,不执行代码,对动态引入和运行时API处理受限,且tree shaking仅适用于ESM。

JavaScript 模块打包不是“把代码压缩一下”,而是解决浏览器无法原生加载 import 语句、模块路径不一致、依赖顺序混乱、开发与生产环境差异大等实际问题的工程化手段。Webpack 是其中最成熟的工具,但它的核心作用不是“打包”,而是“解析模块图 + 按需构建执行逻辑”。
Webpack 怎么识别和处理 import 和 require
Webpack 会从你配置的 entry 文件开始,静态分析所有 import(ESM)和 require(CommonJS)语句,递归构建出一张完整的依赖图。它不运行代码,只做语法层面的解析 —— 所以动态 import() 会被当作异步分割点,而字符串拼接的 require('a' + 'b') 会直接报错或被忽略。
- ESM 的
import必须是顶层语句,不能在条件里;否则 Webpack 无法静态分析 -
require.resolve、require.context这类运行时 API,Webpack 会尝试模拟,但行为受限 - TypeScript 的
import type不会进入依赖图,不影响打包结果 - 如果某模块被
import但没被实际使用(且未启用treeShaking),它仍会被包含进 chunk
为什么 node_modules 里的包默认不被转译
Webpack 默认只对项目源码(src/ 或 ./ 开头路径)应用 babel-loader 或 ts-loader,而跳过 node_modules。这不是偷懒,而是性能和兼容性权衡:大量第三方包已是编译后产物,再转译可能破坏其已适配的运行时环境(比如某些包依赖 process.env.NODE_ENV 做分支判断)。
- 如需转译特定包(如用了新语法的现代库),在
rules的include中显式加入该包路径 - 用
resolve.alias可以把某个包指向其 esm 版本(如react: 'react/cjs/react.development.js'改为react: 'react/index.js'),避免 cjs 包裹带来的副作用 -
externals用于完全排除某模块(如把lodash排除,由 CDN 提供),此时import _ from 'lodash'仍可写,但不会被打入 bundle
mode: 'production' 真正触发了什么
它不只是开启 UglifyJsPlugin,而是激活一整套默认优化策略:自动启用 Tree Shaking(仅对 ESM 生效)、Scope Hoisting(ModuleConcatenationPlugin)、SplitChunksPlugin 默认配置、以及 DefinePlugin 注入 process.env.NODE_ENV = 'production'。
立即学习“Java免费学习笔记(深入)”;
- Tree Shaking 依赖
export和import静态结构,export default function可被摇掉,export default { a: 1 }则大概率保留整个对象 -
SplitChunksPlugin默认只对异步import()和被重复引用 ≥2 次的模块生效,同步import不会自动拆包 - 若代码中写了
if (process.env.NODE_ENV === 'development') {...},DefinePlugin会让该分支在 production 下被完全移除
真正难的不是配置 Webpack,而是理解哪些模块该打进去、哪些该外置、哪些该延迟加载 —— 这些决策藏在业务逻辑里,不在 webpack.config.js 里。











