目前为止,我们的项目可以在控制台上显示 "Hello world~~~"。现在我们尝试混合一些其他资源,比如 images,看看 webpack 如何处理。
在 webpack 出现之前,前端开发人员会使用 grunt 和 gulp 等工具来处理资源,并将它们从 /src 文件夹移动到 /dist 或 /build 目录中。webpack 最出色的功能之一就是,除了引入 JavaScript,还可以内置的资源模块 Asset Modules 引入任何其他类型的文件。
资源模块(asset module)是一种模块类型,它允许我们应用Webpack来打包其他资源文件(如字体,图标等)
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
- asset/resource 发送一个单独的文件并导出 URL。
- asset/inline 导出一个资源的 data URI。
- asset/source 导出资源的源代码。
- asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。
1.5.1 Resource 资源
修改 webpack.config.js配置:
// 配置资源文件
module: {
rules: [{
test: /\.png/,
type: 'asset/resource'
}]
},
06-asset-modules/webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
//...
// 配置资源文件
module: {
rules: [{
test: /\.png/,
type: 'asset/resource'
}]
},
//...
}
准备资源文件,在入口文件中引入,并显示在页面上:
06-asset-modules/src/index.js
// 导入函数模块
import helloWorld from './hello-world.js'
import imgsrc from './assets/img-1.png'
helloWorld()
const img = document.createElement('img')
img.src = imgsrc
document.body.appendChild(img)
执行打包命令:
[felix] 06-asset-modules $ npx webpack
asset 8ec2798f81f4745a7c9b.png 101 KiB [emitted] [immutable] [from: src/assets/img-1.png] (auxiliary name: main)
asset bundle.js 10.5 KiB [emitted] (name: main)
asset app.html 326 bytes [emitted]
runtime modules 1.72 KiB 5 modules
cacheable modules 388 bytes (javascript) 101 KiB (asset)
./src/index.js 208 bytes [built] [code generated]
./src/hello-world.js 138 bytes [built] [code generated]
./src/assets/img-1.png 42 bytes (javascript) 101 KiB (asset) [built] [code generated]
webpack 5.54.0 compiled successfully in 114 ms
发现图片(.png)文件已经打包到了dis目录下:
执行启动服务命令:
打开浏览器:
自定义输出文件名
默认情况下,`asset/resource` 模块以 `[contenthash][ext][query]` 文件名发送到输出目录。
可以通过在 webpack 配置中设置 [`output.assetModuleFilename`](Output | webpack 中文文档) 来修改此模板字符串:
output: {
assetModuleFilename: 'images/[contenthash][ext][query]'
},
06-asset-modules/webpack.config.js
//...
module.exports = {
//...
output: {
//...
assetModuleFilename: 'images/[contenthash][ext][query]'
},
//...
}
执行编译:
[felix] 06-asset-modules $ npx webpack
assets by status 101 KiB [cached] 1 asset
asset bundle.js 10.5 KiB [compared for emit] (name: main)
asset app.html 326 bytes [compared for emit]
runtime modules 1.72 KiB 5 modules
cacheable modules 356 bytes (javascript) 101 KiB (asset)
./src/index.js 208 bytes [built] [code generated]
./src/hello-world.js 106 bytes [built] [code generated]
./src/assets/img-1.png 42 bytes (javascript) 101 KiB (asset) [built] [code generated]
webpack 5.54.0 compiled successfully in 125 ms
另一种自定义输出文件名的方式是,将某些资源发送到指定目录,修改配置:
rules: [{
test: /\.png/,
type: 'asset/resource',
// 优先级高于 assetModuleFilename
generator: {
filename: 'images/[contenthash][ext][query]'
}
}]
06-asset-modules/webpack.config.js
//...
module.exports = {
//...
output: {
//...
// 配置资源文件
module: {
rules: [
{
test: /\.png/,
type: 'asset/resource',
// 优先级高于 assetModuleFilename
generator: {
filename: 'images/[contenthash][ext][query]'
}
}
],
},
//...
}
执行编译:
[felix] 06-asset-modules $ npx webpack
assets by status 102 KiB [cached] 2 assets
assets by path . 10.5 KiB
asset bundle.js 10.5 KiB [compared for emit] (name: main)
asset app.html 71 bytes [compared for emit]
runtime modules 1.72 KiB 5 modules
cacheable modules 356 bytes (javascript) 101 KiB (asset)
./src/index.js 208 bytes [built] [code generated]
./src/hello-world.js 106 bytes [built] [code generated]
./src/assets/img-1.png 42 bytes (javascript) 101 KiB (asset) [built] [code generated]
webpack 5.54.0 compiled successfully in 113 ms
输出结果与 `assetModuleFilename` 设置一样。
1.5.2 inline 资源
修改 `webpack.config.js`配置:
// 配置资源文件
module: {
[
{
test: /\.svg/,
type: 'asset/inline'
}
],
}
06-asset-modules/webpack.config.js
//...
module.exports = {
//...
// 配置资源文件
module: {
rules: [
//...
{
test: /\.svg/,
type: 'asset/inline'
}
],
},
//...
}
执行启动服务命令:
打开浏览器:
可见, .svg 文件都将作为 data URI 注入到 bundle 中。
- 自定义 data URI 生成器
webpack 输出的 data URI,默认是呈现为使用 Base64 算法编码的文件内容。
如果要使用自定义编码算法,则可以指定一个自定义函数来编码文件内容。
安装自定义函数模块:
[felix] webpack5 $ npm install mini-svg-data-uri -D
修改配置文件:
const svgToMiniDataURI = require('mini-svg-data-uri')
rules: [
{
test: /\.svg/,
type: 'asset/inline',
generator: {
dataUrl: content => {
content = content.toString();
return svgToMiniDataURI(content);
}
}
}
]
06-asset-modules/webpack.config.js
//...
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);
}
}
}
],
},
//...
}
现在,所有 `.svg` 文件都将通过 `mini-svg-data-uri` 包进行编码。重新启动服务,在浏览器查看效果:
1.5.3 source 资源
source资源,导出资源的源代码。修改配置文件,添加:
module: {
rules: [
test: /\.txt/,
type: 'asset/source'
]
}
06-asset-modules/webpack.config.js
//...
module.exports = {
//...
// 配置资源文件
module: {
rules: [
//...
{
test: /\.txt/,
type: 'asset/source'
}
],
},
//...
}
在assets里创建一个 `example.txt`文件:
06-asset-modules/src/assets/example.txt
hello webpack
在入口文件里引入一个 .txt文件,添加内容:
import exampleText from './assets/example.txt'
const block = document.createElement('div')
block.style.cssText = `width: 200px; height: 200px; background: aliceblue`
block.textContent = exampleText
document.body.appendChild(block)
06-asset-modules/src/index.js
// 导入函数模块
//...
import exampleText from './assets/example.txt'
//...
const block = document.createElement('div')
block.style.cssText = `width: 200px; height: 200px; background: aliceblue`
block.textContent = exampleText
document.body.appendChild(block)
//...
启动服务,打开浏览器:
所有 `.txt` 文件将原样注入到 bundle 中。
1.5.4 通用资源类型
通用资源类型 asset , 在导出一个 data URI 和发送一个单独的文件之间自动选择。
修改配置文件:
module: {
rules: [
test: /\.jpg/,
type: 'asset'
]
}
现在,webpack 将按照默认条件,自动地在 `resource` 和 `inline` 之间进行选择:小于 8kb 的文件,将会视为 `inline` 模块类型,否则会被视为 `resource` 模块类型。
可以通过在 webpack 配置的 module rule 层级中,设置 [`Rule.parser.dataUrlCondition.maxSize`](Module | webpack 中文文档) 选项来修改此条件:
rules: [
{
test: /\.jpg/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 // 4kb
}
}
}
]
06-asset-modules/webpack.config.js
//...
module.exports = {
//...
// 配置资源文件
module: {
rules: [
//...
{
test: /\.jpg/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 // 4kb
}
}
}
],
},
//...
}
在 `assets`目录下创建 `.jpg` 文件,然后在入口文件中引入:
import jpgMap from './assets/qianfeng-sem.jpg'
const img3 = document.createElement('img')
img3.style.cssText = 'width: 600px; height: 240px; display: block'
img3.src = jpgMap
document.body.appendChild(img3)
06-asset-modules/src/index.js
// 导入函数模块
//...
import jpgMap from './assets/qianfeng-sem.jpg'
//...
const img3 = document.createElement('img')
img3.style.cssText = 'width: 600px; height: 240px; display: block'
img3.src = jpgMap
document.body.appendChild(img3)
启动服务,打开浏览器:
执行编译命令:
[felix] 06-asset-modules $ npx webpack
assets by status 101 KiB [cached] 1 asset
assets by status 653 KiB [emitted]
asset images/33120e6c4bd92df7bec8.jpg 637 KiB [emitted] [immutable] [from: src/assets/qianfeng-sem.jpg] (auxiliary name: main)
asset bundle.js 15.7 KiB [emitted] (name: main)
asset app.html 326 bytes [compared for emit]
runtime modules 1.72 KiB 5 modules
cacheable modules 4.03 KiB (javascript) 738 KiB (asset)
asset modules 3.1 KiB (javascript) 738 KiB (asset)
./src/assets/img-1.png 42 bytes (javascript) 101 KiB (asset) [built] [code generated]
./src/assets/webpack-logo.svg 2.99 KiB [built] [code generated]
./src/assets/example.txt 25 bytes [built] [code generated]
./src/assets/qianfeng-sem.jpg 42 bytes (javascript) 637 KiB (asset) [built] [code generated]
javascript modules 949 bytes
./src/index.js 843 bytes [built] [code generated]
./src/hello-world.js 106 bytes [built] [code generated]
webpack 5.54.0 compiled successfully in 139 ms
发现当前的 `.jpg`文件被打包成了单独的文件,因为此文件大小超过了 `4kb`。
本文暂时没有评论,来添加一个吧(●'◡'●)