进击webpack4 (优化篇)

7次阅读

共计 4300 个字符,预计需要花费 11 分钟才能阅读完成。

进击 webpack 4(基础篇一)进击 webpack4(基础篇二:配置 一)进击 webpack4(基础篇三:配置 二)
不解析不依赖第三方模块的模块
noParse
有一些第三方模块,它本身不依赖于其他模块,比如 jquery,lodash,不去编译这些库,会使得 webpack 打包更加快速 noParse 是个正则或者包含正则的数组 RegExp | [RegExp]
module:{
noParse:/jquery/, // 不去解析 jquery
rules:[
//…
]
},
———————

忽略某些库内的第三方模块
ignorePlugin
以 moment 这个时间库为例,导入 moment 的同时,moment 会引入自身依赖的语言包,这些语言包其中有部分是我们不需要用到的,moment 内部代码

plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
],
2 个参数代表的意思是:
当匹配到 moment 这个库的时候 引入 moment 并且忽略 moment 里面匹配到 locale 的库
这个时候我们如果想要自己需要的 locale 需在 main.js 手动引入
import ‘moment/locale/zh-cn’
动态链接库
另起一个 webpack.config.dll.js 专门用来生成动态链接库
//webpack.config.dll.js

const path=require(‘path’);
const webpack=require(‘webpack’);
module.exports={
mode:’development’,
entry: {
react:[‘react’,’react-dom’],
jquery:[‘jquery’]
},// 把 React 相关模块的放到一个单独的动态链接库
output: {
path: path.resolve(__dirname,’dist’),// 输出的文件都放到 dist 目录下
filename: ‘[name].dll.js’,// 输出的动态链接库的文件名称,[name] 代表当前动态链接库的名称
library: ‘_dll_[name]’,// 存放动态链接库的全局变量名称, 例如对应 react 来说就是 _dll_react
},
plugins: [
new webpack.DllPlugin({
// 动态链接库的全局变量名称,需要和 output.library 中保持一致
// 该字段的值也就是输出的 mainfest.json 文件 中 name 字段的值
// 例如 react.manifest.json 中就有 “name”: “_dll_react”
name: ‘_dll_[name]’,
// 描述动态链接库的 manifest.json 文件输出时的文件名称
path: path.join(__dirname, ‘dist’, ‘[name].mainfest.json’)
})
]
}
// 打包
npx webpack –config webpack.config.dll.js
这样会在 dist 生成

然后在 webpack.config.js 里
const webpack= require(‘webpack’)
plugins: [
new webpack.DllReferencePlugin({
manifest:require(‘./dist/react.mainfest.json’)
}),
new webpack.DllReferencePlugin({
manifest:require(‘./dist/jquery.mainfest.json’)
})
]
这里它会从 mainfest.json 寻找 name 然后根据它的标识找到相应内容, dll.js 就是打包出来后的动态链接库

然后在 html 模板文件里引入
<script src=”./jquery.dll.js”></script>
<script src=”./react.dll.js”></script>
如果你在 main.jsimport React from ‘react’, 他会首先找动态链接库,找不到才会执行打包

注:使用 react 需要配置好 rule

{
test:/\.js/,
use:{
loader:’babel-loader’,
options:{
presets:[
‘@babel/preset-env’,
‘@babel/preset-react’
]
}
}
},

