[原文链接]http://feclub.cn/post/content/20180403
概念
webpack可以看做是模块打包机。它通过分析项目结构,找到 js、css、图片等模块或资源,并将其打包为合适的格式以供浏览器使用。
功能
- 代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等。
- 文件优化/压缩:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等。
- 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。
- 模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件。
等等...
webpack4主要变化
- 环境支持:官方宣布不在支持Node 4
mode 属性:webpack需要设置mode属性,可以是 development 或 production。
通过mode, 你可以轻松设置打包环境。
- 如果你将 mode 设置成 development,你将获得最好的开发阶段体验。这得益于webpack针对开发模式提供的特性:
- 浏览器调试工具
- 注释、开发阶段的详细错误日志和提示
- 快速和优化的增量构建机制
- 如果你将mode设置成了 production, webpack将会专注项目的部署,包括以下特性:
- 开启所有的优化代码
- 更小的bundle大小
- 去除掉只在开发阶段运行的代码
- 可以开启Scope hoisting和Tree-shaking
- 如果你将 mode 设置成 development,你将获得最好的开发阶段体验。这得益于webpack针对开发模式提供的特性:
插件和优化:webpack4删除了CommonsChunkPlugin插件,它使用内置API optimization.splitChunks
优化
优化loader配置(缩小文件搜索范围)
- include & exclude
- resolve.alias(配置项通过别名来把原导入路径映射成一个新的导入路径 ,此优化方法会影响使用Tree-Shaking去除无效代码)
- resolve.modules
- resolve.extensions
module.noParse(module.noParse 配置项可以让 Webpack 忽略对部分没采用模块化的文件的递归解析处理)
module: { noParse: [/react\.min\.js/] }
.dll 为后缀的文件称为动态链接库,在一个动态链接库中可以包含给其他模块调用的函数和数据。
DllPlugin插件: 用于打包出一个个动态链接库
module.exports = { entry: { react: ['react'] //react模块打包到一个动态链接库 }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].dll.js', //输出动态链接库的文件名称 library: '_dll_[name]' //全局变量名称 }, plugins: [ new webpack.DllPlugin({ name: '_dll_[name]', //和output.library中一致,值就是输出的manifest.json中的 name值 path: path.join(__dirname, 'dist', '[name].manifest.json') }) ] }
DllReferencePlugin: 在配置文件中引入DllPlugin插件打包好的动态链接库
plugins: [ new webpack.DllReferencePlugin({ manifest: require(path.join(__dirname, 'dist', 'react.manifest.json')), }) ]
HappyPack针对loader解析过程,能让Webpack把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。
ParallelUglifyPlugin可以把对JS文件的串行压缩变为开启多个子进程并行执行
区分环境:通过环境变量区分,用 webpack-merge覆盖相应配置
CDN:配置publicPath
- 静态资源的URL变成指向CDN服务器的地址
- 把不同的静态资源分配到不同的CDN服务器上
Tree Shaking(ES6模块静态解析)
Tree Shaking 可以用来剔除JavaScript中用不上的死代码。它依赖静态的ES6模块化语法,例如通过import和export导入导出。开启 Scope Hoisting:参考以下文章
https://webpack.js.org/plugins/module-concatenation-plugin/#src/components/Sidebar/Sidebar.jsx
https://segmentfault.com/a/1190000012600832通过分析出模块之间的依赖关系,尽可能的把打散的模块合并到一个函数中去,但前提是不能造成代码冗余。 因此只有那些被引用了一次的模块才能被合并。
const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin'); module.exports = { plugins: [ // 开启 Scope Hoisting new ModuleConcatenationPlugin(), ] };
提取公共代码
使用 common-chunk-and-vendor-chunk(用法待官方文档更新)optimization: { splitChunks: { cacheGroups: { commons: { chunks: "initial", minChunks: 2, maxInitialRequests: 5, // The default limit is too small to showcase the effect minSize: 0 // This is example is too small to create commons chunks }, vendor: { test: /node_modules/, chunks: "initial", name: "vendor", priority: 10, enforce: true } } } }
代码分离
入口起点:使用 entry 配置手动地分离代码。
entry: { index: './src/index.js', another: './src/another-module.js' }
防止重复:使用 splitChunks 去重和分离 chunk。
- 动态导入:通过模块的内联函数调用来分离代码。