1.webpack的安装
- 全局安装 npm i webpack webpack-cli —global ,通过全局进行安装(不推荐) 好处:无论是在哪个目录下面都可以访问到webpack 不推荐的原因是 1.会让你的webpack锁定在某个版本 2.在不同项目中使用同样的webpack可能会导致构建失败 3.团队协作中,构建也会出现问题
- 项目中安装npm i webpack webpack-cli —sava-dev,项目中安装(推荐)
在项目安装之前,我们要通过npm init -y进行package.json的文件初始化
2.运行webpack
1.要对我们的代码进行修改,通过es module的导入导出修改
function webpack(){
console.log("webpack")
}
export default webpack
import webpack from './demo'
webpack()
2.在项目的根目录的终端中,直接使用 webpack(全局的webpack命令)或者npx webpack(项目本地) 命令项目打包,在项目的根目录上就会多一个dist的文件,这就是webpack对项目进行打包生成的文件
3.在终端中输入webpack —stats detailed会有webpack打包的详细信息
3.webpack配置命令
npx webpack —help查看webpack的options
npx webpack —entry ./src/index.js —mode production 设置webpack打包的入口
4.webpack自定义配置
通过 webpack.config.js进行自定义配置,并且是运行在node环境下的,所以要使用commonjs的方式进行配置,所以得使用module.exports = { } 模块
const path = require('path')
module.exports = {
// 打包的入口文件
entry:'./src/index.js',
// 打包输出文件
output:{
// 打包完成的文件名
filename:'bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' )
},
mode:'none'
}
5.webpack工作流
6.webpack的plugins(插件)
1.HtmlWebpackPlugin
1.安装HtmlWebpackPlugin(自动引入资源文件)
npm install --save-dev html-webpack-plugin
2.配置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' )
},
mode:'none',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body'
})
]
}
3.执行npx webpack
2.清理dist(打包之后的文件夹)— 原因:每一次打包都会生成对应html文件或者js文件,我们希望在打包的时候,把旧的文件全部清空,打包完成后,dist里面只有我们最新打包好的文件
需要在webpack.config.js中进行选项的配置
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' ),
// 清理dist的旧文件
clean:true
},
mode:'none',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body'
})
]
}
3.当我们编写的代码出错的时候,我们可以通过配置webpack.config.js进行精确定位的配置
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' ),
// 清理dist的旧文件
clean:true
},
mode:'none',
// source-map
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body'
})
]
}
4.watch mode(观察者)
通过npx webpack --watch 实时编译打包
5.webpack-dev-server(似live-server的插件)
webpack-dev-server为你提供了一个基本的web server,并且具有live reloading(实时重新加载)功能
1.安装
npm install -- save-dev webpack-dev-server
2.配置webpack.config.js
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' ),
// 清理dist的旧文件
clean:true
},
mode:'none',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body'
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
}
}
3.这个webpack.config.js是放在内存中的,无论你删不删dist/app.html,都会触发 热更新 以及 实时打包
7.资源模块
1.Resource资源
1.配置webpack.config.js(第一种方法)
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' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'none',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
test: /.png$/, //以png结尾的图片资源
type: 'asset/resource' // 类型为Resource资源
}
]
}
}
2.配置webpack.config.js(第二种方法)
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' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'none',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
test: /.png$/, // 以png结尾的图片资源
type: 'asset/resource', // 类型为Resource资源
generator: { // 和上面output一样的配置
// filename: 'images/test.png',
filename: 'images/[contenthash][ext]'
}
}
]
}
}
注意:第二种配置的优先级比第一种的优先级高,因为该配置是在module模块里面的
2.inline资源
1.配置webpack.config.js
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' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'none',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// Resource资源
{
test: /.png$/, // 以png结尾的图片资源
type: 'asset/resource', // 类型为Resource资源
generator: { // 和上面output一样的配置
filename: 'images/[contenthash][ext]'
}
},
// inline资源
// 在dist目录下是看不到资源的,只能在浏览器中查看,并且是个base64的格式
{
test: /.svg$/,
type: 'asset/inline', // inline资源
}
]
}
}
3.source资源(导入资源的源代码)
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' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'none',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// Resource资源
{
test: /.png$/, // 以png结尾的图片资源
type: 'asset/resource', // 类型为Resource资源
generator: { // 和上面output一样的配置
filename: 'images/[contenthash][ext]'
}
},
// inline资源
{
test: /.svg$/,
type: 'asset/inline', // inline资源
},
// source资源
{
test: /.txt$/,
type: 'asset/source', // source资源
}
]
}
}
4.通用数据类型(通用资源类型asset ,在导出一个data URI和发送一个单独的文件之间自动选择(在asset /inline和asset /resource))
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' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'none',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// Resource资源
{
test: /.png$/, // 以png结尾的图片资源
type: 'asset/resource', // 类型为Resource资源
generator: { // 和上面output一样的配置
filename: 'images/[contenthash][ext]'
}
},
// inline资源
{
test: /.svg$/,
type: 'asset/inline', // inline资源
},
// source资源
{
test: /.txt$/,
type: 'asset/source', // source资源
},
// 通用资源
{
test: /.jpg$/,
type: 'asset', // 通用资源
},
]
}
}
2.为什么说它会做自动选择呢,默认当资源大于8k,走的是resource资源,小于8k,走的是inline资源
3.修改asset临界值
module:{
// 资源模块规则
rules:[
// Resource资源
{
test: /.png$/, // 以png结尾的图片资源
type: 'asset/resource', // 类型为Resource资源
generator: { // 和上面output一样的配置
filename: 'images/[contenthash][ext]'
}
},
// inline资源
{
test: /.svg$/,
type: 'asset/inline', // inline资源
},
// source资源
{
test: /.txt$/,
type: 'asset/source', // source资源
},
// 通用资源
{
test: /.jpg$/,
type: 'asset', // 通用资源
// 解析器
parsar:{
dataUrlCondition:{
// 4M
maxSize: 4 * 1024 * 1024
}
}
},
]
}
8.loader
1.loader加载CSS模块,并且要
1)安装npm i style-loader -D,作用帮助我们把CSS放在页面上
2)如果使用了sass,less等预处理器,要安装
npm i less-loader less
npm i sass-loader sass
1.普通的css
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' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'none',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// loader加载CSS模块
{
test: /.css$/,
// 先执行css,再执行style,从后往前加载
use: ['style-loader','css-loader']
}
]
}
}
2.使用预编译sass,less
// 资源模块
module:{
// 资源模块规则
rules:[
// loader加载CSS模块
{
test: /.(css | less)$/,
// 先执行css,再执行style,从后往前加载,如果存在的less或者sass
use: ['style-loader','css-loader','less-loader']
}
]
}
2.抽离和压缩CSS
抽离:npm i mini-css-extract-plugin -D (基于webpack5构建的)
压缩:npm i css-minimizer-webpack-plugin -D
1.抽离
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// 打包的入口文件
entry:'./src/index.js',
// 打包输出文件
output:{
// 打包完成的文件名
filename:'bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'none',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// loader加载CSS模块
{
test: /.css$/,
use: [ MinCssExtractPlugin.loader,'css-loader' ]
}
]
}
}
2.压缩
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:'./src/index.js',
// 打包输出文件
output:{
// 打包完成的文件名
filename:'bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// loader加载CSS模块
{
test: /.css$/,
use: [ MinCssExtractPlugin.loader,'css-loader' ]
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
]
}
}
3.加载font字体
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:'./src/index.js',
// 打包输出文件
output:{
// 打包完成的文件名
filename:'bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// 加载font字体
{
test: /.(woff | woff2 | eot | tff | otf )$/,
type: 'asset/resource'
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
]
}
}
4.加载数据
要先安装两个loader
npm i csv-loader xml-loader
data.xml会转化为对象
data.csv会转化为数组
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:'./src/index.js',
// 打包输出文件
output:{
// 打包完成的文件名
filename:'bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// 加载数据
{
test: /.(csv | tsv )$/,
use: 'csv-loader'
},
{
test: /.xml$/,
use: 'xml-loader'
},
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
]
}
}
5.自定义JSON模块parser
安装模块包:npm install toml yaml json5 -D
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const toml = require('toml')
const yaml = require('yaml')
const json5 = require('json5')
module.exports = {
// 打包的入口文件
entry:'./src/index.js',
// 打包输出文件
output:{
// 打包完成的文件名
filename:'bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
// 加入toml
{
test:/.toml$/,
type:'json',
parser:{
parse:toml.parse
}
},
// 加入yaml
{
test:/.yaml$/,
type:'json',
parser:{
parse:yaml.parse
}
},
// 加入json5
{
test:/.json5$/,
type:'json',
parser:{
parse:json5.parse
}
},
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
]
}
}
9.babel-loader(ES6→ES5的解析器,比如Promise)
首先安装三个包
npm install -D babel-loader @babel/core @babel/preset-env
- bafel-loader :在webpack里应用babel解析ES6的桥梁
- ababel/core : babel核心模块
- ababel/preset-env : babel预设,一组babel插件的集合
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:'./src/index.js',
// 打包输出文件
output:{
// 打包完成的文件名
filename:'bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env']
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
]
}
}
2.regeneratorRuntime插件
regeneratorRuntime 是webpack打包生成的全局辅助函数,由babel生成,用于兼容async/await的语法。regeneratorRuntime is not defined这个错误显然是未能正确配置babel
#这个包中包含了regeneratorRuntime,运行时需要
npm install --save @babel/runtime
#这个插件会在需要regeneratorRuntime的地方自动require导包,编译时需要
npm install --save-dev @babel/plugin-transform-runtime
#更多参考这里
https://babeljs.io/docs/en/babel-plugin-transform-runtime
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:'./src/index.js',
// 打包输出文件
output:{
// 打包完成的文件名
filename:'bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
]
}
}
10.代码分离
1.入口起点
这是迄今为止最简单直观的分离代码的方式。不过,这种方式手动配置较多,并有一些隐患,我们将会解决这些问题。
存在问题:一个loadsh的包会分别打包到不同的html中
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:{
index:'./src/index.js',
another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'[name].bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
]
}
}
2.防止重复(本质就是对工具包的单独抽离)
1)第一种防止重复
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:{
index:{
import:'./src/index.js',
dependOn:'shared'
},
another:{
import:'./src/another_module.js',
dependOn:'shared'
},
// 共享包
shared:'lodash'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'[name].bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
]
}
}
2)使用优化配置
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:{
index:'./src/index.js',
another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'[name].bundle.js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
],
// 拆分代码
splitChunks:{
chunks:'all'
}
}
}
3.动态引入
当涉及到动态代码拆分时, webpack提供了两个类似的技术。第一种,也是推荐选择的方式是,使用符合 ECMAScript提案的 import()语法来实现动态导入。第二种,则是webpack的遗留功能,使用webpack'特定的require.ensure。
4.懒加载
懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。
5.预获取/预加载模块
Webpack v4.6.0+增加了对预获取和预加载的支持。 在声明import时,使用下面这些内置指令,可以让webpack输出"resource hint(资源提示)",来告知浏览器:
- prefetch(预获取):将来某些导航下可能需要的资源
- preload(预加载):当前导航下可能需要资源
11.缓存
1.输出文件的文件名
我们可以通过替换output.filename 中的substitutions 设置,来定义输出文件的名称。webpack提供了一种使用称为 substitution(可替换模板字符串)的方式,通过带括号字符串来模板化文件名。其中,[contenthash]substitution将根据资源内容创建出唯一hash。当资源内容发生变化时, [contenthash]也会发生变化。
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:{
index:'./src/index.js',
// another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'[name].[contenthash].js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
],
// 拆分代码
// splitChunks:{
// chunks:'all'
// }
}
}
2.缓存第三方库
将第三方库(library)(例如 lodash)提取到单独的 vendor chunk文件中,是比较推荐的做法,这是因为,它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用client 的长效缓存机制,命中缓存来消除请求,并减少向server获取资源,同时还能保证client代码和server代码版本一致。我们在 optimization.splitChunks 添加如下cacheGroups参数并构建
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:{
index:'./src/index.js',
// another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'[name].[contenthash].js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
],
//拆分代码
splitChunks:{
cacheGroups:{
vendor: {
// 通过文件目录的名字去识别
test: /[\/]node_modules[\/]/,
// 打包的名字
name:'vendors',
// 对所有的chunks做处理
chunks:'all'
}
}
}
}
}
3.将js文件放到一个文件夹中 目前,全部js文件都在dist文件夹根目录下,我们尝试把它们放到一个文件夹中,这个其实也简单,修改配置文件,在output修改filename
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:{
index:'./src/index.js',
// another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'scripts/[name].[contenthash].js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
],
//拆分代码
splitChunks:{
cacheGroups:{
vendor: {
test: /[\/]node_modules[\/]/,
name:'vendors',
chunks:'all'
}
}
}
}
}
12.拆分开发环境和生产环境
1.公共路径
publicPath配置选项在各种场景中都非常有用。你可以通过它来指定应用程序中所有资源的基础路径。 ·基于环境设置 在开发环境中,我们通常有一个assets/文件夹,它与索引页面位于同一级别。这没太大问题,但是,如果我们将所有静态资源托管至CDN,然后想在生产环境中使用呢? 想要解决这个问题,可以直接使用一个environment variable(环境变量)。假设我们有一个变量ASSET_PATH:
const path = require('path')
module.exports = {
// 打包的入口文件
entry:{
index:'./src/index.js',
// another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'scripts/[name].[contenthash].js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]',
publicPath:'http://localhost:8080'
},
mode:'production',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
}
}
2.环境变量
想要消除 webpack.config.js在开发环境和生产环境之间的差异,你可能需要环境变量(environmentvariable)。 webpack 命令行环境配置的--env 参数,可以允许你传入任意数量的环境变量。而在 webpack.config.js中可以访问到这些环境变量。例如,--env production或--env goal=local。 npx webpack --env goal=local --env production --progress 对于我们的webpack配置,有一个必须要修改之处。通常, module.exports指向配置对象。要使用env变量,你必须将module.exports转换成一个函数︰
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
// 使用npx webpack --env production --env name:'zhangsan'
// 在env中打印 env.name 就可以打印出zhangsan
module.exports = (env) => {
return {
// 打包的入口文件
entry:{
index:'./src/index.js',
// another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'scripts/[name].[contenthash].js',
// 存放目录
path: path.resolve( __dirname,'./dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]',
publicPath:'http://localhost:8080'
},
mode:env.production ? 'production' : 'development',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
],
//拆分代码
splitChunks:{
cacheGroups:{
vendor: {
test: /[\/]node_modules[\/]/,
name:'vendors',
chunks:'all'
}
}
}
}
}
}
打包好了之后,发现我们代码没有进行压缩,这时候我们要对代码进行压缩,可以通过
安装terser插件:npm install terser-webpack-plugin -D
配置webpack
const TerserWebpackPlugin = require('terser-webpack-plugin')
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin(),
new TerserWebpackPlugin ()
],
}
3.拆分配置文件
目前,生产环境和开发环境使用的是一个配置文件,我们需要将这两个文件单独放到不同的配置文件中。如webpack.config.dev.js(开发环境配置)和 webpack.config.prod.js (生产环境配置)。在项目根目录下创建一个配置文件夹config来存放他们。 webpack.config.dev.js 配置如下:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// 打包的入口文件
entry:{
index:'./src/index.js',
another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'scripts/[name].js',
// 存放目录
path: path.resolve( __dirname,'../dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]'
},
mode:'development',
devtool: 'inline-source-map',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// live-server
devServer:{
// 需要热更新的目录
static: './dist'
},
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
//拆分代码
splitChunks:{
cacheGroups:{
vendor: {
test: /[\/]node_modules[\/]/,
name:'vendors',
chunks:'all'
}
}
}
}
}
webpack.config.prod.js 配置如下:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MinCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')
module.exports = {
// 打包的入口文件
entry:{
index:'./src/index.js',
// another:'./src/another_module.js'
},
// 打包输出文件
output:{
// 打包完成的文件名
filename:'scripts/[name].[contenthash].js',
// 存放目录
path: path.resolve( __dirname,'../dist' ),
// 清理dist的旧文件
clean:true,
// Resource资源的文件名
// assetModuleFilename: 'images/test.png',
// 不可能所有的资源的文件名都是一样的
assetModuleFilename: 'images/[contenthash][ext]',
publicPath:'http://localhost:8080'
},
mode:'production',
plugins:[
new HtmlWebpackPlugin({
// 以index.html为模板
template:'./index.html',
// 打包出来的名字
filename:'app.html',
// 自动引入资源的script标签 注入在html中的body里面
inject:'body',
}),
// 实例化MinCssExtractPlugin
new MinCssExtractPlugin({
// 打包出来的名字
filename:'style/[contenthash].css',
})
],
// 资源模块
module:{
// 资源模块规则
rules:[
{
// 打包的文件
test:/.js$/,
// 除去node_modules里面的包
exclude:/node_modules/,
use:{
loader:'babel-loader',
options:{
presets:['@babel/preset-env'],
plugins:[
[
'@babel/plugin-transform-runtime'
]
]
}
}
}
]
},
// 优化配置
optimization: {
minimizer: [
new CssMinimizerWebpackPlugin()
],
//拆分代码
splitChunks:{
cacheGroups:{
vendor: {
test: /[\/]node_modules[\/]/,
name:'vendors',
chunks:'all'
}
}
}
}
}
4.提取公共配置
这时,我们发现这两个配置文件里存在大量的重复代码,可以手动的将这些重复的代码单独提取到一个文件里,创建webpack.config.common.js,配置公共的内容:
把env,prod公共的文件提取出来到common中
保留env,prod私有的
// 合并并配置文件,并在项目目录下创建webpack.config.js
1.npm i webpack-merge -D
// 配置webpack.config.js
const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.config.common ");
const productionConfig = require("./webpack.config.prod ");
const developmentConfig = require("./webpack.config.dev ");
module.exports = (env) => {
switch (true) {
case env.development:
return merge(commonConfig, developmentConfig);
case env.production:
return merge(commonConfig, productionconfig);
default:
return new Error("No matching configuration was found");
}
};