HMR热更新
一个模块发生变化只打包这个模块。
样式文件:配合style-loader内部实现HMR
js文件: 默认不实现HMR
html文件:默认不实现HRM
cssHMR
module.exports={
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader', //配套host实现css热更新
'cass-loader'
]
}
]
},
devServer:{
hot:true
}
}
HTMLHMR
// 入口引入,html文件。html就一个文件无需实现HMR
module.exports={
entry:['./index.js','./index.html'],
devServer:{
host:true
}
}
jsHMR
只处理非入口文件
// index.js 文件嵌入代码
if(module.hot){
//说明开启了HMR
module.hot.accept('./modulePath',function(){
//监听模块的变化,一旦发生变化,其他模块不会重新打包。
// 本回调将被执行
})
}
source-map
提供源代码到构建后代码映射技术
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
inline:map.js内联,在代码最未。增加文件体积eval: map.js内联,在每个文件代码后嵌入。增加文件体积cheap:定位到行module: 会将loader的souce map加入
| devtool | 构建速度 | 重新构建速度 | 生产环境 | 调试位置 |
|---|---|---|---|---|
| (none) | +++ | +++ | yes | 无映射代码,打包后的代码 |
| eval | +++ | +++ | no | 生成后的代码 |
| cheap-eval-source-map | + | ++ | no | 转换过的代码(仅限行) |
| cheap-module-eval-source-map | o | ++ | no | 原始源代码(仅限行) |
| eval-source-map | -- | + | no | 原始源代码 |
| cheap-source-map | + | o | yes | 转换过的代码(仅限行) |
| cheap-module-source-map | o | - | yes | 原始源代码(仅限行) |
| inline-cheap-source-map | + | o | no | 转换过的代码(仅限行) |
| inline-cheap-module-source-map | o | - | no | 原始源代码(仅限行) |
| source-map | -- | -- | yes | 原始源代码,代码的错误位置 |
| inline-source-map | -- | -- | no | 原始源代码,的错误位置 |
| hidden-source-map | -- | -- | yes | 原始源代码 |
| nosources-source-map | -- | -- | yes | 无源代码内容 |
oneof
oneof中的laoder只会使用一个
module.exports={
module:{
rules:[
{
//一下loader只会匹配一个
oneOf:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
}
]
}
]
}
}
多进程打包
进程启动时间600ms,进程通信也需耗时。所以消耗时间长的loader,才需多进程打包
// npm i thread-loader
module.exports={
module:{
rules:[
{
test:/\.js$/,
use:[
{
loader:'thread-loader',
// 可设置cup核数,默认进程为cpu核数-1
options:{
workers:2 //进程2
}
}
'babel-loader'
]
}
]
}
}
缓存
- babel缓存
module.exports={
module:{
rules:[
{
test:/\.js$/,
loader:'babel-loader',
options:{
cacheDirectory:true
}
}
]
}
}
- 文件资源缓存
[hash]每次webpack构建会生成一个唯一的hash,每次重新打包hash都会变。缓存无效[chunkhash]:根据chunk生成hash,如果所打的包来源于同一个chunk,hash是一样的,css在js中被引入属于同一个chunk。[contenthash]:根据内容生成hash。
生产使用
contenthash文件打包+服务器缓存配合使用
tree shaking
去除无用的代码
- 条件:使用
es6模块化、mode='production' - 有的版本可能会把需要的代码删了
//package.json
{
"sideEffects":false //所有代码都可以tree shaking
// 会删除.css @babel/polyfill等引入未直接调用的文件
}
//package.json
{
"sideEffects":["*.css","*.less"] //不删除的文件
}
code split
- 多入口,多出口
import { resolve } from 'path';
module.exports={
entry:{
mian:'./src/main.js',
index:'./src/index.js'
},
output:{
filename:'js/[name].[contenthash:10].js',
path:resolve(__dirname,'dist')
}
}
optimization第三方模块单独打成一个包
module.exports={
entry:'./src/index.js',
output:{
filename:'js/[name].[contenthash:10].js',
path:resolve(__dirname,'dist')
},
optimization:{
splitChunks:{
chunks:'all'
}
},
/*
将当前模块的记录其他模块的hash单独打包成一个文件,
解决当文件内容发生变化时contenthash发生变化,导致应用此模块的js文件内容变化
(js文件引用文件引用的是打包后的文件名)
*/
runtimeChunk:{
name:entrypoint=>`runtime-${entrypoint.name}`
}
}
js实现代码分隔 webpack.config.js
module.exports={
entry:'./src/index.js',
output:{
filename:'js/[name].[contenthash:10].js',
path:resolve(__dirname,'dist')
},
}
index.js
import(/webpackChunkName:'test'/'./test.js');
console.log('index')
// 会成两个js文件
懒加载 预加载
- 懒加载:需要使用的时候加载
document.querySelector('.btn').onClick=function(){
import(/*webpackChunkName:'test'*/'./test.js')
}
- 预加载:其他资源加载完毕,空闲时在加载文件(兼容性差)
document.querySelector('.btn').onClick=function(){
import(/*webpackChunkName:'test',webpackRrefetch:true*/'./test.js')
}
dll
对第三方库单独打包
// webpack.dll.config.js
const { resolve } = require('path');
const webpack = require('webpack');
module.exports={
entry:{
/*
vendor最终生成的名字,要打的包['moment']
*/
vendor:['moment'],
}
output:{
filename:'[name].js',
path:resolve(__dirname,'dll'),
library:'[name]_[hash]' //向外暴露内容的名字
},
plugins:[
//作用生成一个manifest.json --> 提供与包的映射关系
new webpack.DllPlugin({
name:'[name]_[hash].js',
path:resolve(__dirname,'dll/mainfest.json')
})
],
mode:'production'
}
// package.json
webpack --config webpack.dll.config.js
webpack排除已打包的第三方库及html自动引入
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
module.exports={
plugins:[
new webpack.DllReferencePlugin({
manifest: resolve(__dirname,'dll/manifest.json')
}),
//在html中自动引入资源
new AddAssetHtmlWebpackPlugin({
filePath:resolve(__dirname,'dll/vendor.js')
})
]
}
externals
module.exports={
// 拒绝包打入
externals:{
// 包名:npm下载的包名
jquery:'jQuery'
}
}