Webpack 资源处理大全 —— CSS/JS/HTML/图片/字体完整指南
Webpack 资源处理大全 —— CSS/JS/HTML/图片/字体完整指南
系列文章第 4 篇 | 预计阅读时间:18 分钟
一、资源处理概述
Webpack 的核心功能之一就是处理各种类型的资源文件:
| 资源类型 | 处理方式 | 核心 Loader/Plugin |
|---|---|---|
| CSS/Less/Sass | 样式处理 | style-loader, css-loader |
| JavaScript | 编译转换 | babel-loader |
| HTML | 模板生成 | html-webpack-plugin |
| 图片 | 资源模块 | Asset Modules |
| 字体图标 | 资源模块 | Asset Modules |
二、CSS 资源处理
2.1 基础 CSS 处理
安装依赖:
npm i style-loader css-loader -D
配置:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"], // 从右到左执行
},
],
},
};
两个 Loader 的作用:
| Loader | 作用 |
|---|---|
css-loader |
将 CSS 编译成 Webpack 能识别的模块 |
style-loader |
创建 <style> 标签,将样式注入页面 |
在 JS 中引入 CSS:
// main.js
import "./css/index.css";
2.2 Less/Sass/Stylus 处理
安装依赖:
npm i less-loader -D # Less
npm i sass-loader sass -D # Sass/Scss
npm i stylus-loader -D # Stylus
配置:
module.exports = {
module: {
rules: [
{
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"],
},
],
},
};
使用示例:
// main.js
import "./css/index.css";
import "./less/index.less";
import "./sass/index.scss";
import "./styl/index.styl";
2.3 CSS 兼容性处理
使用 postcss-loader 自动添加浏览器前缀:
安装依赖:
npm i postcss-loader postcss postcss-preset-env -D
配置:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
"style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"postcss-preset-env", // 自动添加浏览器前缀
],
},
},
},
],
},
],
},
};
效果:
/* 输入 */
.box {
display: flex;
}
/* 输出(自动添加前缀) */
.box {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
三、JavaScript 资源处理
3.1 Babel 编译
作用: 将 ES6+ 语法转换为向后兼容的 JavaScript
安装依赖:
npm i babel-loader @babel/core @babel/preset-env -D
babel.config.js 配置:
module.exports = {
presets: ["@babel/preset-env"],
};
webpack.config.js 配置:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/, // 排除第三方代码
loader: "babel-loader",
},
],
},
};
3.2 ESLint 代码检查
作用: 统一团队代码风格,提前发现潜在问题
安装依赖:
npm i eslint-webpack-plugin eslint -D
.eslintrc.js 配置:
module.exports = {
extends: ["eslint:recommended"],
env: {
node: true,
browser: true,
},
parserOptions: {
ecmaVersion: 6,
sourceType: "module",
},
rules: {
"no-var": 2, // 禁止使用 var
},
};
webpack.config.js 配置:
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
module.exports = {
plugins: [
new ESLintWebpackPlugin({
context: path.resolve(__dirname, "src"), // 检查根目录
exclude: /node_modules/, // 排除 node_modules
}),
],
};
3.3 忽略 ESLint 检查的文件
创建 .eslintignore 文件:
# 忽略 dist 目录
dist
# 忽略构建文件
build
四、HTML 资源处理
4.1 HtmlWebpackPlugin
作用:
- 自动生成 HTML 文件
- 自动引入打包生成的 JS/CSS 资源
- 支持自定义模板
安装依赖:
npm i html-webpack-plugin -D
配置:
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html", // 模板文件
filename: "index.html", // 输出文件名
minify: {
collapseWhitespace: true, // 压缩 HTML
removeComments: true, // 移除注释
},
}),
],
};
模板文件(public/index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Webpack App</title>
<!-- 不需要手动引入 JS,插件会自动添加 -->
</head>
<body>
<div id="app"></div>
</body>
</html>
输出结果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Webpack App</title>
<script src="main.a1b2c3d4.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
4.2 HTML 压缩
生产模式默认开启 HTML 压缩,无需额外配置。
如需自定义压缩选项:
new HtmlWebpackPlugin({
template: "./public/index.html",
minify: {
collapseWhitespace: true, // 折叠空白
removeComments: true, // 移除注释
removeAttributeQuotes: true, // 移除属性引号
minifyCSS: true, // 压缩内联 CSS
minifyJS: true, // 压缩内联 JS
},
});
五、图片资源处理
5.1 Asset Modules(Webpack 5 内置)
Webpack 5 使用 Asset Modules 处理图片,无需额外安装 Loader。
配置:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp|svg)$/,
type: "asset", // 自动选择 inline 或 resource
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于 10kb 转 base64
},
},
generator: {
filename: "static/imgs/[hash:8][ext][query]",
},
},
],
},
};
type 的四种类型:
| 类型 | 作用 | 相当于 |
|---|---|---|
asset |
自动选择 inline 或 resource | url-loader |
asset/resource |
输出文件 URL | file-loader |
asset/inline |
输出 base64 Data URI | url-loader (仅 inline) |
asset/source |
输出文件原始内容 | raw-loader |
5.2 使用方式
在 CSS 中使用:
/* less/index.less */
.box {
width: 100px;
height: 100px;
background-image: url("../images/bg.png");
background-size: cover;
}
在 JS 中使用:
// main.js
import logo from "./images/logo.png";
const img = document.createElement("img");
img.src = logo;
document.body.appendChild(img);
5.3 图片压缩
安装插件:
npm i image-minimizer-webpack-plugin imagemin -D
npm i imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D
配置:
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: [
["gifsicle", { interlaced: true }],
["jpegtran", { progressive: true }],
["optipng", { optimizationLevel: 5 }],
[
"svgo",
{
plugins: [
"preset-default",
"prefixIds",
],
},
],
],
},
},
}),
],
},
};
六、字体图标处理
6.1 下载字体图标
- 打开 阿里巴巴矢量图标库
- 选择图标添加到购物车
- 下载到本地,解压到
src/fonts/目录
6.2 配置
module.exports = {
module: {
rules: [
{
test: /\.(ttf|woff2?|eot)$/,
type: "asset/resource",
generator: {
filename: "static/fonts/[hash:8][ext][query]",
},
},
],
},
};
6.3 使用方式
引入 CSS 文件:
// main.js
import "./css/iconfont.css";
在 HTML 中使用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Webpack App</title>
</head>
<body>
<!-- 使用字体图标 -->
<i class="iconfont icon-arrow-down"></i>
<i class="iconfont icon-ashbin"></i>
<i class="iconfont icon-browse"></i>
</body>
</html>
七、开发服务器
7.1 安装与配置
安装依赖:
npm i webpack-dev-server -D
配置:
module.exports = {
devServer: {
host: "localhost", // 服务器域名
port: 3000, // 服务器端口
open: true, // 自动打开浏览器
hot: true, // 开启 HMR
compress: true, // 启用 gzip 压缩
proxy: { // 代理配置
"/api": {
target: "http://localhost:8080",
changeOrigin: true,
pathRewrite: { "^/api": "" },
},
},
},
};
7.2 启动脚本
package.json 配置:
{
"scripts": {
"start": "npm run dev",
"dev": "npx webpack serve --config webpack.config.js",
"build": "npx webpack --config webpack.prod.js"
}
}
启动开发服务器:
npm run dev
7.3 开发服务器特点
- ✅ 代码在内存中编译打包,不输出到磁盘
- ✅ 支持热模块替换(HMR)
- ✅ 自动刷新浏览器
- ✅ 支持代理解决跨域问题
八、完整配置示例
8.1 开发模式配置
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",
},
module: {
rules: [
{
test: /\.css$/,
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: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024,
},
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "static/media/[hash:8][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
],
},
plugins: [
new ESLintWebpackPlugin({
context: path.resolve(__dirname, "src"),
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "public/index.html"),
}),
],
devServer: {
host: "localhost",
port: 3000,
open: true,
hot: true,
},
mode: "development",
devtool: "cheap-module-source-map",
};
8.2 生产模式配置
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");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "js/[name].[contenthash:8].js",
clean: true,
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: ["postcss-preset-env"],
},
},
},
],
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"less-loader",
],
},
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024,
},
},
},
{
test: /\.(ttf|woff2?)$/,
type: "asset/resource",
generator: {
filename: "media/[name].[contenthash:8][ext]",
},
},
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: {
cacheDirectory: true,
plugins: ["@babel/plugin-transform-runtime"],
},
},
],
},
],
},
plugins: [
new ESLintWebpackPlugin({
context: path.resolve(__dirname, "src"),
cache: true,
}),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "public/index.html"),
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash:8].css",
}),
],
optimization: {
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin(),
],
splitChunks: {
chunks: "all",
},
},
mode: "production",
devtool: "source-map",
};
九、小结
本篇我们学习了 Webpack 处理各种资源的完整方案:
| 资源类型 | 核心方案 | 关键配置 |
|---|---|---|
| CSS | style-loader + css-loader | 生产模式用 MiniCssExtractPlugin |
| Less/Sass | 预处理器 Loader | 添加对应预处理器依赖 |
| JS | babel-loader + ESLint | 开启缓存优化速度 |
| HTML | HtmlWebpackPlugin | 自动引入资源 |
| 图片 | Asset Modules | type: "asset" |
| 字体 | Asset Modules | type: "asset/resource" |
最佳实践总结:
- ✅ 开发模式使用
style-loader(热更新) - ✅ 生产模式使用
MiniCssExtractPlugin(提取 CSS) - ✅ 图片使用 Asset Modules(Webpack 5 内置)
- ✅ 字体图标使用
asset/resource - ✅ HTML 使用
HtmlWebpackPlugin自动生成 - ✅ 开启 Babel 和 ESLint 缓存
下一篇预告: 《高级优化实战》—— 深入讲解 PWA、Core-js、多进程打包、性能分析等高级主题,让你的项目达到生产级优化水准!
系列导航:
- 📌 第 1 篇:Webpack 入门与基础
- 📌 第 2 篇:开发模式完全指南
- 📌 第 3 篇:生产模式与性能优化
- 📌 第 4 篇:资源处理大全(本文)
- ⏭️ 第 5 篇:高级优化实战
本文基于 Webpack 5 编写,如有问题欢迎留言讨论。
评论 (0)