Open maicFir opened 2 years ago
在前面几篇文章中,我们已经基础的如何运用一个webpack与webpack-cli从 0 到 1 搭建一个简单的react或者vue工程应用,其中我们使用了加载文件,我们在之前处理文件使用file-loader或者url-loader处理,url-loader主要是可以针对图片文件大小进行有选择的base64压缩,在webpack5中可以用内置的Asset Modules来处理图片资源
webpack
webpack-cli
file-loader
url-loader
base64
webpack5
Asset Modules
接下来我们一起来探讨下webpack5中关于Asset Modules的那些事
正文开始...
新建一个文件夹webpack-04-resource,
webpack-04-resource
npm init -y
我们安装项目一些基础支持的插件
npm i webpack webpack-cli webpack-dev-server html-webpack-plugin babel-loader @babel l/core -D
在根目录新建webpack.config.js
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { entry: './src/index.js', output: { filename: 'js/[name].js', path: path.resolve(__dirname, 'dist') }, mode: 'development', module: { rules: [ { test: /\.js$/, loader: 'babel-loader', options: { presets: ['@babel/env'] } }, { test: /\.(png|jpg)$/i, type: 'asset/resource' } ] }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ template: './public/index.html' }) ] };
注意我们加载图片没有使用file-loader与url-loader,我们使用的是webpack5内置的asset/rosource这个来处理
asset/rosource
module.exports = { module: { rules: [ { test: /\.(png|jpg)$/i, type: 'asset/resource' } ] } };
在index.js中我们插入一张图片
index.js
import img1Src from '../assets/images/1.png'; var appDom = document.getElementById('app'); const img = new Image(); img.src = img1Src; appDom.appendChild(img);
ok,运行npm run server,打开浏览器localhost:8080 我们会发现,生成的图片地址就是<img src="http://localhost:8080/js/../b1640e009cff6a775ce5.png">
npm run server
localhost:8080
<img src="http://localhost:8080/js/../b1640e009cff6a775ce5.png">
现在我想配置图片的默认输出地址与名字,在module.rules中有一个generator的属性可以配置匹配图片输出的文件
module.rules
generator
// webpack.config.js module.exports = { module: { rules: [ ...{ test: /\.(png|jpg)$/i, type: 'asset/resource', generator: { filename: 'images/[name][ext]' } } ] } };
此时页面加载图片的路径就变成<img src="http://localhost:8080/js/../images/1.png">了
<img src="http://localhost:8080/js/../images/1.png">
如果你的图片地址是上传到cdn上的,那么你可以这么做,但是这种做法是不是在项目中真的需要,还有待商榷,因为这样会导致应用所有的所有图片用cdn方式加载,如果项目中只是部分图片按需 cdn 加载,那么这种做法是不可取的。
cdn
{ test: /\.(png|jpg)$/i, // type: 'asset/resource' type: 'asset', parser: { dataUrlCondition: { maxSize: 40 * 1024 } }, generator: { publicPath: 'https://cdn/assets', // cdn域名前缀 filename: 'images/[name][ext]' } }
自此页面的加载的图片就是<img src="https://cdn/assets/images/3.png">
<img src="https://cdn/assets/images/3.png">
除了generator.filename方式,你也可以在output中加入assetModuleFilename配置来修改图片默认的地址,不过注意这个属性只能是针对rule中设置的 type''asset/resource' | 'asset'类型才生效。
generator.filename
output
assetModuleFilename
rule
''asset/resource' | 'asset'
module.exports = { output: { filename: 'js/[name].js', path: path.resolve(__dirname, 'dist'), assetModuleFilename: 'images/[name][ext]' } };
通常项目里我们会把比较小的图片直接坐base64加载,大的图片就直接输出加载,或者上传到cdn直接加载图片地址,你可以在rules的generator.publicPath设置地址图片地址。
rules
generator.publicPath
因此我引入两张大小不一样的图片测试,修改一下index.js
import img1Src from '../assets/images/1.png'; import img3Src from '../assets/images/3.png'; function renderImage(imageSource) { const weakMap = new WeakMap(); var appDom = document.getElementById('app'); imageSource.forEach((src) => { const img = new Image(); weakMap.set(img, img); if (weakMap.has(img)) { weakMap.get(img).src = src; appDom.appendChild(img); } }); } renderImage([img1Src, img3Src]);
我们再修改下webpack.config.js
module.exports = { module: { rules: [ ...{ test: /\.(png|jpg)$/i, // type: 'asset/resource' type: 'asset', parser: { dataUrlCondition: { maxSize: 40 * 1024 } } } ] } };
在rules中增加parser属性,并且将type改成asset,当我们设置一个dataUrlCondition: {maxSize: 40 * 1024},小于KB就用base64加载了,大于40KB就直接用图片路径加载
parser
type
asset
dataUrlCondition: {maxSize: 40 * 1024}
KB
40KB
因此我们可以看到两张图片,一张图片是base64一张图片就走文件路径了。
所以在你的项目中你可以利用这个parser.dataUrlCondition.maxSize特性来优化图片资源,有些资源小图片就可以用base64来加载,这样可以减少页面图片的资源请求
parser.dataUrlCondition.maxSize
但是并不是所有的图片都要base64,base64生成的字符串非常大,同时也是增加了html的体积,无法利用缓存机制加载图片。
html
所以在优化的网页加载过程中,并不是全部都用base64来加载图片。
主要参考官网asset-modules
webpack5 之前
Data Url
bundle.js
webpack5 现在
用asset module type通过添加以下四种类型来代替以上loader
asset module type
loader
url
row-loader
parse.dataUrlCondition.maxSize
相比较webpack5之前我们加载图片资源文件使用file-loader或者url-loader在webpack5中可以使用内置模块type: 'assets/resource'
type: 'assets/resource'
基于 webpack5 内置模块asset module type来设置资源的加载
图片资源base64处理,根据图片资源的大小parse.dataUrlCondition.maxSize来限制是否需要base64输出
比较asset module type几种模式区别,代替以前row-loader、file-loader、url-loader方案,但是这仅仅是你的webpack版本在 5 以后。
本文code example
在前面几篇文章中,我们已经基础的如何运用一个
webpack
与webpack-cli
从 0 到 1 搭建一个简单的react或者vue工程应用,其中我们使用了加载文件,我们在之前处理文件使用file-loader
或者url-loader
处理,url-loader
主要是可以针对图片文件大小进行有选择的base64
压缩,在webpack5
中可以用内置的Asset Modules
来处理图片资源接下来我们一起来探讨下
webpack5
中关于Asset Modules的那些事正文开始...
初始化基础项目
新建一个文件夹
webpack-04-resource
,我们安装项目一些基础支持的插件
在根目录新建
webpack.config.js
注意我们加载图片没有使用
file-loader
与url-loader
,我们使用的是webpack5
内置的asset/rosource
这个来处理在
index.js
中我们插入一张图片ok,运行
npm run server
,打开浏览器localhost:8080
我们会发现,生成的图片地址就是<img src="http://localhost:8080/js/../b1640e009cff6a775ce5.png">
generator 配置
现在我想配置图片的默认输出地址与名字,在
module.rules
中有一个generator
的属性可以配置匹配图片输出的文件此时页面加载图片的路径就变成
<img src="http://localhost:8080/js/../images/1.png">
了如果你的图片地址是上传到
cdn
上的,那么你可以这么做,但是这种做法是不是在项目中真的需要,还有待商榷,因为这样会导致应用所有的所有图片用cdn
方式加载,如果项目中只是部分图片按需 cdn 加载,那么这种做法是不可取的。自此页面的加载的图片就是
<img src="https://cdn/assets/images/3.png">
assetModuleFilename
除了
generator.filename
方式,你也可以在output
中加入assetModuleFilename
配置来修改图片默认的地址,不过注意这个属性只能是针对rule
中设置的 type''asset/resource' | 'asset'
类型才生效。通常项目里我们会把比较小的图片直接坐
base64
加载,大的图片就直接输出加载,或者上传到cdn
直接加载图片地址,你可以在rules
的generator.publicPath
设置地址图片地址。因此我引入两张大小不一样的图片测试,修改一下
index.js
我们再修改下
webpack.config.js
在
rules
中增加parser
属性,并且将type
改成asset
,当我们设置一个dataUrlCondition: {maxSize: 40 * 1024}
,小于KB
就用base64
加载了,大于40KB
就直接用图片路径加载因此我们可以看到两张图片,一张图片是
base64
一张图片就走文件路径了。所以在你的项目中你可以利用这个
parser.dataUrlCondition.maxSize
特性来优化图片资源,有些资源小图片就可以用base64
来加载,这样可以减少页面图片的资源请求但是并不是所有的图片都要
base64
,base64
生成的字符串非常大,同时也是增加了html
的体积,无法利用缓存机制加载图片。所以在优化的网页加载过程中,并不是全部都用
base64
来加载图片。关于内置模块的几个参数
主要参考官网asset-modules
webpack5 之前
Data Url
嵌入到打包后bundle.js
中,比如base64
文件webpack5 现在
用
asset module type
通过添加以下四种类型来代替以上loader
url
,是file-loader
的替代品url-loader
的替代品row-loader
的替代品url-loader
和file-loader
中选择,配置parse.dataUrlCondition.maxSize
来输出图片资源是否base64
输出总结
相比较
webpack5
之前我们加载图片资源文件使用file-loader
或者url-loader
在webpack5
中可以使用内置模块type: 'assets/resource'
基于 webpack5 内置模块
asset module type
来设置资源的加载图片资源
base64
处理,根据图片资源的大小parse.dataUrlCondition.maxSize
来限制是否需要base64
输出比较
asset module type
几种模式区别,代替以前row-loader
、file-loader
、url-loader
方案,但是这仅仅是你的webpack
版本在 5 以后。本文code example