面试被问到webpack,可别只知道说 HtmlWebpackPlugin 了哇。
npm init -y
npm install webpack webpack-cli --save-dev
// package.json
{
"scripts": {
// ... 其他配置信息
"build": "webpack --mode production"
}
}
通过entry指定项目打包时的入口文件,可以配置单入口或者多入口
module.exports = {
entry: './path/to/my/entry/file.js',
};
module.exports = {
entry: {
index: './src/index.js',
info: './src/information.js',
},
};
通过output配置项目打包后的文件名以及文件的输出路径(位置)
什么是bundle?
根据入口文件,最后打包生成的、可以直接让浏览器解析的JS、CSS文件。
JS属于入口文件,那CSS为什么也可看作bundle?
html算不算?
HTML文件从严格意义上讲不算做bundle,因为不包含直接打包的代码或资源;
只是对打包好的资源做加载或展示;
CODE
module.exports = {
output: {
// 为什么这样命名?方便应用浏览器的缓存机制
filename: 'js/[name].[hash:8].js',
}
}
webpack官方:output->filename
webpack官方:缓存(输出哈希文件名)
官方给出:对应一个绝对路径,如何配置它的值?
绝对路径不做解释,懂得都懂,不懂得自查;
在node下提供了一个全局变量__dirname
,表示的就是当前执行的脚本文件所在的绝对路径;
CODE
module.exports = {
output: {
filename: 'js/[name].[hash:8].js',
// 将打包后的资源输出到当前目录下的 dist 目录中
path: path.resolve(__dirname, 'dist')
}
}
[name]
,[file]
,[query]
,[ext]
,[hash]
与[path]
module.exports = {
output: {
filename: 'js/[name].[hash:8].js',
path: path.resolve(__dirname, 'dist'),
// 将资源文件输出到 assets 目录下以hash码来命名
assetModuleFilename: 'assets/[hash][ext]',
}
}
module.exports = {
output: {
filename: 'js/[name].[hash:8].js',
path: path.resolve(__dirname, 'dist'),
assetModuleFilename: 'assets/[hash][ext]',
clean:true
}
}
优化:比如对代码进行压缩、分割代码、去除未使用的导出模块、去除空chunk等
module.exports = {
//...
optimization: {
minimize: true,
},
};
npm install terser-webpack-plugin --save-dev
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
// 为啥是数组?你就用一个吗?接受的类型就是数组类型
minimizer: [new TerserPlugin()],
},
};
npm install css-minimizer-webpack-plugin --save-dev
## 安装加载器
npm install mini-css-extract-plugin --save-dev
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
// 当前的主角配置
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin(),
],
},
module: {
rules: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [new MiniCssExtractPlugin()],
};
加载器在webpack这里有一个统称,叫loader,用于辅助webpack来加载非JS类型的文件,需要注意使用顺序。
webpack默认情况下只能处理Js文件,如果要处理其他文件,前提得让webpack能够加载其他文件,比如图片、CSS文件等。
配置在module
>rules
中,rules
是一个对象数组,对于某类文件的解析及配置写在对象中,其中test
指定某类文件,use
指定所需的加载器们。
标签的形式插入到 HTML 文档的
部分。
css-loader
一起使用,css-loader
会把 CSS 文件转换为 JavaScript 模块,style-loader
则会提取这个模块中的 CSS 代码,并动态地创建
标签将其插入到 HTML 页面中。module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader'],
},
],
},
};
css-loader
会对@import
和url()
进行处理,就像 js 解析import/require()
一样
url
/image-set
函数进行处理。 如果设置为false
,css-loader
将不会解析url
或者image-set
中的任何路径。module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader',
{
loader:"css-loader",
options:{
url: true // 解析 CSS 中的 url()——处理背景图时需要
}
}
],
},
],
},
};
MiniCssExtractPlugin
插件将这些 CSS 代码合并到一个或多个独立的 CSS 文件中,最后在 HTML 文件中通过
标签引入这些独立的 CSS 文件。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new CssMinimizerPlugin(),
],
},
module: {
rules: [
// 当前的主角配置
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
// 对应插件
plugins: [new MiniCssExtractPlugin()],
};
npm install --save-dev postcss-loader postcss
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
options: {
// 开启压缩
minimize: true,
// 处理 HTML 中的资源引用
sources: true,
},
},
],
},
};
资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。
在 webpack 5 之前,通常使用:
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
asset/resource
file-loader
实现。module.exports = {
// ...其他配置~
module: {
rules: [
{
test: /\.(png|jpeg|jpg|gif)$/i,
// 关键配置:仅匹配背景图路径(示例:src/css/imgs/ 目录)
include: path.resolve(__dirname, 'src/css/imgs'),
type: 'asset/resource',
generator: {
filename: 'bg-images/[name].[contenthash][ext]'
}
},
{
test: /\.(png|jpeg|jpg|gif)$/i,
// 关键配置:排除背景图路径,匹配其他图片(示例:src/assets/images/ 目录)
exclude: path.resolve(__dirname, 'src/css/imgs'),
type: 'asset/resource',
generator: {
// 为什么这里没有用哈希编码命名?因为资源名称涉及网络动态设定。
filename: 'images/[name][ext]'
}
}
]
}
};
asset/inline
url-loader
实现。asset/source
raw-loader
实现。asset
url-loader
,并且配置资源体积限制实现。asset/inline
,否则使用asset/resource
;可以使用parser.dataUrlCondition
来更改临界值。module.exports = {
// ...其他配置
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 // 调整阈值为 4KB
}
},
generator: {
filename: 'images/[name].[contenthash][ext]'
}
}
]
}
};
sass-loader:辅助webpack来加载sass文件。
sass-loader | webpack 中文文档
less-loader:辅助webpack来加载less文件。
less-loader | webpack 中文文档
html-webpack-plugin:根据html模板文件来将打包后的资源自动注入进该模版文件中,最后生成HTML文件。
html-webpack-plugin
可以自动完成这个任务,确保 HTML 文件引用的是最新的打包资源,以script或link引入相关资源。npm i html-webpack-plugin --save-dev
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/js/index.js',
detail: './src/js/info.js',
},
// ...其他配置
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
filename: 'index.html',
chunks: ['index'] // 只注入 index 代码块,也是因为这里的设置才让对应的css能够引入到html中,因为css属于chunk,chunk关联html
}),
new HtmlWebpackPlugin({
template: './public/detail.html',
filename: 'detail.html',
chunks: ['detail'] // 只注入 detail 代码块
})
]
};
MiniCssExtractPlugin:为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并将CSS代码抽离到单独的文件中,而不会让CSS嵌入在Js中。
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
plugins: [
new MiniCssExtractPlugin({filename: 'css/[name].[hash:8].css'})
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
};
CssMinimizerPlugin:对每个CSS文件进行压缩处理。
optimization.minimize
设置为true
。const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
optimization: {
minimizer: [
new CssMinimizerPlugin(),
],
},
plugins: [new MiniCssExtractPlugin()],
};
postcss :一个CSS处理引擎,需要结合postcss-loader来使用在webpack中,有autoprefixer、cssnano、postcss-preset-env等常用插件。
为解决浏览器兼容问题,为css相关样式添加前缀。
需要安装postcss-loader、postcss、autoprefixer
Autoprefixer CSS online
CODE
npm i postcss-loader postcss autoprefixer -D
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
],
},
],
},
};
// package.json
{
// 其他配置
"browserslist": [
"last 2 versions",
"ie >= 8",
"Chrome > 31",
"> 1%"
]
}
// postcss.config.js
module.exports = {
plugins: [require('autoprefixer')]
}
TerserWebpackPlugin:虽然由社区成员维护的第三方包,基于terser来对Javascript进行压缩处理,在webpack中开箱即用,安装配置即可。
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
optimization: {
minimize: true,
minimizer: [new TerserPlugin()]
}
}
// 自动导入 ../images 目录下所有扩展名为 .png、.jpg、.jpeg 或 .gif 的图片文件
require.context('../images', false, /\.(png|jpe?g|gif)$/)
// 由于这些图片可能在多个html中都会用到,所以可以创建一个入口文件写入该代码,配置在entry中,这样webpack就可以知道对这些图片做模块打包了。
'../images'
:这是第一个参数,表示要搜索的目录路径。在这个例子中,Webpack 会从当前文件所在目录的上一级的images
目录开始搜索符合条件的文件。false
:第二个参数是一个布尔值,用于指定是否要递归搜索子目录。false
表示不进行递归搜索,即只在../images
目录下查找文件,而不会深入到其子目录中。如果设置为true
,则会递归搜索该目录下的所有子目录。/.(png|jpe?g|gif)$/
:第三个参数是一个正则表达式,用于筛选符合条件的文件。这个正则表达式表示只匹配扩展名为.png
、.jpg
、.jpeg
或.gif
的文件。由于使用了html-webpack-plugin,可以自动对css和js文件通过link或script插入到html模板中,所以检查是否模板并非模版而是原始的html文件;或者html模板中有引入相对路径下的源码文件。
文件哈希+浏览器缓存
譬如资源的304状态码,其实是由于浏览器中缓存了该资源,且本次请求的该资源同缓存的资源一致,没有变化,直接使用缓存的资源。
就是处理文件读取的关键点,是服务器响应资源时返回的一个唯一标识符,用于标识资源的具体版本。它通常基于资源内容生成(如哈希值、文件大小、修改时间等),类似于文件的 “指纹”。
Etag
,询问服务器资源是否更新:
若资源未更新:
服务器返回304 Not Modified
,告知浏览器可直接使用本地缓存,不返回资源内容,减少带宽消耗。
若资源已更新:
服务器返回新资源内容和新的Etag
,浏览器更新缓存。
Cache-Control
:控制缓存的 “有效期”(如max-age=31536000
表示缓存 1 年)。Etag
:在缓存过期后,作为精确验证手段,确保浏览器获取到最新资源。
Cache-Control
未过期,浏览器直接使用缓存,不触发 Etag 验证;Cache-Control
过期,浏览器发送带If-None-Match
的请求,通过 Etag 验证资源是否真的需要更新。Last-Modified
和Etag
,服务器会优先验证Etag
(If-None-Match
优先级高于If-Modified-Since
)。