关于系统学习webpack5这个Flag立了快一年半了,最近突发觉得要好好完善一下自己的知识体系,终于在今年年底前有了行动。每天学一点,一周一大点。内容偏于基础,有错误的地方欢迎指正
webpack是一个静态资源打包工具
它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出
基本使用
功能介绍
- 开发模式:仅能编译JS中的ES Module语法
- 生产模式:能编译JS中的ES Module语法,还能压缩JS代码(性能提升)
本身只能处理JS文件,对其他如样式文件无法处理,所以我们需要了解它更强大的配置
初始化package.json
package.json中的name不能为webpack
npm init -y
下载依赖
npm i webpack webpack-cli -D
启用webpack
- 开发模式
npx webpack ./src/main.js --mode=development
- 生产模式
npx webpack ./src/main.js --mode=production
npx webpack:用来运行本地安装的webpack。
./src/main.js:指定webpack从main.js开始打包,不但会打包main.js,还会将其依赖也一起打包进来
--mode=xxx:指定打包环境
基本配置
五大核心概念
entry:指定webpack从哪个文件开始打包
output:指定webpack打包好的文件输出到哪里,如何命名
loader:webpack本身只能处理js,json等资源,其他资源要借助loader才能进行解析
plugins:扩展webpack的功能
mode:生产模式/开发模式
配置文件
⭐ webpack的配置文件,要位于项目的根目录下,并且命名一定是webpack.config.js
const path = require('path'); // nodejs核心模块,专门用来处理路径问题
// Webpack 是基于 Node.js 运行的,所以采用 Common.js 模块化规范
module.exports = {
// 入口
entry: './src/main.js', // 相对路径
// 输出
output: {
// 所有文件输出的路径
// __dirname: nodejs的变量,代表当前文件的文件夹目录
path: path.resolve(__dirname, 'dist'), // 绝对路径
// 入口文件打包输出文件名
filename: 'static/js/main.js',
},
// 加载器
module: {
rules: [
// loader的配置
],
},
// 插件
plugins: [
// 三个步骤:下载 引用 new调用
// plugin的配置
],
// 模式
mode: 'development',
};
运行
npx webpack
处理样式资源
处理Css资源
处理Css资源需要下载两个loader包
- css-loader:负责将Css文件编译成webpack能识别的模块
- style-loader:会动态的创建一个style标签,里面放置webpack中Css模块的内容
// 加载器
module: {
rules: [
// 处理Css资源loader配置
{
test: /.css$/i, // 只检测.css文件 --这是一个正则表达式
// use的执行顺序,从右到左(从下到上)
use: ['style-loader', 'css-loader'],
},
],
},
处理Less资源
处理Less资源需要下载三个包(其中有两个是Css资源中需要,不再解释)
如果没有下载less包,则需要下载less包
- less-loader:将less文件编译成css文件
module: {
rules: [
// less资源的loader配置
{
test: /.less$/i, // 只检测.less文件 --这是一个正则表达式
// loader: 'xxxx', 只能使用一个loader,use可以使用多个loader
// use的执行顺序,从右到左(从下到上)
use: [
'style-loader',
'css-loader',
'less-loader', // 将less编译成css文件
],
},
],
<p align=left>},</p>
处理Sass/Scss资源
处理Sass资源需要下载三个包(其中有两个是Css资源中需要,不再解释)
如果没有下载sass包,则需要下载sass包
- sass-loader:将sass/scss文件编译成css文件
module: {
rules: [
// sass资源的loader配置
{
test: /.s[ac]ss$/i, // 只检测.sass/scss文件 --这是一个正则表达式
// use的执行顺序,从右到左(从下到上)
use: [
'style-loader',
'css-loader',
'sass-loader', // 将sass/scss编译成css文件
],
},
],
},
处理Styl资源
处理Less资源需要下载三个包(其中有两个是Css资源中需要,不再解释)
如果没有下载stylus包,则需要下载stylus包
- stylus-loader:将styl文件编译成css文件
module: {
rules: [
// less资源的loader配置
{
test: /.styl$/i, // 只检测.styl文件 --这是一个正则表达式
// loader: 'xxxx', 只能使用一个loader,use可以使用多个loader
// use的执行顺序,从右到左(从下到上)
use: [
'style-loader',
'css-loader',
'stylus-loader', // 将styl编译成css文件
],
},
],
},
提取Css资源为单独文件——插件实现
在上面的配置中,css资源会被打包到js资源中,通过style-loader创建标签来生成样式。这样对于网站来说会出现闪屏现象,对于用户体验效果不好。我们可以通过标签来外链css资源解决这一问题。
- 下载
yarn add mini-css-extract-plugin -D
- 引用
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
- 配置
需要将所有用到style-loader替换成MiniCssExtractPlugin.loader,然后在plugins中调用MiniCssExtractPlugin
plugins: [
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
],
Css兼容性处理
- 下载
yarn add postcss-loader postcss postcss-preset-env -D
- 配置
// postcss-loader配置对象要放在css-loader后面,less-loader/sass-loader/stylus-loader前面
module: {
rules: [
{
test: /.css$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
],
},
],
}
我们还可以在 package.json 文件中添加 browserslist 来控制样式的兼容性做到什么程度。
// 浏览器的兼容程度配置
{
// "browserslist": ["ie >= 8"] // 兼容ie以上浏览器
// "browserslist": ["last 2 version", "> 1%", "not dead"] // 实际开发做到这个程度即可
// 所有浏览器最近2个版本,覆盖99%的浏览器,且没有“死”的
}
Css压缩 - 插件实现
- 下载
yarn add css-minimizer-webpack-plugin -D
- 配置
// 引用
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin');
// 调用
plugins: {
// css压缩
new CssMinimizerWebpackPlugin(),
}
处理图片资源
webpack4处理图片资源要用到file-loader和url-loader进行处理。但是在webpack5中,已经将这两个功能内置,我们只需要做简单配置即可。
在 webpack 5 之前,通常使用:
- raw-loader 将文件导入为字符串
- url-loader 将文件作为 data URI 内联到 bundle 中,将小于某个大小的图片,会转换成base64格式,对图片资源做了些优化。
- file-loader 将文件原封不动发送到输出目录
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
- asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
- asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
- asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
- asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。
基础配置
module: {
rules: [
// 图片资源的loader配置
{
test: /.(png|jpe?g|gif|webp)$/i,
type: 'asset',
},
],
},
对图片资源进行优化 - 将图片资源转换成base64格式
优点:减少图片的请求数量
缺点:体积会更大
module: {
rules: [
// 图片资源的loader配置
{
test: /.(png|jpe?g|gif|webp)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
}
}
},
],
},
处理字体图标资源
- 下载字体图标文件
打开阿里巴巴矢量图标库,选择所需要的图标添加到购物车,统一下载到本地
- 添加字体图片资源
将下载到本地的字体文件与css文件移入到所需项目,并进行引入,注意css中字体文件的引入路径需要做对应修改。再将字体文件css进行引入即可。
- 配置
类似图片资源处理
module: {
rules: [
// 字体图标资源的loader配置
{
test: /.(ttf|woff2?)$/i,
// asset/resource:直接打包输出文件资源
type: 'asset/resource',
generator: {
filename: 'static/iconfont/[hash][ext][query]',
},
},
],
},
其他资源
如音视频资源
一律按照字体图标资源处理,即修改图标资源正则即可。
test: /.(ttf|woff2?|mp3|mp4|avi)$/i
修改输出资源的目录及名称
修改JS资源目录
修改图片资源目录
module: {
rules: [
// 图片资源的loader配置
{
test: /.(png|jpe?g|gif|webp)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
}
},
// hash: 图片hash值, ext:扩展名, query:携带参数
// [hash:10]:hash名只取前10位
generator: {
filename: 'static/images/[hash][ext][query]'
}
},
],
},
自动清空上次打包内容
处理js资源
针对JS的兼容性我们要用到babel来处理(webpack只编译Js中Es模块化语法),针对代码格式则需要用到Eslint来处理。
Eslint
- 安装
yarn add eslint-webpack-plugin eslint -D
- 配置
需要一个.eslintrc.js的配置文件才能干活
会对打包后的文件也进行eslint校验,可以通过.eslintignore配置不校验的文件
module.exports = {
// 解析选项
parserOptions: {
ecmaVersion: 6, // ES 语法版本
sourceType: 'module', // ES 模块化
ecmaFeatures: { // ES 其他特性
jsx: false // 如果是 React 项目,就需要开启 jsx 语法
}
},
// 具体检查规则 键值对形势
// 0|'off' 关闭规则
// 1|'warn' 开启规则,仅警告
// 2|'error' 开启规则, 抛出错误
rules: {
'no-var': 2, // 不能使用 var 定义变量
},
// 继承其他规则
// Eslint官方规则:eslint:recommended
// Vue官方规则:plugin:vue/essential
// React官方规则:react-app
// rules中的规则会比extends的优先级更高
extends: ['eslint:recommended'],
env: {
node: true, // 启用node中全局变量
browser: true, // 启用浏览器中全局变量
},
// ...
// 其他规则详见:https://eslint.bootcss.com/docs/user-guide/configuring
};
const ESLintWebpackPlugin = require('eslint-webpack-plugin');
module.exports ={
plugins: [
// 插件一般是个构造函数 需要用new调用
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "src"),
}),
],
}
Babel
主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中
- 安装
yarn add babel-loader @babel/core @babel/preset-env webpack -D
- 配置
module.exports = {
presets: ['@babel/preset-env'],
};
module.exports={
module: {
rules:[
{
test: /.js$/,
// 排除node_modules代码不编译
exclude: /node_modules/,
loader: 'babel-loader',
// @babel/preset-env 允许您使用最新的 JavaScript
// @babel/preset-react 一个用来编译 React jsx 语法的预设
// @babel/preset-typescript 一个用来编译 TypeScript 语法的预设
// 可以通过外部文件babel.config.js文件编写
// options: {
// presets: ['@babel/preset-env'],
// },
},
]
}
}
处理Html资源
- 安装
yarn add html-webpack-plugin -D
- 配置
切记要删除public/index.html中对js资源的引用,html-webpack-plugin会自动引入打包输出资源
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports ={
plugins: [
new HtmlWebpackPlugin({
// 模板:以public/index.html文件创建新的html文件
// 特点:1.新的html文件结构与原来一致, 2.自动引入打包输出的资源
template: path.resolve(__dirname, "public/index.html"),
}),
],
}
开发服务器自动运行
- 安装
yarn add webpack-dev-server -D
- 配置
module.exports={
// 开发服务器 不会输出资源,在内存中编译打包
devServer: {
host: 'localhost', // 启动服务器
port: '3000', // 端口号
open: true, // 是否自动打开浏览器
}
}
生产模式
- 优化代码运行性能
- 优化代码打包速度
配置开发/生产环境
开发环境配置
- 开发模式没有输出,不需要指定输出目录
- 开发模式没有输出,不需要清空输出结果
- webpack配置文件目录变了,因此所有绝对路径需要回退目录才能找到对应的文件(webpack配置文件不在项目根目录文件下的情况)
- 运行指令:npx webpack serve --config ./config/webpack.dev.js(可以在package.json运行命令中进行配置)
生产环境配置
- 打包之前可以将上一次目录内容清空
- 无需开发服务器配置
- mode模式为production
- 绝对路径需要回退目录(webpack配置文件不在项目根目录文件下的情况)
- 运行命令:npx webpack --config ./config/webpack.prod.js(可以在package.json运行命令中进行配置)
package.json运行配置
"scripts": {
"start": "npm run dev",
"dev": "webpack serve --config ./config/webpack.dev.js",
"build": "webpack --config ./config/webpack.prod.js"
},