携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
webpack5
安装文件
npm install webpack webpack-cli --save-dev
配置文件组成
//webpack.config.js
module.exports = {
//打包的入口文件
//entry: {},
entry: "",
//打包的输出文件
// output: "",
output: {},
//环境配置
mode: "",
//loader配置
module: {},
//插件
plugins: [],
//开发服务器
DevServer: {},
//监听文件打包变化
watch: true,
//监听文件打包配置选项
watchOptions: {},
//解析模块
resolve: {},
// 配置开发工具模式
devtool: "",
//第三方模块不需要webpack打包
externals: {},
//优化性能
Optimization: {},
};
-
entry
-
字符串
module.exports = { entry: "打包入口文件名", };
-
对象
module.exports = { entry: { 应用APP1: "打包入口文件名1", 应用APP2: "打包入口文件名2", }, };
-
-
output
-
单入口
module.exports = { output: { filename: "输出文件名", path: "输出指定的路径", }, };
-
多入口
module.exports = { entry: { 应用APP1: "打包入口文件名1", 应用APP2: "打包入口文件名2", }, output: { filename: "[name].js", path: __dirname + "/dist", }, };
-
-
module
module.exports = { module: { rules: [ { test: "匹配文件名正则表达式规则", use: ["loader1", "loader2"], }, { test: /\.js$/, //排除所有符合条件的模块 exclude: 排除目录, // 引入符合以下任何条件的模块 include: 检查指定目录, // 优先执行 enforce: "pre", // 延后执行 // enforce: 'post', // 单个loader用loader use: "loader1", options: {}, }, ], }, };
-
plugins
module.exports = { plugins: [ new 插件1(插件构造参数), new 插件2(插件构造参数) ], };
配置文件案例
//webpack.config.js
const path = require("path");
module.exports = {
//监听文件打包变化
watch: true,
//监听文件打包配置选项
watchOptions: {
//防抖,和函数防抖一样, 改变过程中不重新打包, 只有改变完成指定时间后才打包
aggregateTimeout: 300,
// 每隔多少时间检查一次变动
poll: 1000,
// 排除一些巨大的文件夹, 不需要监控的文件夹
ignored: /node_modules/,
},
/**
* 配置开发工具模式
*/
devtool: "source-map",
/**
* 指定打包的模式
* development: 不会对打包的JS代码进行压缩
* production: 会对打包的JS代码进行压缩
*/
mode: "development",
/**
* 指定需要打包的文件
*/
entry: "./src/index.js",
/**
* 指定打包之后的文件输出的路径和输出的文件名称
*/
output: {
/**
* 指定打包之后的JS文件的名称
*/
filename: "bundle.js",
/**
* 指定打包之后的文件存储到什么地方
*/
path: path.join(__dirname, "bundle"),
// 自动将上次打包目录资源清空
clean: true,
},
resolve: {
//别名
// alias: {
// // 创建 import 或 require 的别名,来确保模块引入变得更简单
// bootstrapcss: "bootstrap/dist/css/bootstrap.css",
// },
// 指定模块入口的查找顺序
// mainFields: ['style', 'main']
// 指定导入模块查找顺序
extensions: [".css", ".js", ".joson"],
},
/*
第三方模块不需要webpack打包
* */
externals: {
/*
通过import导入jquery模块时,
它不是通过node_modules中导入jquery,
而是全局引入jquery导入
* */
jquery: "jQuery",
lodash: "_",
},
/**
* 处理webpack不能够识别的文件
*/
module: {
rules: [],
},
/**
* webpack插件
*/
plugins: [],
};
模式开发
-
安装命令
npm install --save-dev webpack-merge
-
配置文件详情
const { merge } = require("webpack-merge"); const common = require("./webpack.common.js"); module.exports = merge(common, { mode: "mode模式", });
Loader
介绍
webapck的本质是一个模块打包工具
, 所以webpack默认只能处理JS文件,不能处理其他文件
,
因为其他文件中没有模块
的概念, 但是在企业开发中我们除了需要对JS进行打包以外,
还有可能需要对图片CSS等进行打包, 所以为了能够让webpack能够对其它的文件类型进行打包,
在打包之前就必须将其它类型文件转换为webpack能够识别处理的模块,
用于将其它类型文件转换为webpack能够识别处理模块的工具我们就称之为loader
特点
-
单一原则, 一个loader只做一件事情
-
多个loader会按照从右至左, 从下至上的顺序执行
-
从右至左
-
["style-loader", "css-loader"];
- 先执行
css-loader
解析css
文件关系拿到所有内容 - 再执行
style-loader
将内容插入到HTML的HEAD代码中
-
-
从下至上
-
[ { loader: "style-loader", }, { loader: "css-loader", }, ];
- 先执行
css-loader
解析css
文件关系拿到所有内容 - 再执行
style-loader
将内容插入到HTML的HEAD代码中
-
-
样式
css-loader
-
安装命令
npm install css-loader --save-dev npm install style-loader --save-dev
-
配置文件详情
module.exports = { module: { rules: [ //打包CSS规则 { test: /.css$/i, /** * css-loader: 解析css文件中的@import依赖关系 * style-loader: 将webpack处理之后的内容插入到html的head代码中 * */ // use: ["style-loader", "css-loader"], use: [ { loader: "style-loader", }, { loader: "css-loader", options: { // 开启CSS模块化 modules: true, }, }, ], }, ], }, };
less-loader
-
安装命令
npm install css-loader --save-dev npm install style-loader --save-dev npm install less-loader --save-dev
-
配置文件详情
module.exports = { module: { rules: [ // 打包less规则 { test: /.less$/i, use: [ { loader: "style-loader", }, { loader: "css-loader", }, { loader: "less-loader", }, ], }, ], }, };
scss-loader
-
安装命令
npm install css-loader --save-dev npm install style-loader --save-dev npm install node-sass --save-dev npm install sass-loader --save-dev
-
配置文件详情
module.exports = { module: { rules: [ // 打包SCSS规则 { test: /.scss$/, use: [ // 将 JS 字符串生成为 style 节点 { loader: "style-loader", }, //将 CSS 转化成 CommonJS 模块 { loader: "css-loader", }, // 将 Sass 编译成 CSS { loader: "sass-loader", }, ], }, ], }, };
PostCSS
自动补全浏览器前缀及兼容游览器
-
安装命令
npm install css-loader --save-dev npm install style-loader --save-dev npm install node-sass --save-dev npm install sass-loader --save-dev npm install less-loader --save-dev npm i -D postcss-loader npm i -D autoprefixer npm install postcss-pxtorem -D
-
配置文件详情
module.exports = { module: { rules: [ // 打包postcss规则 { test: /.s[ac]ss$/i, use: [ // 将 JS 字符串生成为 style 节点 { loader: "style-loader", }, // 将 CSS 转化成 CommonJS 模块 { loader: "css-loader", options: { modules: true, }, }, // 将 Sass 编译成 CSS { loader: "sass-loader", }, // 将 postcss 编译成 CSS { loader: "postcss-loader", options: { postcssOptions: { plugins: [ [ "autoprefixer", { // 选项 overrideBrowserslist: [ "ie >= 8", // 兼容IE7以上浏览器 "Firefox >= 3.5", // 兼容火狐版本号大于3.5浏览器 "chrome >= 35", // 兼容谷歌版本号大于35浏览器, "opera >= 11.5", // 兼容欧朋版本号大于11.5浏览器, ], }, ], [ "postcss-pxtorem", { // 根元素字体大小 rootValue: 100, // 可以从px更改到rem的属性 propList: ["*"], // propList: ["height"] unitPrecision: 5, // 将哪些html元素排除在外,我这里添加了一个vant的 selectorBlackList: ["vant-"], replace: true, mediaQuery: false, minPixelValue: 0, exclude: /node_modules/i, }, ], ], }, }, }, ], }, ], }, };
语法转换
bable-loader
-
安装命令
npm install --save-dev babel-loader @babel/core npm install @babel/preset-env --save-dev
-
配置文件详情
module.exports = { module: { rules: [ //打包JS规则 { test: /.m?js$/, // 告诉webpack不处理哪一个文件夹 exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-env"], }, }, }, ], }, };
图片文件
file-loader
-
安装命令
npm install --save-dev file-loader
-
配置文件详情
module.exports = { module: { rules: [ // 打包字体图标规则 { test: /.(eot|json|svg|ttf|woff|woff2)$/, use: [ { loader: "file-loader", options: { // 指定打包后文件名称 name: "[name].[ext]", // 指定打包后文件存放目录 outputPath: "font/", }, }, ], }, //打包图片规则 { test: /.(png|jpe?g|gif)$/i, use: [ { loader: "file-loader", options: { // 指定打包后文件名称 name: "[path][name].[ext]", // 指定打包后文件存放目录 outputPath: "images", // 指定托管服务器地址(统一替换图片地址) publicPath: "assets", }, }, ], }, ], }, };
url-loader
-
安装命令
npm install --save-dev url-loader
-
配置文件详情
module.exports = { module: { rules: [ //打包图片规则 { test: /.(png|jpe?g|gif)$/i, use: [ { loader: "url-loader", options: { /** * limit: 指定图片限制的大小 * 如果被打包的图片超过了限制的大小, 就会将图片保存为一个文件 * 如果被打包的图片没有超过限制的大小, 就会将图片转换成base64的字符串 * 注意点: * 对于比较小的图片, 我们将图片转换成base64的字符串之后, 可以提升网页的性能(因为减少了请求的次数) * 对于比较大的图片, 哪怕我们将图片转换成了base64的字符串之后, 也不会提升网页的性能, 还有可能降低网页的性能 * (因为图片如果比较大, 那么转换之后的字符串也会比较多, 那么网页的体积就会表达, 那么访问的速度就会变慢) * */ limit: 1024 * 100, // 指定打包后文件名称 name: "[path][name].[ext]", // 指定打包后文件存放目录 outputPath: "images", }, }, ], }, ], }, };
asset
module.exports = {
module: {
rules: [
{
//处理图片的
test: /.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
// 将图片文件输出到 static/imgs 目录中
// 将图片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件扩展名
// [query]: 添加之前的query参数
filename: "static/imgs/[hash:8][ext][query]",
},
},
{
//处理字体
test: /.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
//处理视频和音频
test: /.(ttf|woff2?|map4|map3|avi)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
],
},
};
image-webpack-loader
-
安装命令
npm install image-webpack-loader --save-dev
-
配置文件详情
module.exports = { module: { rules: [ //打包图片规则 { test: /.(png|jpe?g|gif)$/i, use: [ { loader: "file-loader", options: { // 指定打包后文件名称 name: "[path][name].[ext]", // 指定打包后文件存放目录 outputPath: "images", // 指定托管服务器地址(统一替换图片地址) // publicPath: "assets", }, }, { loader: "image-webpack-loader", options: { mozjpeg: { progressive: true, }, // optipng.enabled: false will disable optipng optipng: { enabled: false, }, pngquant: { quality: [0.65, 0.9], speed: 4, }, gifsicle: { interlaced: false, }, // the webp option will enable WEBP webp: { quality: 75, }, }, }, ], }, ], }, };
plugins
html插件
-
安装文件
npm install --save-dev html-webpack-plugin
-
配置文件详情
//打包结束之后自动创建一个index.html, 并将打包好的JS自动引入到这个文件中 const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { plugins: [ new HtmlWebpackPlugin({ //指定打包的模板, 如果不指定会自动生成一个空的 template: "./src/index.html", minify: { // htmlPlugin打包之后的html文件需要压缩 collapseWhitespace: true, }, }), ], };
压缩css文件
-
安装文件
npm install --save-dev mini-css-extract-plugin npm install --save-dev css-minimizer-webpack-plugin
-
配置文件详情
//创建独立一个css文件 const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //压缩css文件 const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); module.exports = { optimization: { //开发环境进行压缩css minimize: true, minimizer: [new CssMinimizerPlugin()], }, plugins: [ new MiniCssExtractPlugin({ // 类似于 webpackOptions.output 中的选项 // 所有选项都是可选的 filename: "[name].css", chunkFilename: "[id].css", }), ], };
按需打包css文件
-
安装文件
npm install --save-dev purgecss-webpack-plugin
-
配置文件详情
const path = require("path"); const glob = require("glob"); // 按需打包css const PurgecssPlugin = require("purgecss-webpack-plugin"); module.exports = { plugins: [ new PurgecssPlugin({ paths: glob.sync(`${path.join(__dirname, "src")}/**/*`, { nodir: true }), }), ], };
热更新
-
css配置文件
const Webpack = require("webpack"); module.exports = { devServer: { // 开启热更新, 只要开启了热更新就不会自动刷新网页了 hot: true, // 哪怕不支持热更新也不要刷新网页 hotOnly: true, }, plugins: [new Webpack.HotModuleReplacementPlugin()], };
-
js配置
// 判断当前有没有开启热更新 if (module.hot) { // 告诉热更新需要监听哪一个JS模块的变化 module.hot.accept("js文件路径", function () { console.log("js更新了"); }); }
清空打包文件
-
安装文件
npm install --save-dev clean-webpack-plugin
-
配置文件详情
//应用场景每次打包前将指定(dist/build)目录清空, 然后再存放新打包的内容, 避免新老混淆问题 const { CleanWebpackPlugin } = require("clean-webpack-plugin"); module.exports = { plugins: [ //清理每次打包之前文件 new CleanWebpackPlugin(), ], };
拷贝文件
-
安装文件
npm install --save-dev copy-webpack-plugin
-
配置文件详情
//文档内容是固定不变的, 我们只需要将对应的文件拷贝到打包目录中即可 const CopyPlugin = require("copy-webpack-plugin"); module.exports = { plugins: [ //拷贝 new CopyPlugin({ patterns: [ { from: "./doc", to: "doc", }, ], }), ], };
EsLint
-
安装文件
npm install eslint-webpack-plugin --save-dev npm install eslint --save-dev npm install eslint-plugin-promise eslint-plugin-node eslint-plugin-import eslint-plugin-standard eslint-config-standard --save-dev
-
配置文件
const ESLintPlugin = require('eslint-webpack-plugin'); module.exports = { // ... plugins: [new ESLintPlugin(options)], // ... };
代码分割
"use strict";
module.exports = {
/*
告诉webpack需要对代码进行分割
* */
optimization: {
splitChunks: {
chunks: "all", // 对那些代码进行分割 async(只分割异步加载模块)、all(所有导入模块)
minSize: 20000, // 表示被分割的代码体积至少有多大才分割(单位是字节)
minChunks: 1, // 表示至少被引用多少次数才分割,默认为1
maxAsyncRequests: 30, // 异步加载并发最大请求数(保持默认即可)
maxInitialRequests: 30, // 最大的初始请求数(保持默认即可)
automaticNameDelimiter: "+", // 指定被分割出来的文件名称的连接符
name: false, // 拆分出来块的名字使用0/1/2...(false) 还是指定名称(true)
/*
cacheGroups: 缓存组
缓存组的作用: 将当前文件中导入的所有模块都缓存起来统一处理
* */
cacheGroups: {
/*
vendors: 专门用于处理从node_modules中导入的模块
会将所有从node_modules中导入的模块写入到一个文件中去
* */
vendors: {
test: /[\/]node_modules[\/]/,
priority: -10, // 抽取公共代码的优先级,数字越大,优先级越高
reuseExistingChunk: true, // 是否复用分割的代码
},
/*
default: 专门用于处理从任意位置导入的模块
会将所有从任意位置导入的模块写入到一个文件中去
* */
/*
注意点: 如果我们导入的模块同时满足了两个条件, 那么就会按照优先级来写入
例如: 我们导入了jQuery, jQuery存放在了node_modules目录中
所以满足vendors的条件, 也满足default条件, 但是vendors的条件的优先级高于default的优先级
所以就只会执行vendors规则, 只会写入到vendors对应的文件中去
* */
default: {
minChunks: 1, // 表示至少被引用多少次数才分割,默认为1
priority: -20,
reuseExistingChunk: true, // 是否复用分割的代码
},
},
},
},
};
全局导入
"use strict";
const Webpack = require("webpack");
module.exports = {
plugins: [
// 全局导入
new Webpack.ProvidePlugin({
$: "jquery",
}),
],
};
忽略第三方包部分目录导入
'use strict';
const Webpack = require('webpack');
module.exports = {
plugins: [
/*
在打包moment该库的时候, 将整个locale目录都忽略掉
* */
new Webpack.IgnorePlugin(/^./locale$/, /moment$/)
]
};
动态dll库
新建一个配置文件, 专门用于打包不会变化的第三方库
"use strict";
const path = require("path");
const Webpack = require("webpack");
module.exports = {
entry: {
jquery: ["jquery"],
lodash: ["lodash"],
},
/**
* 指定打包之后的文件输出的路径和输出的文件名称
*/
output: {
/**
* 指定打包之后的JS文件的名称
*/
filename: "[name].dll.js",
/**
* 指定打包之后的文件存储到什么地方
*/
path: path.join(__dirname, "dll"),
library: "[name]",
},
/**
* 指定打包的模式
* development: 不会对打包的JS代码进行压缩
* production: 会对打包的JS代码进行压缩
*/
mode: "development",
/**
* webpack插件
*/
plugins: [
/*
DllPlugin作用:
在打包第三方库的时候生成一个清单文件
* */
new Webpack.DllPlugin({
name: "[name]", // 注意这个名称必须和library名称一致
path: path.resolve(__dirname, "dll/[name].manifest.json"),
}),
],
};
安装插件把打包好的库插入到html中
npm i add-asset-html-webpack-plugin -D
在专门打包第三方的配置文件中添加生成清单配置
"use strict";
const path = require("path");
const fs = require("fs");
const Webpack = require("webpack");
const AddAssetHtmlPlugin = require("add-asset-html-webpack-plugin");
const plugins = [];
const dllPath = path.resolve(__dirname, "dll");
const files = fs.readdirSync(dllPath);
files.forEach(function (file) {
if (file.endsWith(".js")) {
plugins.push(
new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, "dll", file),
})
);
} else if (file.endsWith(".json")) {
plugins.push(
new Webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, "dll", file),
})
);
}
});
module.exports = {
plugins: plugins,
};
加载模块
-
异步加载模块
import("加载模块").then(() => { //代码.... });
-
懒加载模块
//webpackPreload 是否懒加载 //webpackChunkName 定义懒加载名称 import( /* webpackPreload: true */ /* webpackChunkName: "jquery" */ "加载模块" ).then(() => { //代码... });