Webpack学习手册
Webpack5学习手册
介绍
Webpack是一个静态资源打包工具。它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。
输出的文件就是编译好的文件,就可以在浏览器中运行了。
我们将 Webpack 输出的文件叫做bundle。
Webpack本身功能是有限的:
- 开发模式:仅能编译JS中的ES Module语法
- 生产模式:能编译JS中的ES Module语法,还能压缩JS代码
对于其他资源的处理,还需要通过一系列的配置。
起步
- 创建一个空文件夹 webpack-test
资源目录如下:
webpack_code # 项目根目录(所有指令必须在这个目录运行)
└── src # 项目源码目录
├── js # js文件目录
│ ├── count.js
│ └── sum.js
└── main.js # 项目主文件
-
编辑代码
- count.js
export default function count(x, y) { return x - y; }
- sum.js
export default function sum(...args) { return args.reduce((p, c) => p + c, 0); }
- main.js
import count from "./js/count"; import sum from "./js/sum"; console.log(count(2, 1)); console.log(sum(1, 2, 3, 4));
-
下载依赖
打开项目终端,运行以下指令:- 初始化package.json
npm i init -y
- 下载依赖
npm i webpack webpack-cli -D
-
启用Webpack
npx webpack:运行本地安装webpack包
./src/main.js:指定Webpack从main.js文件开始打包,不但会打包main.js,还会将其依赖也一起打包进来
--mode=xxx:指定模式(环境)
- 开发模式
npx webpack ./src/main.js --mode=development
- 生产模式
npx webpack ./src/main.js --mode=production
默认Webpack会将文件打包输出到dist目录下。
基本配置
5大核心概念
Webpack的配置有5大核心概念:
-
entry(入口)
指示Webpack从哪个文件开始打包
-
output(输出)
指示 Webpack打包完的文件输出到哪里去,如何命名等
-
loader(加载器)
webpack本身只能处理js、json等资源,其他资源需要借助 loader,Webpack 才能解析
-
plugins(插件)
扩展 Webpack 的功能
-
mode(模式)
主要由两种模式:开发模式(development)和生产模式(production)
创建配置文件
在项目根目录下新建:webpack.config.js
module.exports = {
// 入口
entry:"",
// 输出
output:{},
// 加载器
module:{
rules:[]
},
//插件
plugins:[],
//模式
mode:""
}
配置文件初始化
-
配置文件
// Node.js的核心模块,专门用来处理文件路径 const path = require("path"); module.exports = { // 入口 entry:"./src/main.js", //相对路径和绝对路径都行 // 输出 output:{ // path: 文件输出目录,必须是绝对路径 // path.resovle()方法返回一个绝对路径 // __dirname当前文件的文件夹绝对路径 path: path.resolve(__dirname,"dist"), // filename:输出文件的文件名 filename: 'main.js' }, // 加载器 module:{ rules:[] }, //插件 plugins:[], //模式 mode:"development",//开发模式 }
-
运行指令
npx webpack
开发模式
开发模式就是我们开发代码时使用的模式。
这个模式下我们主要做两件事:
编译代码,使浏览器能识别运行
开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源
代码质量检查,树立代码规范
提前检查代码的一些隐患,让代码运行时能更加健壮。
提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。
开发服务器&&自动化
为了避免每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们可以通过配置进行自动化
- 下载包
npm i webpack-dev-server -D
- 配置
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
module.exports = {
// 入口
entry:"./src/main.js", //相对路径和绝对路径都行
// 输出
output:{
// path: 文件输出目录,必须是绝对路径
// path.resovle()方法返回一个绝对路径
// __dirname当前文件的文件夹绝对路径
path: path.resolve(__dirname,"dist"),
// filename:输出文件的文件名
filename: 'main.js'
},
// 加载器
module:{
rules:[]
},
//插件
plugins:[],
//开发服务器
devServer:{
host:"localhost",//启动服务器域名
port:"3000",//启动服务器端口号
open:true,//是否自动打开浏览器
},
//模式
mode:"development",//开发模式
}
- 运行指令
npx webpack serve
注意运行指令发生了变化
并且当你使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。
处理Html资源
-
添加Html资源
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Webpack Learning</title>
</head>
<body>
<h1>Hello Webpack5</h1>
</body>
</html>
- 下载包
npm i html-webpack-plugin -D
- 配置
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// 入口
entry:"./src/main.js", //相对路径和绝对路径都行
// 输出
output:{
// path: 文件输出目录,必须是绝对路径
// path.resovle()方法返回一个绝对路径
// __dirname当前文件的文件夹绝对路径
path: path.resolve(__dirname,"dist"),
// filename:输出文件的文件名
filename: 'main.js'
},
// 加载器
module:{
rules:[]
},
//插件
plugins:[
new HtmlWebpackPlugin({
//以public/index.html为模板创建文件
// 新的html文件有两个特点:1.内容和源文件一致 2.自动引入打包生成的js等资源
template:path.resolve(__dirname,"public/index.html")
})
],
//开发服务器
devServer:{
host:"localhost",//启动服务器域名
port:"3000",//启动服务器端口号
open:true,//是否自动打开浏览器
},
//模式
mode:"development",//开发模式
}
-
运行开发服务器 npx webpack serve
因为 HtmlWebpackPlugin 会自动引入 main.js,所以可以在控制台看到main.js的输出语句
处理样式资源
Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源
我们找 Loader 都应该去官方文档中找到对应的 Loader,然后使用官方文档找不到的话,可以从社区 Github 中搜索查询 Webpack 官方 Loader 文档
-
处理CSS资源
-
处理CSS资源
- 下载包
npm i css-loader style-loader -D
注意:需要下载两个loader
css-loader:负责将 Css 文件编译成 Webpack 能识别的模块
style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容此时样式就会以 Style 标签的形式在页面上生效
- 配置
// Node.js的核心模块,专门用来处理文件路径 const path = require("path"); const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { // 入口 entry:"./src/main.js", //相对路径和绝对路径都行 // 输出 output:{ // path: 文件输出目录,必须是绝对路径 // path.resovle()方法返回一个绝对路径 // __dirname当前文件的文件夹绝对路径 path: path.resolve(__dirname,"dist"), // filename:输出文件的文件名 filename: 'main.js' }, // 加载器 module:{ rules:[ { // 用来匹配.css结尾的文件 test:/\.css$/, // use数组里面Loader执行顺序是从右到左 use:["style-loader","css-loader"] } ] }, //插件 plugins:[ new HtmlWebpackPlugin({ //以public/index.html为模板创建文件 // 新的html文件有两个特点:1.内容和源文件一致 2.自动引入打包生成的js等资源 template:path.resolve(__dirname,"public/index.html") }) ], //开发服务器 devServer:{ host:"localhost",//启动服务器域名 port:"3000",//启动服务器端口号 open:true,//是否自动打开浏览器 }, //模式 mode:"development",//开发模式 }
-
添加CSS资源
- src/css/index.css
.box1{ width: 100px; height: 100px; background-color: pink; }
- src/main.js
import count from './js/count'; import sum from "./js/sum"; // 在入口文件引入css资源,webpack才会对其打包 import './css/index.css' console.log(count(2,1)); console.log(sum(1,2,3,4));
- public/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Webpack Learning</title> </head> <body> <h1>Hello Webpack5</h1> <!-- 准备一个使用样式的 DOM容器 --> <div class="box1"></div> </body> </html>
此时,可以在服务器看到页面多出了一个粉红色的正方形样式
-
-
处理CSS预处理器资源
有了上面处理CSS资源的经验,可以举一反三处理Sass/Scss、Less等预处理器资源了。下面以处理Sass/Scss资源为例。
-
处理Sass/Scss资源
- 下载包
npm i sass-loader sass -D
sass-loader:负责将 Sass 文件编译成 css 文件
sass:sass-loader 依赖 sass 进行编译- 配置
// 加载器 module:{ rules:[ ... { //用来匹配 .sass 或 .scss结尾的文件 test:/\.s[ac]ss$/, use:[ "style-loader","css-loader","sass-loader" ] } ] }
-
添加Sass/Scss资源
- src/sass/index.scss
$bgColor: blue; .box2 { width: 100px; height: 100px; background-color: $bgColor; }
- src/sass/index.sass
/* 可以省略大括号和分号 */ .box3 width: 100px height: 100px background-color: hotpink
- src/main.js
import count from './js/count'; import sum from "./js/sum"; // 在入口文件引入css资源,webpack才会对其打包 import './css/index.css' import './sass/index.sass' import './sass/index.scss' console.log(count(2,1)); console.log(sum(1,2,3,4));
- public/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Webpack Learning</title> </head> <body> <h1>Hello Webpack5</h1> <!-- 准备一个使用样式的 DOM容器 --> <div class="box1"></div> <div class="box2"></div> <div class="box3"></div> </body> </html>
此时,可以在服务器看到页面多出了2个正方形样式
-
处理图片资源
- 配置
// 加载器
module:{
rules:[
...
{
test:/\.(png|jpe?g|gif|webp)$/,
type:'asset'
}
]
},
2.使用图片资源
// src/css/index.css
.box1 {
width: 100px;
height: 100px;
background-image: url('../image/1.gif');
background-size: cover;
}
// src/sass/index.scss
.box2 {
width: 100px;
height: 100px;
background-image: url('../image/2.jpg');
background-size: cover;
}
// src/sass/index.sass
.box3
width: 100px
height: 100px
background-image: url("../image/3.jpg")
background-size: cover
查看页面效果:
3.输出资源情况
如果使用命令npx webpack,查看dist目录的话,会发现多了三张图片资源,Webpack会将所有打包好的资源输出到 dist 目录下。但是在dist目录下却没有样式资源,这是因为经过style-loader的处理,样式资源打包到 main.js 里面去了,所以没有额外输出出来。
4.优化图片资源
通过配置可以将小于某个大小的图片转化成 data URI 形式(Base64 格式)
优点:减少请求数量
缺点:体积变得更大
// 加载器
module:{
rules:[
...
{
test:/\.(png|jpe?g|gif|webp)$/,
type:'asset',
parser:{
dataUrlCondition:{
maxSize:10*1024 // 小于10kb的图片会被base64处理
}
}
}
]
},
生产模式
生产模式下主要对代码进行优化,优化主要从以下两个角度出发:
1.优化代码运行性能
2.优化代码打包速度
文件目录
修改文件目录,两个配置文件对应生产模式和开发模式
├── webpack-test (项目根目录)
├── config (Webpack配置文件目录)
│ ├── webpack.dev.js(开发模式配置文件)
│ └── webpack.prod.js(生产模式配置文件)
├── node_modules (下载包存放目录)
├── src (项目源码目录,除了html其他都在src里面)
│ └── 略
├── public (项目html文件)
│ └── index.html
├── .eslintrc.js(Eslint配置文件)
├── babel.config.js(Babel配置文件)
└── package.json (包的依赖管理配置文件)
修改webpack.dev.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: undefined, // 开发模式没有输出,不需要指定输出目录
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
// clean: true, // 开发模式没有输出,不需要清空输出结果
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
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: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
],
// 其他省略
devServer: {
host: "localhost", // 启动服务器域名
port: "3000", // 启动服务器端口号
open: true, // 是否自动打开浏览器
},
mode: "development",
};
运行开发模式的指令:
npx webpack serve --config ./config/webpack.dev.js
修改webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
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: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
运行生产模式的指令:
npx webpack --config ./config/webpack.prod.js
配置运行指令
为了方便运行不同模式的指令,在 package.json 中 scripts 里面定义指令
// package.json
{
// 其他省略
"scripts": {
"start": "npm run dev",
"dev": "npx webpack serve --config ./config/webpack.dev.js",
"build": "npx webpack --config ./config/webpack.prod.js"
}
}
以后启动指令:
开发模式:npm start 或 npm run dev
生产模式:npm run build
CSS处理
提取CSS成单独文件
在之前的样式资源处理中,css文件总是被打包到js文件里,这就导致在网页中,当 js 文件加载时,会创建一个 style 标签来生成样式,性能下降,用户体验不好。css文件应该是通过link标签在网页加载,性能才好。
1.下载包
npm i mini-css-extract-plugin -D
2.配置 webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
{
test: /\.s[ac]ss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
{
test: /\.styl$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
},
{
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: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
3.运行指令
npm run build
CSS兼容性处理
1.下载包
npm i postcss-loader postcss postcss-preset-env -D
2.配置weback.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
],
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"less-loader",
],
},
{
test: /\.s[ac]ss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"sass-loader",
],
},
{
test: /\.styl$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
"stylus-loader",
],
},
{
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: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
3.控制兼容性
可以在 package.json 文件中添加 browserslist 来控制样式的兼容性做到什么程度。
{
// 其他省略
"browserslist": ["ie >= 8"]
}
想要知道更多的 browserslist 配置,查看browserslist 文档
以上为了测试兼容性所以设置兼容浏览器 ie8 以上。
实际开发中一般不考虑旧版本浏览器了,所以可以这样设置:
{
// 其他省略
"browserslist": ["last 2 version", "> 1%", "not dead"]
}
4.合并配置webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
};
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.styl$/,
use: getStyleLoaders("stylus-loader"),
},
{
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: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};
CSS压缩
1.下载包
npm i css-minimizer-webpack-plugin -D
2.配置webpack.prod.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
return [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 能解决大多数样式兼容性问题
],
},
},
},
preProcessor,
].filter(Boolean);
};
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
clean: true,
},
module: {
rules: [
{
// 用来匹配 .css 结尾的文件
test: /\.css$/,
// use 数组里面 Loader 执行顺序是从右到左
use: getStyleLoaders(),
},
{
test: /\.less$/,
use: getStyleLoaders("less-loader"),
},
{
test: /\.s[ac]ss$/,
use: getStyleLoaders("sass-loader"),
},
{
test: /\.styl$/,
use: getStyleLoaders("stylus-loader"),
},
{
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: /\.js$/,
exclude: /node_modules/, // 排除node_modules代码不编译
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
// 指定检查文件的根目录
context: path.resolve(__dirname, "../src"),
}),
new HtmlWebpackPlugin({
// 以 public/index.html 为模板创建文件
// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
template: path.resolve(__dirname, "../public/index.html"),
}),
// 提取css成单独文件
new MiniCssExtractPlugin({
// 定义输出文件名和目录
filename: "static/css/main.css",
}),
// css压缩
new CssMinimizerPlugin(),
],
// devServer: {
// host: "localhost", // 启动服务器域名
// port: "3000", // 启动服务器端口号
// open: true, // 是否自动打开浏览器
// },
mode: "production",
};