项目中有很多模块,一个模块就是一个js文件,项目中加载这些js的时候发送很多http请求,影响性能。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的网页</title>
<!-- <style>
body {
background-color: grey;
}
</style> -->
<!-- rel="stylesheet"必须写 -->
<link href="./test.css" rel="stylesheet">
</head>
<body>
<h1>我的网页</h1>
<div id="app">
<!-- <div>header</div>
<div>content</div>
<div>footer</div> -->
</div>
<!-- <script src="./test.js"></script> -->
<script src="./header.js"></script>
<script src="./content.js"></script>
<script src="./footer.js"></script>
<script src="./test.js"></script>
<!-- 传统模块化开发 -->
<!-- 多加载了js文件,发送了多次http请求 -->
<!-- 变量的来源不是很确定 -->
<!-- 加载顺序问题 -->
<!-- 现在的模块化开发使用ES6的import export 使用模块 -->
<!-- 但浏览器不能识别import export -->
<!-- => webpack 解决以上问题 -->
</body>
</html>
body {
background-color: rgb(212, 207, 207);
}
// alert('hello')
const app = document.getElementById('app')
const header = document.createElement('div')
header.innerText='header';
app.appendChild(header)
const content = document.createElement('div')
content.innerText='content';
app.appendChild(content)
const footer = document.createElement('div')
footer.innerText='footer';
app.appendChild(footer)
/***
* 以上就是面向过程编程,所有的代码都写在一个js文件里面,
* 对以后项目的维护,功能的扩展都不是很友好
*
* => 面向对象编程
*
*/
new Header();
new Content();
new Footer();
// header.js
function Header(){
const header = document.createElement('div')
header.innerText='header';
app.appendChild(header)
}
// content.js
function Content(){
const content = document.createElement('div')
content.innerText='content';
app.appendChild(content)
}
// footer.js
function Footer(){
const footer = document.createElement('div')
footer.innerText='footer';
app.appendChild(footer)
}
https://webpack.docschina.org/
npx webpack index.js
告诉webpack模块打包的入口文件是index.js,然后开始打包
配置入口文件 webpack.config.js
(默认配置名)
module.exports = {
entry: './index.js',
};
可以在控制台直接执行npx webpack
webpack.dev.config.js
npx webpack --config ./webpack.dev.config.js
output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。
你可以通过在配置中指定一个 output 字段,来配置这些处理过程:
const path = require('path');
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
//在任何模块文件内部,可以使用__dirname变量获取当前模块文件所在目录的完整绝对路径。
filename: 'my-first-webpack.bundle.js',
publicPath: 'http://localhost:8080/' //打入引入js文件的域名
},
};
const path = require('path');
module.exports = {
entry: {
main:'./index.js',
// entry中key值为打包后的名字
// 可以有多个入口
},
};
const path = require('path');
module.exports = {
entry: {
main: './index.js',
// entry中key值为打包后的名字
// 可以有多个入口
sub:'./index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
// 输入两个文件main sub
},
},
;
Performance
https://webpack.docschina.org/configuration/performance/#root
关闭性能优化的提示
module.exports = {
//...
performance:false,
//关闭性能优化的相关内容,
// 发现npx weback 打包的一些报警信息没有了
};
浏览器缓存
每次打包生产相同的bundle.js文件,浏览如果开启了缓存就会从缓存中读取,不会更新最新的文件
output filename使用由生成的内容产生的 hash:
webpack.config.js
module.exports = {
//...
output: {
filename: '[name][contenthash:8].bundle.js',
},
};
通过选择 development, production 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production。
module.exports = {
mode: 'development',
};
同过不同的文件配置
{
"scripts":{
"build":"webpack --config ./build/webpack.prod.js",
"dev":"webpack-dev-server --config ./build/webpack.dev.js",
"dev:build":"webpack --config ./build/webpack.dev.js",
}
}
const path = require('path');
module.exports = {
entry: {
main: './index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
},
;
const {merge} = require('webpack-merge')
// 公共配置
const baseConfig = require('./webpack.base')
// 开发配置
const devConfig = module.exports = {
"mode":"development",
"devtool":"",
"devServer":{},
"plugins":[]
}
module.exports = merge(baseConfig,devConfig)
在 webpack 的配置中,loader 有两个属性:
const path = require('path');
module.exports = {
output: {
filename: 'my-first-webpack.bundle.js',
},
module: {
rules: [{ test: /\.txt$/, use: 'raw-loader' }],
},
};
以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:test 和 use。这告诉 webpack 编译器(compiler) 如下信息:
“嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 ‘.txt’ 的路径」时,在你对它打包之前,先 use(使用) raw-loader 转换一下。”
https://webpack.docschina.org/loaders/在这里安装loader
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[hash].[ext]',
// 生成的dist中图片名是原图片名(默认文件名是一个md5生成的)
// name配置项是配置打包生成的文件的名字,使用的是placeholder语法
// [name]表示的是原文件的名字;
// [hash] 表示的是这次打包的hash值
// [ext]表示的是原文件的后缀;
outputPath: 'images',
// 生成的图片在dist/images/路径下
},
}
],
},
],
},
};
import testJpg from './resource/test.jpg';
console.log('name',testJpg)
const img = new Image();
img.src = testJpg;
const app = document.getElementsByTagName('div')[0]
app.appendChild(img);
执行npx打包命令后,打开dist中的首页可以看到图片显示
https://v4.webpack.docschina.org/loaders/url-loader/
A loader for webpack which transforms files into base64 URIs.
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
// 防止图片过大,限制大小
}
}
]
}
]
}
}
图片很大->url loader->base64字符串很大->bundle.js体积会很大->index.html加载bundle.js时间就很长
图片很小->url loader->图片base64直接设置在img的src属性上->不需要发送额外的http请求图片
图片很小->file-loader->单独生成图片文件->index引入->bunde.js很小->页面加载块->多发送一次http请求
图片很大->file-loader->bunde.js很小->图片单独请求
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
name: 'dirname/[hash].[ext]',
// 生成的dist中图片名是原图片名(默认文件名是一个md生成的)
outputPath: 'images',
// 生成的图片在dist/images/路径下
limit: 8192
// 防止图片过大,限制大小
}
}
]
}
]
}
}
{
module: {
rules: [
{
test: /\.css$/,
// use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
uer: ['style-loader','css-loader']
},
];
}
}
从右往左 从下往上
// webpack.config.js
module.exports = {
...
module: {
rules: [{
test: /\.scss$/,
use: [
"style-loader", // 将 JS 字符串生成为 style 节点
"css-loader", // 将 CSS 转化成 CommonJS 模块
"sass-loader" // 将 Sass 编译成 CSS,默认使用 Node Sass
]
}]
}
};
// webpack.config.js
{
test: /\.scss/,
use: [
{ loader: 'style-loader'},
{ loader: 'css-loader',
options: {
importLoaders: 2 //如果css中import scss文件 应用2个层级的loader
},
},
{ loader: 'postcss-loader' },
{ loader: 'sass-loader'}
]
}
https://v4.webpack.docschina.org/loaders/postcss-loader/#sourcemap
{
test: /\.css/,
use: [
{ loader: 'style-loader', options: { sourceMap: true } },
{ loader: 'css-loader', options: { sourceMap: true } },
{ loader: 'postcss-loader', options: { sourceMap: true } },
{ loader: 'sass-loader', options: { sourceMap: true } }
]
}
{
test: /\.css$/,
use: [
{
loader: 'postcss-loader',
options: {
plugins: () => [require('autoprefixer')({
'browsers': ['> 1%', 'last 2 versions']
})],
}
},
]
}
or
module.exports = ({ file, options, env }) => ({
// parser: file.extname === '.sss' ? 'sugarss' : false,
plugins: {
// require('autoprefixer')({...options}),
// require('autoprefixer')({
// // 也可以在这设置目标浏览器
// browsers : ['last 100 versions']
// })
require('autoprefixer')({
'browsers': ['> 1%', 'last 2 versions']
})
}
})
"browserslist":[
"> %1",
"last 2 versions"
]
在讲如何实现CSS模块化之前先讲讲要利用模块化来解决什么问题:
https://github.com/css-modules/css-modules
https://webpack.docschina.org/loaders/css-loader/#modules
{
test: /\.css$/i,
loader: "css-loader",
options: {
modules: true,
},
}
/* components/Button.css */
.normal { /* normal 相关的所有样式 */ }
.disabled { /* disabled 相关的所有样式 */ }
/* components/Button.js */
import styles from './Button.css';
console.log(styles);
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`
生成的 HTML 是
<button class="button--normal-abc53"> Processing... </button>
打印结果
Object {
normal: 'button--normal-abc546',
disabled: 'button--disabled-def884',
}
CSS Modules 对 CSS 中的 class 名都做了处理,使用对象来保存原 class 和混淆后 class 的对应关系。
https://v4.webpack.docschina.org/plugins/
https://webpack.js.org/awesome-webpack/
https://v4.webpack.docschina.org/plugins/html-webpack-plugin/
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js'
},
// 插件都是实例化使用
plugins: [new HtmlWebpackPlugin()]
};
这将会产生一个包含以下内容的文件 dist/index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>webpack App</title>
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js'
},
plugins: [new HtmlWebpackPlugin({
template:'./src/index.html'
//配置dist/html模板
})]
};
https://v4.webpack.docschina.org/configuration/devtool/#devtool
const path = require('path');
module.exports = {
mode:'development',
devtool:'none',
entry: {
main: './index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
},
}
index.js
console.logg('hello')
// 这行代码webpack打包的时候不会报错,打开网页后浏览器报错,问题定位到dist/main.js
npx webpack
or npm run build
进行构建打包,刷新页面才能看到修改的页面https://v4.webpack.js.org/configuration/dev-server/
npm install webpack-dev-server --save-dev
var path = require('path');
module.exports = {
//...
devServer: {
// contentBase: path.join(__dirname, 'dist'),
// webpack5中contentBase已经失效了
static: {
directory: path.join(__dirname, 'dist'),
},
compress: true,//压缩
port: 9000,
open: true //告诉 dev-server 在 server 启动后打开浏览器。默认禁用。
// proxy 可以处理跨域问题
},
};
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev" : "webpack-dev-server"
},
npm run dev
webpack.config.js
module.exports = {
//...
devServer: {
// 1.
// proxy: {
// '/api': 'http://localhost:3000'
// },
// 2.
// proxy: {
// '/api': {
// target: 'http://localhost:3000'
// }
// }
proxy: {
'/api': {
// 一旦devServer(5000)服务器接收到 /api/xxx 的请求,就会把请求转发到另一个服务器(3000)
// 浏览器和服务器之间有跨域,但是服务器和服务器之间没有跨域
target: 'http://thirdserver.com:3000',
changeOrigin: true,
pathRewrite: {
'^/api': ''
// 所有以/api开头的请求,把/api转换为空字符串
// 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api
},
secure: false,
//默认情况下,不接受运行在 HTTPS 上,且使用了无效证书的后端服务器。
// 如果你想要接受,修改配置如下:
}
}
}
};
请求到 /api/users 现在会被代理到请求 http://localhost:3000/api/users。
"scripts":{
"build":"webpack", // 打包后文件在dist/main.js可以找到
"dev":"webpack-dev-server" //打包后文件在内存中
}
const webpack = require('webpack');
// ........
module.exports = {
plugins:[new webpack.HotModuleReplacementPlugin()]
// webpack内置插件
}
https://stackoverflow.com/questions/69102254/webpack-options-has-an-unknown-property-hotonly-invalid-options-object-dev-s
The latest versions automatically apply HotModuleReplacementPlugin plugin when you set hot: true, so please check you don’t have HotModuleReplacementPlugin in your plugins if you have hot: true/hot: “only”. You will get a warning as " [webpack-dev-server] “hot: true” automatically applies HMR plugin, you don’t have to add it manually to your webpack configuration." if you have the preceding settings.
if(module.hot){ //在你要监听的文件里面写
console.log('hot')
// './print.js'
// Ignored an update to unaccepted module ./src/print.js -> ./src/index.js
// accept第一个参数必须是当前依赖的模块路径
module.hot.accept('./print.js',()=>{ // ./src值得是更新文件路径
console.log('代码热更新,写自己的代码控制')
const oldSpan = document.getElementsByTagName('span')[0];
oldSpan.innerText=`HRP-sp${print.a}`;
})
}
https://www.babeljs.cn/docs/index.html
Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。下面列出的是 Babel 能为你做的事情:
npm install -D babel-loader @babel/core @babel/preset-env
config
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,//排除第三方代码
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
babel.config.json
https://babel.docschina.org/docs/en/next/usage/
const flag = true;
if(flag){
const {add} = require('./math')
}
if(flag){
import {add} from ('./math')
// 这种动态引入会报错
// import and export may only appear at the top level
}
Tree Shaking指的就是当我引入一个模块的时候,我不引入这个模块的所有代码,我只引入我需要的代码,这就需要借助webpack里面自带的Tree Shaking这个功能,帮助我们实现。Tree Shaking只支持ES Module(import…) 不支持require…
https://developer.mozilla.org/zh-CN/docs/Glossary/Tree_shaking
https://webpack.js.org/guides/tree-shaking/
当在development模式下配置tree shaking时:
mode:'development',
optimization: {
usedExports: true,
},
在production 模式下不用在webpack.config.js中配置.usedExports默认自动开启
如果Tree Shaking不生效请检查source-map
通过 package.json 的 “sideEffects” 属性,来实现这种方式。
{
"name": "your-project",
"sideEffects": false
}
如果所有代码都不包含副作用,我们就可以简单地将该属性标记为 false,来告知 webpack 它可以安全地删除未用到的 export。
因为Tree Shaking会删除掉我们未使用的export函数,因为polyfill都在window上定义的,没有export,所以会被删除掉.
配置side effect排除副作用的检查
:::tip
“side effect(副作用)” 的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个 export 或多个 export。举例说明,例如 polyfill,它影响全局作用域,并且通常不提供 export。
:::
{
"name": "your-project",
"sideEffects": ["@babeli/polyfill","*.css"]
}
https://webpack.docschina.org/guides/code-splitting/
import _ form 'lodash'
console.log('hello world!');//每次修改业务逻辑,webpack打包的时候也会将lodash一块重新打包到bundle.js
const result = _.join(['test1','test2','test3'],'-');
console.log('result',result)
console.log('hello world!');
const result = _.join(['test1','test2','test3'],'-');
console.log('result',result)
import _ form 'lodash'
window._= _
module.exports = {
entry:{
main:'./src/index.js',
lodash:'./src/lodash.js'
//打包生成 main.js和lodash.js并引入到index.html中
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
}
},
}
SplitChunksPlugin 去重和分离 chunk。
https://webpack.docschina.org/plugins/split-chunks-plugin/
src/index.js
import _ form 'lodash'
console.log('hello world!');//每次修改业务逻辑,webpack打包的时候也会将lodash一块重新打包到bundle.js
const result = _.join(['test1','test2','test3'],'-');
console.log('result',result)
module.exports = {
//...
optimization: {
splitChunks: {
chunks:'all'
},
};
https://webpack.docschina.org/guides/lazy-loading/#root
// Note that because a network request is involved, some indication
// of loading would need to be shown in a production-level site/app.
button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => {
const print = module.default;
// 注意当调用 ES6 模块的 import() 方法(引入模块)时,必须指向模块的 .default 值,因为它才是 promise 被处理后返回的实际的 module 对象。
print();
});
splitChunks.chunks:This indicates which chunks will be selected for optimization. When a string is provided, valid values are all, async, and initial. Providing all can be particularly powerful, because it means that chunks can be shared even between async and non-async chunks.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jtOQyPHA-1654528404640)(https://gitee.com/jingyu7/pic/raw/master/202201061256177.png)]
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',//默认只有异步代码进行代码分隔 all, async, and initial
minSize: 20000, //如果引入的包>20000KB就进行代码分隔
minRemainingSize: 0,//通过确保拆分后剩余的最小 chunk 体积
minChunks: 1, //拆分前必须共享模块的最小 chunks 数。
// 这个配置表示split前单个非按需导入的module的并行数的最低下限
// 注:只对import或require直接引入的module有效。
// 1. minChunks设置为n
// 2. 假设有m个入口点,这m个入口点都直接引入了某个模块module(通过import或require直接或间接地引入了模块),也就是共享次数为m
// 3. 当m至少等于n时,module才会被单独拆分成一个bundle
maxAsyncRequests: 30,//按需加载时的最大并行请求数。
maxInitialRequests: 30,//入口点的最大并行请求数
enforceSizeThreshold: 50000,//强制执行拆分的体积阈值和其他限制
cacheGroups: { //缓存组
// 对于缓存组是一个对象,处了可以有上面的chunks、minSize、minChunks、maxAsyncRequests、maxInitialRequests、name外,还有其他的一些参数:
// 如果不在缓存组中重新赋值,缓存组默认继承上面的选项,但是还有一些参数是必须在缓存组进行配置的
// 缓存组的概念理解
// 源代码中引入了lodash jquery 都分别分隔到了对应的js
// 假如希望它两合并后分隔
// 当分析到引入lodash时缓存到defaultVendors,分析到jquery满足规则也缓存起来
// 当所有模块到分析结束后,再把defaultVendors组一起分隔
defaultVendors: {
test: /[\\/]node_modules[\\/]/, //捕获模块规则
priority: -10, //优先级
reuseExistingChunk: true,
//如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
//假如源代码中不同文件中都引入lodash模块,
//在第一次引入分析后被当前缓存组缓存,后面的此模块的引入分析复用之前缓存结果
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
Automatically load modules instead of having to import or require them everywhere.
new webpack.ProvidePlugin({
identifier: 'module1',
// ...
});
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
// webpack为我们提供了ProvidePlugin的插件,上面配置的意思是,当我们在模块中遇到‘$’就会去自动的引入jquery
});
],
};
Then in any of our source code:
// in a module
$('#item'); // <= works
jQuery('#item'); // <= also works
// $ is automatically set to the exports of module "jquery"
有两种优化方向
exclude,include
exclude:path.resolve(__dirname,'node_modules')
问题
因为如果你不排除这个文件夹的话,你在自己的代码中引用的其他工具库的代码,也会被babel读取并重新编译,JavaScript代码的编译比较慢,很多情况下,你自己的业务代码只占了10%,但引用的其他工具库的代码,编译完以后可能占到80~90%,假如编译你自己的业务代码需要10秒钟,那整个项目的代码,就需要100秒,你会发现速度非常慢,不利于提高开发效率。另一方面,现在发布到npm上面的工具库,一般都包含了源代码和编译以后的代码,同时默认引用的是编译以后的代码,这样相当于你把编译完以后的代码又编译了一遍,实际上并没有任何效果,反而浪费了时间。所以我们在配置的时候,一般都将node_modules当中的工具库代码,排除在babel的编译范围之外。
虽然 npm 中的 package 没有明确规范需要编译成 es5/es3的语法,但是目前事实就是绝大部分公开的 package 都是编译到这个规范的,所以已经是一个事实标准了。
如果node_modules里的某些包有es6语法怎么办?
答:通过正则指定node_modules中的某些包不排除
babel 缓存:在babel-loader中的options中开启 cacheDirectory:true
把已经编译好的兼容性代码就放在缓存中,下次编译的时候如果缓存中有就直接使用编译后的代码,
只对js生效
module:{
rules:[
test: /\,js$/,
options:{
cacheDirectiry:true
},
inclued:srcPath,
exclude:path.resolve(__dirname,'node_modules')
]
}
webpack 中的 IgnorePlugin 在打包时忽略本地化内容,如引入了一个插件,只用到了中文语言包,打包的时候把非中文语言包排除掉
在项目中经常用到moment库处理时间,有没有发现引入moment之后,项目build完的文件大小明显大了不少,下面就来分析一下原因, 以及如何做优化。
//
import moment from 'moment'
// 引入中文
import 'moment/locale/zh-cn'
// 设置中文
moment.locale('zh-cn');
let momentStr = moment().subtract(10, 'days').calendar();
console.log('现在时间:', momentStr);
网上搜了一波才知道, 打包时把所有的locale都打包进去了, 初步解决方案是用webpack.IgnorePlugin来处理。
IgnorePlugin又是做了什么操作?
...
plugins: [
new webpack.IgnorePlugin(/^./locale$/, /moment$/) // 配置忽略规则
// 忽略moment库中的locale文件夹啊
]
那么你可能会有疑问,所有本地文件都被移除了,但我想要用其中的一个怎么办。不用担心,你依然可以在代码中这样使用:
const moment = require('moment');
require('moment/locale/ja');//如果需要请单独引用
moment.locale('ja');
https://github.com/zhanzizhen/how-to-optimize-momentjs-with-webpack/blob/master/README.md
一般使用.min.js结尾的文件,都是已经经过模块化处理的,那么这个时候就没必要在进行loder或者webpack分析了,noParer的字面意思也是不再解析。
module: {
noParse: /jquery/, // 不解析模块中的依赖关系 提高打包效率
rules: []
}
ignorePlugin和noParse的对比
noParse不会改变打包体积,只会加快构建速度
由于 JavaScript 是单线程模型,要想发挥多核 CPU 的能力,只能通过多进程去实现,而无法通过多线程实现。
由于运行在 Node.js 之上的 Webpack 是单线程模型的,所以 Webpack 需要处理的任务要一个一个进行操作。而 Happypack 的作用就是将文件解析任务分解成多个子进程并发执行。子进程处理完任务后再将结果发送给主进程。所以可以大大提升 Webpack 的项目构件速度
Webpack 可以监听文件变化,当它们修改后会重新编译。
启用 Watch 模式。这意味着在初始构建之后,webpack 将继续监听任何已解析文件的更改。
module.exports = {
//...
watch: true,
};
webpack-dev-server 和 webpack-dev-middleware 里 Watch 模式默认开启。
module.exports = {
//...
watchOptions: {
ignored: /node_modules/,
//监听大量文件会导致大量的 CPU 或内存占用。可以使用正则排除像 node_modules 如此庞大的文件夹:
aggregateTimeout: 200,//批量更新
// 当第一个文件更改,会在重新构建前增加延迟。这个选项允许 webpack 将这段时间内进行的任何其他更改都聚合到一次重新构建里。以毫秒为单位:
},
};
DllPlugin,DllReferencePlugin就是事先把常用但又构建时间长的代码提前打包好(例如 react、react-dom),取个名字叫 dll。后面再打包的时候就跳过原来的未打包代码,直接用 dll。这样一来,构建时间就会缩短,提高 webpack 打包速度。
就是个缓存吗!拿空间换时间。
autodll-webpack-plugin 也是类式插件, 之前被 vue-cli 使用
webpack 4 有着比 dll 更好的打包性能。所以已经不使用autodll-webpack-plugin了
当我后续找到 autodll-webpack-plugin,并发现 dll 已经被抛弃时,其实还是有些失望,觉得自己的之前的努力都白费了,不由自主产生 学不动 的想法。但是当我仔细想了一下 dll 的原理,发现也就是那么一会事儿,拿空间换时间,只不过配置复杂了一些。
所以这也提醒我们,学习新知识的时候,不要专注于流程的配置和调参。因为流程终会简化,参数(API)终会升级。要抓大放小,把精力放在最核心的内容上,因为核心的思想是最不容易过时的。