Webpack5使用手册
安装
全局安装
npm i webpack webpack-cli -g
本地安装
npm i webpack webpack-cli -D
本地打包指令
npx webpack
npx webpack --watch //监测变化并重新编译打包
使用配置文件进行打包
const path = require('path')
module.exports = {
entry: './assets/js/main.js', //入口文件
output: { //出口文件及其路径
filename: 'app.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
]
},
plugins: [
//此处即为插件
],
mode: 'development'
}
Plugin
定义
webpack中的plugin用于处理更宽广的业务。例如打包优化和压缩等功能性操作。具体内容看具体的插件
webpack官网中有三种类型的插件:社区的、官方的、第三方的
插件参考文献:webpack.js.org/plugins/
【社区】html-wepack-plugin
作用
生成一个html5文件,会在Body里面使用标签引入webpack生成的Bundle
安装指令
npm install html-webpack-plugin -D //本地安装
Webpack-dev-server
定义
提供一个基础web server,并具有实时重新加载的功能
指令
npm install webpack-dev-server -D //本地安装
npx webpack-dev-server //启动
资源模块 Asset Modules
定义
它允许使用资源文件(字体,图标等)而无需配置额外 loader。
-
asset/resource:发送一个单独的文件并导出 URL
-
asset/inline:导出一个资源的 Data URI ( 64位图 )
-
asset/source:导出资源的源代码
-
asset:在导出一个资源的 Data URI 和发送一个单独的文件之间自动进行选择
// js 文件导入 import 命名 from '资源路径' // css 文件引用 .box { background-image: url('资源路径'); }
assets/resource 文件url
当前文件在assets中存在
webpack具体配置文件
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'), //_dirname为webapck所在路径
clean: true, //每次打包清除dist
assetModuleFilename: 'images/[contenthash][ext]' //根据文件内容生成哈希+文件拓展名 = 资源文件名以及打包后的路径
},
mode: 'development', //设置开发模式
devtool: 'inline-source-map',
plugins: [
//使用HtmlwebpackPlugin进行生成html文件,会自动引入webpack打包的bundle
new HtmlWebpackPlugin({
template: './index.html', //模板文件
filename: 'app.html', //文件名称
inject: 'body' //bundle插入的位置(默认为head)
})
],
devServer: {
static: './dist' //静态路径
},
module: {
rules: [{
test: /.png$/, //.png结尾的文件
type: 'asset/resource', //生成文件的url
generator: { //文件生成路径以及文件名称【优先级会比assetModuleFilename要高】
filename: 'images/[contenthash][ext]'
}
},
{
test: /.svg$/,
type: 'asset/inline', //生成文件的base64
},
{
test: /.txt$/,
type: 'asset/source', //生成文件的源代码
}, {
test: /.jpeg$/,
type: 'asset', //系统根据文件大小自动选择resource 或者 inline 临界值8k >8k resouce ,<8k inline
parser: {
dataUrlCondiction: {
maxSize: 4 * 1024 //临界值 8k
}
}
}
]
}
}
loder
定义
webpack中管理资源模块,本来webpack只能处理js文件,通过loader可以加载转化其他文件进行打包处理。
加载css
npm install css-loader -D //本地安装css-loader 可处理css文件
npm install style-loader -D //style-loader 可将css样式放在页面上
npm install less-loader less -D //less-loader 以及 Less解析 处理less样式
配置文件
module: {
...
rules: [ {
test: /.(css|less)$/,
use: ['style-loader', 'css-loader'] //此处位置不能颠倒,是从后往前加载的。需要先用css-loader来加载css文件,再用style-loader将css样式放置在页面标签上,
// use: ['style-loader', 'css-loader', 'less-loader'] less-loader最后,先用Less-loader解析css文件,将结果给css文件,css文件在将结果给style-loader
}
]
}
抽离css和压缩css
npm install mini-css-extract-plugin -D //本地抽离css文件压缩css
npm i css-minimizer-webpack-plugin -D //本地压缩css 在生产环境模式下使用 有助于css加载效率
配置文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
...
mode: 'production', //设置开发模式
devtool: 'inline-source-map',
plugins: [
...
new MiniCssExtractPlugin({
filename: 'style/[contenthash].css'
})
],
optimization: { //优化配置
minimizer: [
new CssMinimizerPlugin() //将model改为production
]
}
}
加载字体与csv、xml文件(JSON可以直接打包无需插件)
指令
npm install csv-loader -D
npm install xml-loader -D
配置文件
module: {
...
rules: [ {
test: /.(woff|woff2|eot|ttf|otf)$/,
type:'asset/resource'
},{
test: /.(csv|tsv)$/,
type:'csv-loader'
},{
test: /.xml$/,
type:'xml-loader'
}
]
}
babel-loader
用处:打包时将Es6转换为低版本Es代码,让其他浏览器也能正常运行。
- babel-loader: 在 webpack 里应用 babel 解析 ES6 的桥梁
- @babel/core: babel 核心模块
- @babel/preset-env: babel 预设,一组 babel 插件的集合
指令
npm i babel-loader @babel/core @babel/preset-env -D //本地安装babel的三个模块
配置
{//module节点下
test: /.\js$/,
exclude:/node_modules/, //过滤掉node_modules里面的
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'] //设置预设
}
}
}
注意:
regeneratorRuntime 是 webpack 打包生成的全局辅助函数,由 babel 生成,用于兼容 async/await 的语法。
npm i @babel/runtime @babel/plugin-transform-runtime -D //安装regeneratorRuntime 辅助函数
新增配置
module.exports = {
...
module: {
rules: [
{
test: /.m?js$/,
// 排除 node_modules 中安装的库
exclude: /(node_modules|bower_components)/,
use: {
// 加载 loader
loader: 'babel-loader',
options: {
// 配置预设
presets: ['@babel/preset-env']
plugins: [
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
}
}
代码分离
webpack中最引入注目的一个功能特性,可以将代码分离到不同的Bundle中,然后进行按需加载或者并行加载。使用得当可以极大的提升加载速率、以下为常用三种方法。
配置入口节点
使用entry手动分离代码,但会有问题。如果多个入口,这些多个入口共享的文件会在每个包里面重复打包。
module.exports = {
entry: { //配置多入口
index: './src/index.js',
another: './src/another-modules.js'
},
output: {
filename: '[name].bundle.js', //对应多入口进行出口文件分离
path: path.resolve(__dirname, 'dist'), //_dirname为webapck所在路径
clean: true, //每次打包清除dist
assetModuleFilename: 'images/[contenthash][ext]' //根据文件内容生成哈希+文件拓展名 = 资源文件名以及打包后的路径
},
}
📢:如果在多入口文件中引用相同的包,比如lodash。打包成两个bundle后会发现,lodash被重复打包了。
防止重复打包
使用entry dependencies 或者 splitChunksPlugin去重和分离代码
入口依赖 entry dependencies
moudle.exports = {
entry: { //配置多入口
index: {
import: './src/index.js',
dependOn: 'shared' //可以共享资源
},
another: {
import: './src/another-modules.js',
dependOn: 'shared'
},
shared: 'lodash' //设置共享的资源 shared为自定义Key值
},
output: {
filename: '[name].bundle.js', //对应多入口进行出口文件分离
path: path.resolve(__dirname, 'dist'), //_dirname为webapck所在路径
clean: true, //每次打包清除dist
assetModuleFilename: 'images/[contenthash][ext]' //根据文件内容生成哈希+文件拓展名 = 资源文件名以及打包后的路径
},
}
//输出结果 index.bundle.js another.bundle.js shared.bundle.js
//会将index、another中的lodash 分离出来 打包成为shared.bundle.js
splitChunks 自动分离
module.exports = {
entry: { //配置多入口
// index: {
// import: './src/index.js',
// dependOn: 'shared' //可以共享资源
// },
// another: {
// import: './src/another-modules.js',
// dependOn: 'shared'
// },
// shared: 'lodash' //设置共享的资源
index: './src/index.js',
another: './src/another-modules.js'
},
...
optimization: { //优化配置
minimizer: [
new CssMinimizerPlugin() //将model改为production
],
splitChunks: { //自动抽离相同资源代码 Lodash这种
chunks: 'all'
}
}
}
//输出结果 会多出两个bundle vendor/babel runtime helper bundle.js 发现index another中体积小了很多
动态导入
通过模块import内联函数来分离代码
懒加载
定义:也叫按需加载,可以极大优化首页加载的速度
//index.js
const addButton = document.createElement('button')
addButton.textContent = "执行加法运算"
//添加事件 通过动态导入的方式
addButton.addEventListener('click', () => {
//使用魔法值修改math.js打包后的bundle名字
import( /* webpackChunkName:'math'*/ './math').then(({
add
}) => {
alert(add(4, 5))
})
})
//将button放置在页面上
document.body.appendChild(addButton)
注意📢:只有在按钮被点击后math.bundle.js才会被网络加载,效果非常好
预获取/预加载
-
预获取prefetch:将来某些导航可能需要的资源
- 在浏览器network中看到文件会被导入,但element标签中发现多了一个。这种加载是在所有资源加载完之后,网络空闲时间,再进行加载
- 使用效果会比预加载或者懒加载要好
-
预加载preload:当前导航下可能需要的资源
- 与懒加载类似
缓存
output: {
filename: '[name].[contenthash].js', //对应多入口进行出口文件分离
path: path.resolve(__dirname, 'dist'), //_dirname为webapck所在路径
clean: true, //每次打包清除dist
assetModuleFilename: 'images/[contenthash][ext]' //根据文件内容生成哈希+文件拓展名 = 资源文件名以及打包后的路径
},
【缓存业务文件】出口bundel文件 根据contentdash修改文件名称,可以让浏览器缓存更新
【缓存第三方】一般不变的资源,可以提高首屏加载速度,节省网络流量
module.exports = {
...
splitChunks: {
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
【将所有打包出来的js放到一个目录下】
module.exports = {
...
output: {
filename: 'sciprts/[name].[contenthash].js', //对应多入口进行出口文件分离 直接加路径即可
...
},
}
\