1、懒加载与预加载
index.js
console.log('index');
document.querySelector('#btn').onclick=function(){
// 懒加载
import(/* webpackChunkName:'test' */'./test').then(({test1})=>{
console.log('test1test1', test1(6));
})
}
test.js
console.log('test');
export const test1 = (a)=>{
console.log('a11',a);
return a +3
}
这个时候,我点击页面的btn按钮时才会加载test.js文件
预加载
document.querySelector('#btn').onclick=function(){
// 懒加载 import语法 文件需要用的时候才加载 (会有延迟效果)
// 预加载 webpackPrefetch: true 会在使用之前提前加载js文件
// 正常加载是并行加载(同一时间加载多个文件)
// 预加载Prefetch等其他文件加载完毕,浏览器空闲了,再加载资源
import(/* webpackChunkName:'test2', webpackPrefetch:true */'./test').then(({test1})=>{
console.log('test1test1', test1(6));
})
}
2、PWA (在服务器中才行)
https://www.jianshu.com/p/74db1b1f90a7
https://www.jianshu.com/p/f28341217c4f
/**
* PWA 渐进式网络开发应用程序
* workbox --->workbox-webpack-plugin
* **/
const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
...
plugins: [
new WorkboxWebpackPlugin.GenerateSW({
// 帮助serviceworker快速启动
// 删除就的serviceworker
clientsClaim: true,
skipWaiting: true
})
index.js
// serviceWorker
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);
});
});
}
3、多进程打包,优化打包速度
项目变的庞大,文件很多的情况下,采取多进程打包
test: /\.js$/,
exclude: /node_modules/,
use: [
/**
* 开启多进程打包
* 进程开启大概600ms,进程通信也有开销
* 只有工作消耗时间比较长的时候,才需要多进程打包
* 如果小项目,文件不多,无需开启多进程打包,反而会变慢,因为开启进程是需要花费时间的
* */
{
loader: 'thread-loader',
options: {
workers: 2 // 进程2个
}
},
{
loader: 'babel-loader',
options: {
....
4、externals 不把某些文件打包
之后我们要在html中手动引入,一般使用cdn,这样可能比我们访问我们的资源要快一些。
externals: {
// 忽略库名---》npm 包名
jquery: 'jQuery'
}
5、_dll
为了把node_modules里面的代码打包成不同chunk.
上面externals是不打包jquery,通过cdn引入。下面是单独把jquery 打包出去,并引入文件 ,
需要新建一个文件
webpack.dll.js
/**
* 使用dll技术,对某些库(第三方库比如: jquery, react, vue,...)进行单独打包
* 运行webpack时,默认查找webpack.config.js配置文件
* 所以我们运行时,需要webpack --config webpack.dll.js
*
*/
const path = require('path')
const webpack = require('webpack')
module.exports={
entry:{
// 最终打包生成的[name]
// ['jquery'] 要打包的库
jquery: ['jquery',]
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dll'),
library: '[name]_[hash]', //打包库里面暴露出去的内容叫什么
},
plugins:[
// 打包生成一个json文件 ,提供映射关系
new webpack.DllPlugin({
name: '[name]_[hash]', // 映射库暴露的内容名称
path: path.resolve(__dirname, 'dll/manifest.json') // 输出的文件路径
})
]
}
然后修改 webpack.config.js
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
const webpack = require('webpack')
...
plugins:[
// 告诉webpack哪些库不参与打包,同时使用是名称也要变
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dll/manifest.json')
}),
// 将某个文件打包输出去,并在HTML中自动引入该资源
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, 'dll/jquery.js')
})
entry
/**
* entry : 入口
* 1、string ---> './src/index.js
* 单入口
* 打包形成一个chunk.输出一个bundle文件
* 此时chunk的名称默认是main
* 2、array ----> ['./src/index.js', './src/test.js']
* 多入口
* 所有入口文件最终会形成一个chunk,输出文件只有一个bundle文件
* ---》 只有HMR功能中能让html热更新生效
* 3、object
* 多入口
* 有几个入口文件就形成几个chunk,输出一个bundle文件
* 初始chunk的名称是key
*/
//入口
entry: {
index: './src/index.js'
},
output
output: {
// 文件名称(指定名称 + 目录)
filename: 'js/[name].[contenthash:5].js',
// 输出文件目录
path: path.resolve(__dirname, 'build'),
// 素有资源引入公共路径前缀
publicPath: '/',
// 非入口chunk的名称
chunkFilename: 'js/[name]_chunk.js',
library: '[name]', // 整个库向外暴露的变量名, 结合dll使用
// libraryTarget: 'window', // 变量名添加到 window上
// libraryTarget: 'gloabal', // 变量名添加到 gloabal
libraryTarget: 'commonjs', // 用模块化引用
},
loader
// loader
module: {
rules: [
{
test: /\.js$/,
// 排除
exclude: /node_modules/,
// 只坚持src下的文件
include: path.resolve(__dirname, 'src'),
// 优先执行 (比如这里先eslint通过之后,在babel-loader)
enforce: 'pre', // 'pre'优先执行 'post'延后执行
loader: 'eslint-loader',
options:{}
},
{
// loader只会匹配一个
// 由于只能匹配一个,所有如果下面有匹配两个js 一个做eslitn 一个做兼容处理, 需要提取一个到外面
oneOf: [
{
test: /\.css$/,
use: [
...
resolve 解析模考规则
module.exports = {
resolve: {
// 模块路径别名
alias: {
'@': path.resolve('src'),
components: path.resolve('src/components'),
vue$: 'vue/dist/vue.js',
},
// 省略文件后缀名 默认 js json
extensions: ['.js', '.less', '.css', '.vue', '.jsx', '.scss'],
// 告诉webpack 解析模块去哪个目录 ,比如专题项目中,每个专题文件夹直接去根目录寻找
modules: [path.resolve(__dirname, '../../node_modules'), 'node_modules']
},
optimization
optimization: {
// 将当前模块记录其他模块的hash单独打包成一个文件 runtime,这样如果a引入了b文件,a文件修改的话,不会重新打包b文件,只是会修改runtime对应hash文件
// 解决: 修改a文件导致b文件的contenthash变化
runtimeChunk:{
name: entrypotint => `runtime-${entrypotint.name}`
},
// 代码分割
splitChunks: {
chunks: 'all',
// 以下都是默认值
// miniSize: 30*1024, // 分割最小为30kb
// maxSize: 0 , // 最大没有限制
// minChunks: 1, // 要提取的chunk最少被引用1次
// maxAsyncRequests: 5, // 按需加载时并行加载的文件最大数量
// maxInitialRequests:3, //入口js文件最大并行请求数量
// automaticNameDelimiter: '~', // 命名连接符
// name: true, //可以使用命名规则
// cacheGroups:{ // 分割chunk的组
// // node_modules文件会被打包到vendors组的chunk中
// defaultVendors:{
// test: /[\\/]node_modules[\\/]/,
// priority: -10, // 优先级
// }
// },
// default:{
// // 要提取的chunk最少被引用2次
// minChunks: 2,
// //优先级
// priority: -20,
// // 如果当前要打包的模块,和之前已提取的模块是同一个,就会复用,而不是重新打包
// reuseExistingChunk: true
// }
},
minimize: true,
minimizer: [
// 修改 配置生产环境的压缩方案 js和css
// 注意如果你跟我一样也是用的webpack5学习 那么需要制定版本"terser-webpack-plugin": "^4.2.3",不然打包后失败
new TerserPlugin({
exclude: /\/excludes/,
// 开启缓存
cache: true,
// 开启多进程打包
parallel: true,
// 开启source-map // 如果在生产环境中使用 source-maps,必须设置为 true
sourceMap: true
})
]
},
webpack 常用配置解析(一)
webpack 常用配置解析(二)
webpack 常用配置解析(三)