1. webpack-dev-server 的 hmr功能 一定要使用webpack serve --hot-only 命令启动不要用npx webpack-dev-server启动
hmr 全程为 hot module replacement 热模块替换, 把devServer属性的hot 改为true即可
需要验证三种case 改样式 改js 改html 但是我的mac可能出问题了,模块更新后没有刷新浏览器
2. source-map
方便调试 ,找到源代码到构建后代码的错误位置
开启只需要把属性 devtool: ‘source-map’ 开启即可
可选配置的语法为 [inline- | hidden- | eval- ] [nosources-] [cheap-[module-]] source-map
0.source-map 外部
错误代码的信息 和源代码位置
1.inline-source-map 内联
只生产一个内联的source-map,告诉了错误的原因 不方便调试
2.hidden-source-map 外部
告诉了错误的原因,但是没有源代码的错误位置 , 隐藏了源代码
3.eval-source-map 内联
每一个文件都生产source-map,都在eval语句中
告诉了错误的原因,但是没有源代码的错误位置
4.nosources-source-map 外部
告诉了错误的原因, 源代码 和构建后代码都隐藏了
5.cheap-source-map 外部
告诉了错误的原因,只能精确到行
6.cheap-module-source-map 外部
告诉了错误的原因,可以精确到模块
在开发环境中我们使用:cheap-module-eval-source-map
在生产环境中我们使用:cheap-module-source-map。 因为生产环境内联的包太大 ,所以要排除掉eval
3. oneOf
loader 存在的问题在于每个文件都会被所有loader 过一遍 ,但其实每个文件可能只会匹配一个loader,很少有可能一个文件匹配两个loader
此时就是oneOf上场的时候
rules: [
{
oneOf:[
{
test: /\.(jpg|png|gif|jpeg)$/,
loader: 'url-loader',
options:{
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs'
}
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
},
]
}
]
此时如果一个文件类似于 js 需要eslint 和babel同时处理的话,需要这么写:
rules: [
{
test: /\.js$/,
loader:'eslint-loader',
enforce: 'pre',
exclude:'/node_modules/',
options:{
fix: true
}
},
{
oneOf:[
{
test: /\.js$/,
loader:'babel-loader',
exclude:'/node_modules/',
options:{
presets: [
'@babel/preset-env',
// [
// '@babel/preset-env',
// {
// useBuiltIns: 'usage',
// corejs: {
// version: 3
// },
// targets: {
// // chrome: '60',
// firefox: '60',
// // safari: '10',
// // edge: '17'
// }
// }
// ]
]
}
]
}
]
4. 缓存
1, 开启babel 缓存,可以使代码在第二次本地构建时,从babel缓存中读取没有改变的js ,从而加速
cacheDirectory: true
{
test: /\.js$/,
loader:'babel-loader',
exclude:'/node_modules/',
options:{
presets: [
'@babel/preset-env',
// [
// '@babel/preset-env',
// {
// useBuiltIns: 'usage',
// corejs: {
// version: 3
// },
// targets: {
// // chrome: '60',
// firefox: '60',
// // safari: '10',
// // edge: '17'
// }
// }
// ]
],
cacheDirectory: true
}
},
2.文件缓存
1. hash
根据webpack.config.js覆盖下的内容每次计算的hash值,顺便给静态文件用了,一个文件改了所有的缓存都废了
2. chunkhash
是js chunk包的hash值 因为js 和css 在一个chunk下所以会一样 ,js改了,css缓存也废了
3. contenthash 最优解
根据每个文件内容生产hash , 这样耦合度很低, 每个文件只对自己改动有影响,充分利用缓存优势
5. tree shaking
使用的前提 1,es6module 2,production环境 ,这里要说的是 如果开了生产那么就远不止 tree shaking 这么简单了,treeshaking 只是其中一项
作用 : 减少不必要代码的体积
优化tree shaking 在package.json中配置 “sideEffects”: false, 会把样式 polifill等文件 干掉, 所以正确的配置为
“sideEffects”: [".css",".less","./src/extends.js"]
6. 代码切割 code_split
webpack.config.js增加属性
optimization:{
splitChunks:{
chunks: 'all'
}
}
注意 import(’./print.js’) 也会引起chunk块的切割 一半名字按照随机id分配的; 如果想要名字 那么要这么写
// 第一步修改webpack.config.js重的 output 的chunkFilename:'js/[name].chunk.js'
// 第二步 在实际代码使用webpackChunkName
import(/* webpackChunkName: "MyFile" */'./print.js').then(res=> console.log(res));
7. 懒加载 预加载
1. 普通加载
按照正常浏览器顺序加载文件
2. 懒加载 用的最多
使用iport()语法加载的文件,在满足一定条件时才会触发加载
document.getElementById('box').onclick=function(){
import(/* webpackChunkName: "MyFile" */'./print.js').then(res=> console.log(res));
}
3. 预加载 使用注视实现,bug较多 慎用 ;通过webpackPrefetch: true 实现
在浏览器加载完成其他文件后, 在加载自己这部分文件
document.getElementById('box').onclick=function(){
import(/* webpackChunkName: "MyFile" *//*webpackPrefetch: true*/'./print.js').then(res=> console.log(res));
}
8. pwa 渐进式网页web app技术 ,可以使得网页在掉线的情况下,仍能保持部分功能
pwa 需要在server环境下验证,所以需要借助http-server 或server这种工具来模拟server环境
// 分为两步实现
// 第一步 webpack.config.js
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
new WorkboxWebpackPlugin.GenerateSW({
/**
* 1.帮助serviceWorker 快速启动
* 2,移除旧的serviceWorker
* 3,生成一个serviceWorker文件
* */
clientsClaim: true,
skipWaiting: true
})
// 第二步 在主代码中注册
if('serviceWorker' in navigator){
// 页面加载完成后加载serviceWorker
window.addEventListener('load',()=>{
navigator.serviceWorker.register('/service-worker.js')
.then(res=>{console.log('注册serviceWorker成功')})
.catch(res=>{console.log('注册serviceWorker失败')})
})
}
9. 多进程打包
使用多个进程来打包,增加打包速度,但是利用不好也会减速, 一般用于babel打包比较大的js的场景
{
test: /\.js$/,
exclude: '/node_modules/',
use: [
{
loader: 'thread-loader',
options:{
workers: 2 // 2个进程
}
},
{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
],
cacheDirectory: true
},
}
]
10. externals 属性配置
cdn配置 ,防止将cdn的库打包到最终的包中
// 分为3个步骤
// 第一步 webpack.config.js配置
externals: {
// 引用名: npm包名
jquery: 'jQuery'
}
// 第二步 在html中引入cdn
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
// 第三步 在代码中使用库,并验证打包后的体积 是否明显包含库的大小
11. dll
主要是为了分离第三方库,使之不参与打包,从而增快打包速度
前提要写一个dll相关的webapck.dll.js 来打一下第三方包, 然后在主webpack.config.js中引用这个包即可
// 分为三个步骤
// 第1步 编写webapck.dll.js 运行 webpack 命令生产第三方包 webpack --congfig webapck.dll.js
/**webapck.dll.js */
const Webpack = require('webpack');
const path = require('path');
const {resolve} = path;
module.exports = {
entry:{
// 最终的打包生产的名字 : npm包名
jquery: ['jquery'] // 可以打多个相关的库进去,一般一个
},
output:{
filename: '[name].js',
path: resolve(__dirname,'dll'), // 文件路径
library: '[name]___[hash]' // 打包出去的库的内容暴露出去的名字
},
plugins:[
// 生成 mainfest.json 建立起 当前打的包和node_modules中的对应包的关系
new Webpack.DllPlugin({
name: '[name]___[hash]', // 映射库里的内容 名称 和library 要一致
path: resolve(__dirname,'dll/manifest.json') // 输出文件的路径
})
]
}
// 第2步 在主配置里 引用第三方包,加快整体打包速度
const Webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
new Webpack.DllReferencePlugin({ // 告诉webpack 那些不用参与打包,同时使用时 名称也需要变化一下
manifest: resolve(__dirname,'dll/manifest.json')
}),
new AddAssetHtmlWebpackPlugin([{ // 把资源引入 并输出到html中作为cdn本地资源使用
filepath: resolve(__dirname,'dll/jquery.js'),
publicPath: '',
}])
// 第3步 在主代码中使用第三方包 验证是否有效
import $ from 'jquery';
console.log($);