1.资源缓存:【作用:让代码上线运行缓存更好使用】
修改文件名后面带有hash值:.[hash:10]:每次webpack打包成功都会生成唯一hash值
问题:css和js文件同时使用一个hash值,如果只修改了css文件,重新打包的话会导致js文件的缓存失效
chunkhash:.[chunkhash:10]:根据chunk生成的hash值,如果打包来源于同一个chunk,那么hash值一样。(在js中引入css文件的话,打包后同属于一个chunk),所以,如果只修改了css文件,重新打包的话会导致js文重新加载
contenthash:.[contenthash:10] 根据文件内容生成hash值,不同的文件hash值不一样,就可以解决上面的问题
2、tree shaking:移除 JavaScript 上下文中的未引用代码(dead-code),减少代码体积。
你可以将应用程序想象成一棵树。绿色表示实际用到的 source code(源码) 和 library(库),是树上活的树叶。灰色表示未引用代码,是秋天树上枯萎的树叶。为了除去死去的树叶,你必须摇动这棵树,使它们落下。
使用:
- 使用 ES2015 模块语法(即
import
和export
)。 - 确保没有编译器将您的 ES2015 模块语法转换为 CommonJS 的(顺带一提,这是现在常用的 @babel/preset-env 的默认行为,)。
- 在项目的
package.json
文件中,添加"sideEffects"
属性。 - 使用
mode
为"production"
的配置项以启用更多优化项,包括压缩代码与 tree shaking。
"sideEffects": false
上述配置代表所有代码都没有副作用,都可以进行tree shaking,但是会把css/@babel/polyfill文件干掉
所以需要修改配置为:写在数组中的文件不会被tree shaking
"sideEffects": ["*.css"]
3、code split:代码分割
方式一:配置多个入口文件,一个入口会对应输出一个bundle
module.exports = {
entry:{
index: './src/js/index.js',
test: './src/js/test.js'
},
output:{
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build')
},
}
缺点:不太灵活,
方式二:可以将node_modules中的代码单独打包一个chunk最终输出【vue-cli默认打包就是这样的】;
module.exports = {
optimization: {
splitChunks: {
chunks: 'all'
}
}
}
多入口文件下,假如两个js文件同时引入了jquery,以上配置会最终打包成一个jquery的chunk,否则会打包两份。也就是说它可以分析多入口chunk中有没有公共的文件(文件体积稍大的),如果有的话会打包成单独一个chunk
方法三:[一般使用这种方法]
import动态导入语法:能将某个文件单独打包成一个chunk
import(/* webpackChunkName: 'test' */'./test')
.then(({mul, count}) => {
console.log(mul(2. 5));
})
.catch(() => {
console.log('文件加载失败')
})
4.lazy loading懒加载:对js进行懒加载
现有两个js文件,index.js和test.js,当点击按钮的时候再加载test.js文件,
5.预加载:prefetch,会在使用之前提前加载js文件
页面初始化时network中可以看到加载了test.js文件,点击按钮的时候会读取缓存,重新加载js文件
那么疑问来了,既然预加载会直接加载js文件,为什么还要放在函数里呢,和被注释掉的代码有什么却别呢?
预加载:会在浏览器加载完其他文件后,空闲的时候再偷偷加载文件,相对于懒加载的好处是,当要加载的文件体积较大时 会造成用户体验不。但是预加载的兼容性较差,甚用!
6.PWA:渐进式网络开发应用程序 让项目变成离线也可以访问的效果
1.安装插件
npm install workbox-webpack-plugin --save-dev
2.引入插件并使用,插件会帮我们生成一个service-worker 配置文件
const WorkboxPlugin = require('workbox-webpack-plugin');
module.exports = {
plugins: [
new WorkboxPlugin.GenerateSW({
// 这些选项帮助快速启用 ServiceWorkers
// 不允许遗留任何“旧的” ServiceWorkers
clientsClaim: true,
skipWaiting: true,
}),
],
};
3.在入口文件中注册service work
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js').then(registration => {
console.log('SW registered: ', registration);
}).catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
});
}
4.service work代码必须运行在服务器上,我们可以借助插件来实现:
a.安装:
npm install http-server --save-dev
b.修改 package.json
的 scripts
部分,来添加一个 start
script:
dist是我们打包后的文件夹
{
...
"scripts": {
"build": "webpack",
"start": "http-server dist"
},
...
}
c.运行命令就启动服务器啦
npm start
打开页面,可以观察application中的service workers、cache storage模块
把浏览器的network调成offline,刷新页面就可以验证了
7.externals:防止将某些 import
的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。
例如index.html中引入的jquery是从cdn上引入的
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous"
></script>
webpack.config.js
module.exports = {
//...
externals: {
// 拒绝jquery被打包进来
jquery: 'jQuery',
},
};
8.DLL:动态链接库,
安装插件:dll-reference-plugin、add-asset-html-plugin
a.创建webpack.dll.js文件:使用dll技术,对某些库(第三方库:jquery、react、vue...)进行单独打包
const webpack = require('webpack')
const path = require('path')
module.exports = {
entry: {
// 最终打包生成的名称:要打包的库
react: ['react', 'react-dom']
},
output: {
library: 'react', // 以一个库的形式导出
filename: '[name].dll.js'
},
plugins: [
// 打包生成一个mainfest.json->提供和react映射
new webpack.DllPlugin({
name: 'react', // 映射库的暴露的内容名称
path: path.resolve(__dirname, 'dist/manifest.json') // 输出文件路径
})
]
}
生成一个 react.dll.js打包文件和一个结构文件manifest.json,manifest.json用于读取打包前文件后打包后文件的对应关系,
可能会有多组文件需要打包。
b.配置打包命令
"script" : {
"dll": "webpack --config webpack.dll.js --mode=development"
}
c.webpack.config.js中
plugins: [
// 告诉webpack那些库不参与打包,同时使用时的名称也得变
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dist/manifest.json')
}),
// 将某个文件打包输出去,并在html中自动引入该资源
new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, 'dist/react.dll.js')
})
]