从基础到实战 手把手带你掌握新版Webpack4.0-2

懒加载和 chunk 是什么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import _ from "lodash";
function getComponent() {
return import('/* webpackChunkName:"lodash" */ lodash').then(({ default: _ }) => {
var element = document.createElement("div");
element.innnerHTML = _.join(["Hello", "Every", "One"], "-");
return element;
});
}

// 只有当点击页面时才加载lodash
document.addEventListener("click", () => {
getComponent().then(element => {
document.body.appendChild(element);
});
});

在页面加载时,上面的代码所依赖的lodash模块是不会被加载的,可以查看请求记录,只有当点击页面时,lodash被打的包才会被加载 。 这就是懒加载。(注意上面的语法)

懒加载实际上是 ES6 的概念,不是 webpack 的,只是 webpack 支持这个语法而已。

css 进行代码分割

使用mini-css-extract-plugin插件,注意修改 tree shaking 的配置。比如sideEffects:["*.css"]

如果想把多个入口的 css 打包到同一个文件中,或者分开打包,都需要参考 cacheGroup,参考官网配置。

filename 和 chunkFileName 的区别

如果生成的文件是被入口 index.html 文件直接引用的,则使用 filename 指定的规则,如果是被其他模块引用的文件也就是二级引用则走 chunkFileName 规则。

Shimming

这个意思就是“垫片”,什么是垫片呢,举个例子;
比如你引入了一个第三方的模块 A,他依赖 jquery,但是它本身自己没有对 jquery 的引用,虽然你在自己的项目安装也引用了 jquery,但是由于 webpack 打包是基于模块的,A 是无法使用项目中引入的 jquery 的,但是第三方安装包,我们又不能改代码,Shimming 就是来解决这个问题的。
这需要用到webpackProvidePlugin

1
2
3
4
5
6
7
8
plugins: [
new webpack.ProvidePlugin({
// 这个指定,只要有用到$的地方,就在这个使用的模块中引入jquery,并命名成$
$: "jquery",
// 把lodash中的join方法打包成_join,这样也就可以在代码中直接使用了。
_join: ["lodash", "join"],
}),
];

模块中的 this 指向 window

模块中的 this 指向模块本身
使用imports-loader可以轻松做到这个。

1
2
3
4
5
6
7
8
9
10
11
module: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{ loader: "babel-loader" },
// 加上下面的配置,模块中的this就指向window了
{ loader: "imports-loader?this=>window" },
],
},
];

这也是shimming的一种

打包分析

参考官网介绍
中文版
也可以参考《项目性能和规范总结》一文中的介绍。
官网给了多种分析方式,其中一种是官方分析工具,这个比较简单,直接在 webpack 的 bu 打包生产环境的命令中传几个参数即可。--profile --json > stats.json

1
2
3
"scripts":{
"build":"webpack --profile --json > stats.json --config webpack.pro.js"
}

这样打包后会有一个stats.json文件,打开这个工具提供的分析网站,把生成的stats.json文件上传,就会生成界面化的分析结果。

查看 js 代码使用率

在 chrome 浏览器的开发者工具中,在下面窗口的Coverage窗口中可以录制代码的使用率,并且打开代码也可以看到哪些代码使用了,哪些代码没使用到,这样可以有针对性的把第一次没有用到的代码使用动态加载的方式来做,提高效率。

prefetching

在官网的概念模块讲解了 prefetching 的概念,这个就是当访问页面时,主文件先下载,等主要文件下载完了,线程有空闲了再下载prefetching的文件。
这个需要和懒加载一起使用,通过注释的方式来指定是否prefetching

1
import(/* webpackPrefetch: true */ "LoginModal");

根据文件内容命名文件

1
2
3
4
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js'
}

webpack4 之前的版本需要配置 runtime;老版本因为把 manifest 打包到了各个 chunk 中,所以老版本的 webpack 打包,即使内容没改变,打出的包的名字 hash 也可能不一样,因为 manifest 可能发生了变化。

1
2
3
4
5
optimization: {
runtimeChunk: {
name: "runtime";
}
}

library

当开发一个工具包时,我们也可以通过 webpack 进行打包,并发布到 npm 仓库中。
配置很简单,和常用的配置差别不大,甚至没那么复杂。

1
2
3
4
5
6
7
8
9
var path = require("path");

module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "webpack-numbers.js",
},
};

上面的配置就已经做完了,这样就可以进行打包了。但是可以从以下几个方面进行优化会更好:

  1. 外部化 lodash
  2. 支持多种方式访问包,比如 amd,cmd,es6 等等
  3. 把包暴露给指定的全局变量
  4. 指定包的执行文件
  5. 发布到 npm 仓库

外部化

首先介绍下什么是外部化:外部化就是使用用户环境中的第三方库,而不是把第三方库打包到我们的包中。
比如我们开发一个数字处理的工具包 A,我们的代码中用到了lodashmoment等等多种第三方包,如果不做外部化处理,这些在代码中用到的第三方包都会和我们的逻辑代码一起进行打包。这就有个问题,使用我们包 A 的用户的项目中如果也用到了lodashmoment,那就会出现重复的打包。
因此在我们的开发包 A 中不对这些第三方的包进行打包,而是让使用我们包 A 的用户去安装我们依赖的这些包,然后使用包 A 的地方也引入包 A 所依赖的包即可;
实现这个功能需要用到externals的配置

1
2
3
4
5
6
7
8
externals: {
lodash: {
commonjs: 'lodash', // 指定在commonjs环境下引入lodash的名字
commonjs2: 'lodash',
amd: 'lodash',
root: '_', // script标签引入lodash的变量名
}
}

这样我们虽然使用了 lodash,但 lodash 不会被打包到包 A 中。

支持多种方式访问包

我们的包打包后,应该支持 amd、cmd、es6 以及在文件中引入等方式的使用。实现这个功能也很简单,配置output属性的librarylibraryTarget即可。具体的参数可参见官网上的详细介绍

1
2
3
4
5
6
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack-numbers.js',
library: 'myLibrary',// 通过配置这个,可以让通过script标签的方式引入,通过全局变量myLibrary来访问
libraryTarget: 'umd'
},

libraryTarget 的值不同,包可被访问的方式就不同。

  • 变量:默认值。作为一个全局变量,通过 script 标签来访问(libraryTarget:’var’),需要配置 library 属性来指定变量的名字。
  • this:通过 this 对象访问(libraryTarget:’this’)。
  • window:通过 window 对象访问,在浏览器中(libraryTarget:’window’)。
  • UMD:在 AMD 或 CommonJS 的 require 之后可访问(libraryTarget:’umd’)。

    只配置libraryTarget不支持通过 script 标签的方式引入。

指定包的执行文件

当别人使用我们的包时,加载的是哪个文件可以在 package.json 中的 main 字段进行配置。

1
main: "./dist/webpack-numbers.js";

发布到 npm 仓库

首先需要在 npm 官网上有一个账号。在命令行中运行npm adduser,然后输入用户名和密码,接着运行发布命令npm publish,这样你的 npm 包就发送完成了,包名就是 package.json 中 name 指定的名字。npm install 包名就可以安装了。

动态链接库用的也是这块的功能。

文章作者: wenmu
文章链接: http://blog.wangpengpeng.site/2020/01/09/%E4%BB%8E%E5%9F%BA%E7%A1%80%E5%88%B0%E5%AE%9E%E6%88%98%20%E6%89%8B%E6%8A%8A%E6%89%8B%E5%B8%A6%E4%BD%A0%E6%8E%8C%E6%8F%A1%E6%96%B0%E7%89%88Webpack4.0-2/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 温木的博客
微信打赏