// 在webpack.config.js中配置 hot : true
devServer : {
contentBase : path.resolve(__dirname,"build"),
compress : true,
port : 3000,
open : true,
//开启HMR热模块替换
hot : true,
}
/**
* HMR : hot moudle replacement 热模块替换/模块热替换
* 作用:一个模块发生改变,只会重新打包当前一个模块,不会影响其他模块,极大提高打包速度
*
*
*样式文件:可以使用HMR功能,因为style-loader内部已经做了功能实现
*
*
*js文件 : 默认情况下js文件是不能使用HMR功能的
* 注意:HMR功能对js的处理只能处理非入口js的其他文件。(依赖都在入口文件引入)
* 在入口文件做一下逻辑
```js
if(module.hot){
//当module.hot为true 说明开启了HMR功能,
module.hot.accept(‘xxxxx.js‘,function(){
// module.hot.accept 监听xxxxx.js 文件的变化,不会影响其他文件的打包构建。
执行方法
})
}
```js
*
*
*html文件:默认情况下htm;文件是不能使用HMR功能的,同时会导致html不能热更新,(不建议做HMR)
* 解决方案: 修改entry入口 将html文件引入
*/
//在webpack.config.js中
devtool : ‘source-map‘,
/*
source-map 提供源代码到构建后代码 映射
通俗解释:如果构建后代码报错,通过映射可以追踪到源代码报错地方。
*/
/*
devtool后面参数汇总:
source-map : 外部
错误代码准确信息 和 源代码的准确位置
inline-source-map : 内联
只会生成一个内联 source-map
错误代码准确信息 和 源代码的准确位置
hidden-source-map : 外部
错误代码的原因 但是 不会追踪到源代码的错误的位置
eval-source-map : 内联
每一个文件都生成对应的source-map 都在eval
错误代码准确信息 和 源代码的准确位置 文件会多了一个hash值
nosoureces-source-map : 外部
错误代码准确信息 但是 没有源代码信息
cheap-source-map : 外部
错误代码准确信息 和 源代码的准确位置 但是 整行都会报错,不会具体的那一段代码
cheap-module-source-map : 外部
错误代码准确信息 和 源代码的准确位置
内联 和 外部的区别 :
a: 外部生成了文件,内联没有生成文件
b: 内联构建速度更快
怎么使用source-map:
开发环境:
速度快,调试更加方便友好,
速度:
eval > inline > cheao > ...
可以组合应用:
eval-cheap-source-map
eval-source-map
调试:
source-map
cheap-module-source-map
cheap-source-map
比较好-----> eval-source-map / eval-cheap-module-source-map
生产环境:
源代码要不要隐藏?调试要不要友好
内联会让代码体积变大,所有在生产环境尽量不要使用内联
nosoureces-source-map 全部隐藏
hidden-source-map 只隐藏源代码,会提示构建后代码错误信息
比较好-----> source-map / cheap-module-source-map
*/
优化打包构建速度
优化代码运行性能
oneOf优化
moudle : {
rules : [
{
//以下loader只会匹配以下
//执行逻辑:匹配成功之后就不会再往下匹配
//注意不能有两个配置处理同一种类型文件
//如果有两个配置处理一个文件(例如:js eslint babel ) 可以把优先执行的配置单独拎出来,{ } 放在rules里面。
onnOf : [
{...配置}
]
}
]
}
缓存
//对bable缓存
{
test: /\.js$/,
exclude: /node_modules/,
loader: ‘babel-loader‘,
//开启缓存
cacheDirectory : true
}
//文件资源缓存:
/*
filename : ‘css/built.[hash:10].css‘
hash : 每次webpack构建时会生成一个唯一的hash值
问题:因为js和css同时使用一个hash值
如果重新打包会导致所有缓存失败,
filename : ‘css/built.[chunkhash:10].css‘
chunkhash : 根据chunk 生成的hash值,如果打包来源于同一个chunk 那么hash值就一样
问题:因为js和css同时使用一个hash值
filename : ‘css/built.[contenthash:10].css‘
contenthash : 根据文件内容生成的hash值,不同文件hash值不一样
*/
tree shaking 去除无用的代码
//当webpack.config.js mode:‘production‘ 则开启 tree shaking
/*
前提条件:
a: 必须使用es6模块化
b: 开启production环境
作用:减少代码体积
在package.json中配置
"sideEffects" : false,
所有代码没有副作用(都可以进行 tree shaking)
问题:可能会把css/ @babel/polyfill 文件干掉
"sideEffects" : ["*.css","*.scss"],
*/
code split ( 代码分割 )
//单入口、多入口
module.exports = {
//entry : ‘./src/main.js‘ // 单入口
//多入口
entry : {
main : ‘./src/main.js‘,
test : ‘./src/test.js‘
},
//输出配置
output : {
//name 给输出的文件命名,否则多入口输出都是一个文件名称。
filename : js[name].js,
path : path.resolve(__dirname,‘build‘)
}
}
//webpack.config.js
//将node_module中代码单独打包一个chunk输出
//会分析多入口chunk中,有没有公共的文件。如果有只打包一个
//例如 a.js b.js都依赖jquery 这样单独拎出jquery打包
module.exports = {
optimization:{
splitChunks : {
chunks : ‘all‘
}
}
}
//通过js逻辑,完成文件被单独打包一个chunk
import(/*webpacjChunkName:test*/‘.test‘)
.then(() => {
console.log(‘文件加载成功‘)
})
.catch(() => {
console.log(‘文件加载失败‘)
})
懒加载 预加载
//懒加载
//场景:当点击按钮的时候在调用某个模块、以及某个模块中的方法
//不直接 import引入 而是把引入放在逻辑里面
btn.addEventListener(‘click‘,() => {
import(/*webpacjChunkName:test*/‘./text.js‘)
.then((fn) => {
fn()
})
})
//预加载
//会在模块使用之前去加载js文件
// webpackPrefetch :true
btn.addEventListener(‘click‘,() => {
import(/*webpacjChunkName:test,webpackPrefetch :true*/‘./text.js‘)
.then((fn) => {
fn()
})
})
PWA 离线访问
//webpack.config.js配置
//安装
// $ cnpm instal work-box-webpack-plugin -D
//引入
// const WorBoxWebpackPlugin = require(‘work-box-webpack-plugin‘);
//配置
module.exports = {
plugins : [
new WorBoxWebpackPlugin({
/*
1: 使serviceworler快速启动
2:删除旧的serviceworker
生成有一个serviceworker 配置文件
*/
clientsClaim : true,
skipWaiting : true,
})
]
}
//在入口文件js中注册serviceworker
if(‘serviceworker‘ in navigator){
window.addEventListener(‘load‘,() => {
navigator.serviceworker
.register(‘./serviceworker.js‘)
.then(() => {
console.log(‘serviceworker注册成功‘)
})
.catch(() => {
console.log(‘serviceworker注册失败‘)
})
})
}
/*
注意事项:
1: eslint 不识别 window / navigator全局变量
解决:
在package.json中eslintConfig配置
"env" : {
"browser" : true
//支持浏览器端全局变量
}
2: serviceworker 必须运行在服务器上
*/
多进程打包
// cnpm install thread-loader -D
//配置 : 在 babel中使用即可
{
test: /\.js$/,
exclude: /node_modules/,
use : [
{
/*
开启多个进程打包:
进程启动大概在600ms 进程通信也有开销
只有工作消耗比较大的时候才能使用多进程打包
*/
loader : ‘thread-loader‘,
options : {
workers : 2//进程2个
}
},
{
loader: ‘babel-loader‘,
options: {
persets: [
[
‘@babel/preset-env‘,
{
useBuildIns: ‘usage‘,
corejs: {
version: 3
},
targets: {
chrome: ‘60‘,
firefox: ‘60‘,
ie: ‘9‘,
safari: ‘10‘,
edge: ‘17‘
}
}
]
]
}
}
]
}
externals (忽略某个包进行打包 : 例如忽略引入的jquery库)
//配置:只需要在webpack.config.js 添加 externals即可
externals : {
//拒绝jQuery被打包进来
//jQuery 为 npm包的名称
jquery : ‘jQuery‘
}
DLL打包
// 创建 webpack.dll.js文件
// 使用dll技术对某些库 (第三方库 : jquery、react、vue ...) 进行单独打包
const {reslove} = require(‘path‘)
const webpack = require(‘webpack‘)
module.exports = {
entry : {
//最终打包成的[name] => jquery
//[‘jquery‘] 要打包的库是 jquery
jquery : [‘jquery‘]
},
output : {
filename : ‘[name].js‘,
path : resolve(__dirname,‘dll‘),
library : ‘[name]_[hash]‘ //打包的库里面向外暴露出去的内容的名称
},
plugins : [
new webpack.DllPlugin({
name : ‘[name]_[hash]‘ //映射库的暴露的内容名称
path : resolve(__dirname,‘dll/manifest.json‘) //输出文件的路径
})
],
mode : ‘production‘
}
//webpack.config.js中配置
// 安装 引入 webpack add-asset-html-webpack-plugin
plugins : [
// 告诉webpack哪些库不参与打包,同时使用时候的名称也需要变更
new webpack.DllReferencePlugin({
manifest : path.resolve(__dirname,‘dll/manifest.json‘)
}),
//将某个文件打包输出去,并在html中自动引入
new AdAssetHtmlWebpackPlugin({
filename : path.resolve(__dirname,‘dll/jquery.js‘)
})
]
原文:https://www.cnblogs.com/bruce-w/p/14074156.html