
9、webpack-性能优化 - CDN_shimming_DLL
一、CDN
内容分发网络(Content Delivery Network 或 Content Distribution Network,缩写:CDN)
是指通过相互连接的网络系统,利用最靠近每个用户的服务器;
更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户;
来提供高性能、可扩展性及低成本的网络内容传递给用户;
在开发中,我们使用 CDN 主要是两种方式:
方式一:打包的所有静态资源,放到 CDN 服务器,用户所有资源都是通过 CDN 服务器加载的;
方式二:一些第三方资源放到 CDN 服务器上;
所有的静态资源都想要放到 CDN 服务器上,需要购买自己的 CDN 服务器;
目前阿里、腾讯、亚马逊、Google 等都可以购买 CDN 服务器;
可以直接修改 publicPath,在打包时添加上自己的 CDN 地址;
第三方库 CDN
一些比较出名的开源框架都会将打包后的源码放到一些比较出名的、免费的 CDN 服务器上:
国际上使用比较多的是 unpkg、JSDelivr、cdnjs;
国内也有一个比较好用的 CDN 是 bootcdn;
在项目中,我们如何去引入这些 CDN 呢?
在打包的时候我们不再需要对类似于 lodash 或者 dayjs 这些库进行打包;
在 html 模块中,我们需要自己加入对应的 CDN 服务器地址;
可以通过 webpack 配置,来排除一些库的打包:
在 html 模块中,加入 CDN 服务器地址:
也就是先排除掉第三方库,然后再打包好后的 index.html 中自己导入 cdn 地址
一个问题
在生产环境中使用 CDN 是可以的,但是在开发环境中,本地启动的服务器就没有必要在设置 cdn 了,所以可以在 index.html 中通过 ejs 的 if 语法来进行判断
二、shimming
shimming 是一个概念,是某一类功能的统称:
shimming 翻译过来称之为垫片,相当于给我们的代码填充一些垫片来处理一些问题
比如我们现在依赖一个第三方的库,这个第三方的库本身依赖 lodash,但是默认没有对 lodash 进行导入(认为全局存在 lodash)
那么我们就可以通过 ProvidePlugin 来实现 shimming 的效果;
注意:webpack 并不推荐随意的使用 shimming
- **Webpack 背后的整个理念是使前端开发更加模块化;
** - 也就是说,需要编写具有封闭性的、不存在隐含依赖(比如全局变量)的彼此隔离的模块;
Shimming 预支全局变量
目前 lodash、dayjs 都使用了 CDN 进行引入,所以相当于在全局是可以使用_和 dayjs 的
假如一个文件中使用了 axios,但是没有对它进行引入,那么下面的代码是会报错的
可以通过使用 ProvidePlugin 来实现 shimming 的效果:
ProvidePlugin 能够帮助我们在每个模块中,通过一个变量来获取一个 package;
如果 webpack 看到这个模块,它将在最终的 bundle 中引入这个模块;
另外 ProvidePlugin 是 webpack 默认的一个插件,所以不需要专门导入;
webpack 不建议使用 shimming
三、MiniCssExtractPlugin
MiniCssExtractPlugin 可以帮助我们将 css 提取到一个独立的 css 文件中,该插件需要在 webpack4+才可以使用。
首先,我们需要安装 mini-css-extract-plugin:npm install mini-css-extract-plugin -D
配置 rules 和 plugins:
chunkFilename 用于动态导入的包
这个再生产环境中使用,但是在开发环境中不太需要,所以可以进行判断
1 | const commonConfig = (isProduction) => { |
四、Hash、ContentHash、ChunkHash
给打包的文件进行命名的时候,会使用 placeholder,placeholder 中有几个属性比较相似:hash、chunkhash、contenthash
hash 本身是通过 MD4 的散列函数处理后,生成一个 128 位的 hash 值(32 个十六进制);
hash 值的生成和整个项目有关系:
比如我们现在有两个入口 index.js 和 main.js;
它们分别会输出到不同的 bundle 文件中,并且在文件名称中我们有使用 hash;
这个时候,如果修改了 index.js 文件中的内容,那么 hash 会发生变化;
那就意味着两个文件的名称都会发生变化;
chunkhash 可以有效的解决上面的问题,它会根据不同的入口进行借来解析来生成 hash 值:
- 比如我们修改了 index.js,那么 main.js 的 chunkhash 是不会发生改变的;
contenthash 表示生成的文件 hash 名称,只和内容有关系:
比如我们的 index.js,引入了一个 style.css,style.css 有被抽取到一个独立的 css 文件中;
这个 css 文件在命名时,如果我们使用的是 chunkhash;
那么当 index.js 文件的内容发生变化时,css 文件的命名也会发生变化;
这个时候我们可以使用 contenthash;
hash 一变都变 chunkHash 只改变当前入口 contenthash 只改变当前入口的某个文件
五、DLL
DLL 全程是动态链接库(Dynamic Link Library),是为软件在 Windows 中实现共享函数库的一种实现方式;
webpack 中也有内置 DLL 的功能,它指的是我们可以将可以共享,并且不经常改变的代码,抽取成一个共享的库;
这个库在之后编译的过程中,会被引入到其他项目的代码中;
DLL 库的使用分为两步:
第一步:打包一个 DLL 库;
第二步:项目中引入 DLL 库
注意:在升级到 webpack4 之后,React 和 Vue 脚手架都移除了 DLL 库
打包一个 DLL 库
pwebpack 帮助我们内置了一个 DllPlugin 可以帮助我们打包一个 DLL 的库文件;
使用打包的 DLL 库
代码中使用了 react、react-dom,我们有配置 splitChunks 的情况下,他们会进行分包,打包到一个独立的 chunk 中。
但是现在我们有了 dll_react,不再需要单独去打包它们,可以直接去引用 dll_react 即可:
第一步:通过 DllReferencePlugin 插件告知要使用的 DLL 库;
第二步:通过 AddAssetHtmlPlugin 插件,将我们打包的 DLL 库引入到 Html 模块
DLL 了解即可