开启多进程打包
npm i happypack -D
如果一个项目代码密集,读写操作频繁,happypack 就能让 Webpack 把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。
const HappyPack = require(‘happypack’);
rules: [
{
test: /\.js$/,
// 把对 .js 文件的处理转交给 id 为 babel 的 HappyPack 实例
use: [‘happypack/loader?id=babel’],
exclude: path.resolve(__dirname, ‘node_modules’),
},
{
test: /\.css$/,
// 把对 .css 文件的处理转交给 id 为 css 的 HappyPack 实例
use: [‘happypack/loader?id=css’]
}
]
new Happypack({
//ID 是标识符的意思,ID 用来代理当前的 happypack 是用来处理一类特定的文件的
id: ‘js’,
use: [{
loader: ‘babel-loader’,
//options=query 都是向插件传递参数的
options: {
presets: [[“@babel/preset-env”, { modules: false}], “@babel/preset-react”],
plugins: [
[“@babel/plugin-proposal-decorators”, { “legacy”: true}],
[“@babel/plugin-proposal-class-properties”, { “loose”: true}],
]
}
}]
}),
new Happypack({
//ID 是标识符的意思,ID 用来代理当前的 happypack 是用来处理一类特定的文件的
id: ‘css’,
use: [MiniCssExtractPlugin.loader, ‘css-loader’, ‘postcss-loader’],
threads: 4,// 你要开启多少个子进程去处理这一类型的文件
verbose: true// 是否要输出详细的日志 verbose
})
注意:开启进程也需要时间,如果一个项目并不是很复杂,斟酌使用
不打包第三方库 使用 cdn 引入
module.exports = {
//…
externals: {
jquery: ‘jQuery’
}
};
main.js 引入 jquery 将不会打包 import jquery from ‘jQuery’
html 模板内引入 jquery 的 cdn 地址即可
尽量使用 es6 的模块导入
webpack 的 tree-shaking 自己可以分析出哪些没有使用到的代码可以剔除,前提是 es6 模块语法 scope-hosting 可以提升作用域 比如 var a = 1; var b = a ; console.log(b) 会编译成 var b = 1; console.log(b)
提取公共代码
做这种操作首先得是多页面
entry:{
home:[‘./src/index.js’],
login:[‘./src/login.js’]
}, // 入口文件
//home.js
import React from ‘react’
import {render}from ‘react-dom’
render(<h1> 动态链接库 </h1>,window.root)

//login.js
import React from ‘react’
import {render}from ‘react-dom’
render(<h1> 动态链接库 </h1>,window.root)
//webpack.config.js

optimization:{// 优化
splitChunks:{// 分割代码
cacheGroups:{// 缓存组
common:{// 公共的代码 一般是自己写的公共代码
chunks:’initial’,
minSize:0,
minChunks: 2, // 最少被引用 2 次的模块
name: “common”
},
vendor:{// 一般是第三方公共模块
priority:1, // 因为执行是从上往下,所以设置优先级比上面高 不然上面抽离的话第三方模块也被抽离了
test:/node_modules/ , // 匹配 node_modules 下的公共代码,
chunks:’initial’,
minSize:0,
minChunks: 2, // 最少被引用 2 次的模块
name: “vendor”
}
}
}
}

懒加载
这里拿 vue 举例
const Login = () => import(/* webpackChunkName: “login” */,”./login”);
new VueRouter({
routes: [{path: “/login”, component: Login}]
})
webpackChunkName 虽然是注释,但是 webpack 能识别,编译后这个组件生产的名字就是 login
可能会需要 @babel/plugin-syntax-dynamic-import 才能识别
yarn add @babel/plugin-syntax-dynamic-import -D
具体配置看此文
热更新
devServer:{
// 告诉 DevServer 要开启模块热替换模式
hot: true,
}
在 vue 中只要这样配置就可以了,vue 自己帮我们做了配置
其他库中:
import React from ‘react’
import {render} from ‘react-dom’

render(<App/>, document.getElementById(‘root’));

if (module.hot) {
// accept 函数的第一个参数指出当前文件接受哪些子模块的替换,这里表示只接受 ./AppComponent 这个子模块
// 第 2 个参数用于在新的子模块加载完毕后需要执行的逻辑
module.hot.accept([‘./App’], () => {
// 新的 AppComponent 加载成功后重新执行下组建渲染逻辑
let App=require(‘./App’).default;
render(<App/>, document.getElementById(‘root’));
});
}

正文完
 0