资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。
在 webpack 5 之前,通常使用:
raw-loader
将文件导入为字符串url-loader
将文件作为 data URI 内联到 bundle 中file-loader
将文件发送到输出目录资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
下面的例子分别通过不同类型文件,来验证资源模块类型。
例子结构:
webpack 基础配置:
'use strict';
const path = require('path');
const svgToMiniDataURI = require('mini-svg-data-uri');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
},
resolve: {
},
devtool: 'source-map',
plugins: [
]
};
index.html 引入打包之后的js文件:
<!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>Document</title>
</head>
<body>
<script src="./dist/bundle.js"></script>
</body>
</html>
Resource 模式的作用是将 资源输送到指定目录,修改名称,并且其路径将被注入到 bundle 中。
例子过程描述:
这里添加img1 图片
webpack.config 文件里 ,配置png 文件为Resource 模式
module: {
rules: [
{
test: /\.png/,
type: 'asset/resource'
}
}
指定图片打包之后的文件夹,如果不指定默认打包到根目录。
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
assetModuleFilename: 'images/[hash][ext][query]'
},
webpack 打包入口文件为 index.js , 这里以后会陆续引入图片资源。
index.js :
/*
* @Author: ZY
* @Date: 2022-02-16 10:44:46
* @LastEditors: ZY
* @LastEditTime: 2022-02-16 14:55:09
* @FilePath: /webpack-demo/packages/asset-demo/src/index.js
* @Description: 打包资源
*/
import png from "../images/img1.png";
const container = document.createElement("div");
Object.assign(container.style, {
display: "flex",
flexDirection:'column',
justifyContent: "center",
});
document.body.appendChild(container);
function createImageElement(title, src) {
const div = document.createElement("div");
div.style.textAlign = "center";
const h2 = document.createElement("h2");
h2.textContent = title;
div.appendChild(h2);
const img = document.createElement("img");
img.setAttribute("src", src);
img.setAttribute("width", "150");
div.appendChild(img);
container.appendChild(div);
}
[png].forEach((src,index) => {
const typeArray = ['resource']
createImageElement(typeArray[index], src);
});
执行webpack 打包后的结果:
自定注入bundle.js 里:
以html 文件为例,所有的html 文件都会被输出到static 目录下:
{
test: /\.html/,
type: 'asset/resource',
generator: {
filename: 'static/[hash][ext][query]'
}
},
在项目目录里放一个test,html 文件并在入口index.js 文件里引入,执行webpack 打包。
验证结果如下:
inline 资源模式,默认将图片编程base64 的格式,注入到bundle.js 内部。
内联模式以jpeg 类型文件为例。
引入img2,jpeg 文件
{
test: /\.jpeg/,
type: 'asset/inline'
},
图片变成了base64 出现在bundlle.js 里
webpack 输出的 data URI,默认是呈现为使用 Base64 算法编码的文件内容。
如果要使用自定义编码算法,则可以指定一个自定义函数来编码文件内容,
以 svg 图片为例,利用mini-svg-data-uri压缩编码格式
/*
* @Author: ZY
* @Date: 2022-02-15 15:51:35
* @LastEditors: ZY
* @LastEditTime: 2022-02-16 14:56:22
* @FilePath: /webpack-demo/packages/asset-demo/webpack.config.js
* @Description: 文件描述
*/
'use strict';
const svgToMiniDataURI = require('mini-svg-data-uri');
module.exports = {
module: {
rules: [
{
test:/\.svg/,
type: 'asset/inline',
generator: {
dataUrl: content => {
content = content.toString();
return svgToMiniDataURI(content);
}
}
},
]
},
};
将文件原样注入到打包后的文件,类似raw-loader实现
例子以 txt 文件为例
新建txt 文文件
index.js 引入:
import helloText from "./hello.txt";
const text = document.createElement("h2");
text.textContent = helloText;
container.appendChild(text);
{
test:/\.txt/,
type:'asset/source'
},
打包完之后,直接内容到bundle.js :
现在,webpack 将按照默认条件,自动地在 resource 和 inline 之间进行选择:小于 8kb 的文件,将会视为 inline 模块类型,否则会被视为 resource 模块类型。
为了更好的验证,引入小于8kb 文件和大于8kb 文件
例子以jpg 文件为例
{
test:/\.jpg/,
type:'asset'
}
dist 只有 大于290kb 文件资源,小于8kb 的会被内联。具体看demo案例。
webpack5 引入资源干掉了一堆loader,改为type 模式loader,更清晰。本文示例详细,文章没有提及到的请查看demo。