Loader file-loader 将引用文件(图片)移动到dist目录下
url-loader 将引用的图片转化成Base64打包到js文件中,可限定大小配置是否转换
style-loader,css-loader,sass-loader,postcss-loader
css-loader的配置 options: { importLoaders: 2 // 打包时也会执行下面两个loader }
css模块化 css-loader options: { modules: true } import style from './index.css' class名使用style.avatar
字体打包 file-loader
Asset Management 静态资源
SourceMap 源码映射,方便错误追踪,一般在开发环境中设置 可设置是否包括loader或module
devtool: 'inline-source-map'
source-map: 生成一个map文件保存信息 inline-...: 映射信息打包到js文件 cheap-...信息简略 eval-..打包速度最快
推荐 development: 'cheap-module-eval-source-map' production: 'cheap-module-source-map'
Hot Module Replacement 模块热更新
devServer: { hot: true, hotOnly: true // 若hot失效,会刷新页面 }
plugins: [ new webpack.HotModuleRplacementPlugin() ]
fn()
if (module.hot) { module.hot.accept('./main.js', () => { fn() }) }
Babel @babel/core babel-loader { test: /jsx?$/, loader: 'babel', options: { presets: [['@babel/preset-env', { targets: { chrome: '67' }, useBuiltIns: 'usege' // 只打包使用到的模块,按需引入,不必手动引入@babel/polyfill }]], plugins: [ // 开发库时,避免preset(如引用polyfill,全局变量的影响) // index.js中不需引入polyfill ['@babel/plugin-transform-runtime', { 'corejs': 2, // 按需打包 需安装 @babel/runtime-corejs2 'helpers': true, 'regenerator': true, 'useESModules': false }] ] } }
index.js imoport '@babel/polyfill' // 兼容低版本浏览器
================================================
Tree Shaking 只支持ES Module 去除未使用的模块 mode: 'production' // 生产模式下默认Tree Shaking
mode: 'development, optimization: { usedExports: true // 生产环境不需配置 }
配合 package.json { // 生产环境也需配置 "sideEffects": false // 对所有模块进行tree shaking 或 [*.css],对中括号中的文件不进行tree shaking }
===============================================
webpack-merge
clean-webpack-plugin new CleanWebpackPlugin(['dist'], { root: path.resolve(__dirname, '../') // 配置项目根目录, 默认webpack配置文件所在的目录 })
配置支持动态引入 babel-plugin-dynamic-import-webpack //不支持魔法注释 换官方插件 @babel/plugin-syntax-dynamic-import
================================================
Code Splitting 代码分割
// 同步 optimization: { splitChunks: { chunks: 'all' // 将node_modules引入的库单独打包 } }
// 异步 无需webpack配置 import(/* webpackChunkName: "lodash" */ 'lodash').then() // 使用魔法注释命名分割后的模块名
配置参数(还是看文档吧~~) optimization: { splitChunks: { chunks: 'all', cacheGroup: { // 组 ... } default: {
}
...
} }
chunks: all async 只对异步引入生效 inital 只对同步引入生效
minSize
maxSize 一般不配
minChunks: 1 至少使用1次
priority 分组的优先级,哪个组优先级高,就打包到哪个组 reuseExisttingChunk: true 重复使用已打包过的模块
=================================================
Lazy Loading 懒加载 await import()
=================================================
打包分析 github.com/webpack/analyse webpack --profile --json > stats.json
Bundle Analyse webpack-bundle-analyzer
=================================================
代码利用率/覆盖率 尽量多写异步代码
Preloading Prefetching import(/webpackPrefech: true/, 'click.js')
==================================================
CSS文件代码分割 { use: [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader' ] }
new MiniCssExtractPlugin({ filename: '[name].css', chunkFilename: '[name].chunk.css' })
注意:tree-shaking干掉css package.json { sideEffects: ['*.css'] }
压缩 optimize-css-assets-webpack-plugin optimization: { minimizer: [new OptimizeCssAssetsWebpackPlugin({})], }
=============================================================
浏览器缓存(Caching) output: { filename: '[name].[contenthash]js' chunkFilename: '[name].[contenthash]js' }
老版本webpack mainfest差异 optimization : { runtimeChunk: { name: 'runtime' } }
==============================================================
Shimming 垫片
new webpack.ProvidePlugin({
'时,会帮助引入jquery
})
// 将this指向window loader: imports-loader?this=>window
===============================================================
环境变量 package.json --env.production
webpack.config module.exports = (env) => { if (env.production) { return merge(commonConfig, config) } }
=====================================================
Library的打包
package.json { name: "haha" mian: "./dist/index.js" }
webpack.config.js { externals: ['lodash'], // 打包时忽略已安装的库 output: { library: 'library' // 支持全局引入 全局变量名: library libraryTarget: 'umd' // 引入的方式配置 import require } }
======================================================
PWA 一种技术,当服务器挂了,网站再次访问,页面依然能展示
workbox-webpack-plugin
======================================================
TypeScript
{ test: /.(ts|tsx)$/, use: 'ts-loader', exclude: /node_modules/ }
tsconfig.json { "compilerOptions": { "outDir": "./dist", "module": "es6", "target": "es5", "allowJs": true } }
=======================================================
WebpackDevServer 请求转发
devServer: { proxy: { '/api': 'http: .../api', '/api2': { target: '...', pathRewrite: { 'a.json': 'b.json' }, changeOrigin: true } } }
https secure: true
========================================================
WebpackDevServer 开发环境解决单页面路由问题
url请求时,服务器没有对应的请求路径 historyApiFallback
devServer: { historyAPiFallback: true // 相当于把所有的路由请求都指向index.html }
生产环境 需后端处理
========================================================
ESLint .eslintrc.js { extends: 'airbnb' // 规范(较严) parser: 'babel-eslint', rules: {
}, globals: { document: false // document可作为全局变量 } }
vscode插件 ESLint
webpack loader的执行顺序是从后往前 { { test: /.js$/, use: [ 'babel-loader', { loader: 'eslint-loader', // 一般不用这个loader,会降低打包速度 options: { fix: true, // 自动修复 } } ] }
devServer: { overlay: true // 在窗口显示eslint错误信息 } }
最佳实现: 使用 git 钩子 eslint src
===========================================================
webpack 性能优化
提升打包速度
-
升级工具
-
尽可能少的模块上应用Loader 合理使用include exclude
-
Plugin 尽可能精简并确保可靠 如:开发环境不需代码压缩、选择官方推荐的插件
-
resolve 参数合理配置(不宜配置太多) resolve: { extensions: ['.js', '.jsx'] // 支配只逻辑文件,不宜配置(css, png等) mianFiles: ['index', 'child'] // 引入目录时,默认引入index或child文件,不宜配置会降低性能 alias: { // 别名 '@': path.resolve(__dirname, '../src') } }
-
dll 第三方模块只打包一次 webpack.dll.js { entry: { vendors: ['react', 'react-dom', 'lodash'], output: { filename: '[name].dll.js', path: path.resolve(__dirname, '../dll'), library: '[name]', } }, plugins: [ new webpack.DllPlugin({ // 生成映射文件 path: path.resolve(__dirname, '../dll/[name].manifest.json') }) ] }
add-asset-html-webpack-plugin webpack.config { plugins: [ new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '../dll.vendors.dll.js') }), new webpack.DllReferencePlugin({ // 使用映射文件 manifest: path.resolve(__dirname, '../dll/vendors.manifest.json') }) ] }
// 动态使用dll,使用node const files = fs.readdirSync(path.resovle(__dirname, '../dll')) files.forEach(file => { if (/..dll.js/.test(file)) { plugins.push(new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '../dll', file) })) } if (/..manifest.json/.test(file)) { new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, '../dll', file) })) } })
-
控制包文件大小
-
thread-loader, parallel-webpack, happypack 多进程打包
-
合理使用 sourceMap
-
结合 stats 分析打包结果
-
开发环境内存编译 无用插件剔除
=============================================================
多页面打包
{ entry: { main: './src/index.js', list: './src/list.js' }, plugins: [ new HtmlWebpackPlugin({ template: 'src/index.html' filename: 'index.html, chunks: ['runtime', 'vendors', 'main'] }), new HtmlWebpackPlugin({ template: 'src/index.html' filename: 'list.html, chunks: ['runtime', 'vendors', 'list'] }) ] }
自动化 config.plugins = (configs) => {
}