- 作者简介:大家好,我是文艺理科生Owen,某车企前端开发,负责AIGC+RAG项目
- 目前在卷的技术方向:工程化系列,主要偏向最佳实践
- 希望可以在评论区交流互动,感谢支持~~~
上一篇我们从0开始构建了webpack的最小化项目,分别举例说明了ES6语法、css语法、typescript语法和tsx语法的编译转换。
在实际的项目开发中,存在多种类型的静态文件,如图片、文本文件、字体文件等。在webpack4中,需要引入对应的loader去逐个解决。但在webpack5中,有更为简便的使用方式。相应的,文章后面也会列举vite的静态资源模块的最佳实践。
webpack5中处理资源模块
静态资源模块(Asset Modules)
回顾webpack4中,处理静态资源需要使用 raw-loader、url-loader、file-loader等。但在webpack5中,可以使用内置的静态资源模块更方便地处理静态资源。
其中有4种静态资源模块类型。
webpack5 | 用途 | 替代webpack4的loader名称 |
---|---|---|
asset/resource | 导出静态资源的独立文件到输出目录中,并导出独立文件的url | file-loader |
asset/inline | 导出静态资源的data URI | url-loader |
asset/source | 导出静态资源的源代码 | raw-loader |
asset | 在 导出静态资源的 data URI 和 单独文件 自动选择 | url-loader |
接着上一篇文章的 demo,稍作一些修改,当前目录为:
├─ package.json
├─ pnpm-lock.yaml
├─ README.md
├─ src
│ ├─ index.js
│ └─ index.txt
└─ webpack.config.js
// index.txt
webpack
// package.json
{
"name": "demo",
"version": "1.0.0",
"description": "V6.0.0 从零到一搭建项目脚手架,梳理工程化中构建的来龙去脉",
"main": "index.js",
"scripts": {
"dev": "webpack --mode development --config webpack.config.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
},
"browserslist": "> 0.05%, not dead"
}
// webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
clean: true
}
}
我们看到在src目录下新建了一个txt文件,并且在入口文件index.js中引入了txt文件。默认情况下,运行pnpm dev
命令打包后,发现 index.txt文件内容会作为字符串嵌入到输出的bundle.js中。
输出独立文件
修改webpack配置,对txt文件采用asset/resource类型处理。
// webpack.config.js
module.exports = {
+ module: {
+ rules: [
+ {
+ test: /.txt$/,
+ type: 'asset/resource' // 对txt文件采用asset/resource类型处理
+ }
+ ]
+ }
}
运行pnpm dev
命令打包后,发现 在输出目录中 直接输出了txt独立文件,并在bundle文件中带出了该独立文件的url。
输出data URI
修改webpack配置,对txt文件采用asset/inline类型处理。
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /.txt$/,
- type: 'asset/resource'
+ type: 'asset/inline' // 对txt文件采用asset/inline类型处理
}
]
}
}
运行pnpm dev
命令打包后,发现在bundle文件中直接生成了base64地址。
输出源代码
修改webpack配置,对txt文件采用asset/source类型处理。
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /.txt$/,
- type: 'asset/inline'
+ type: 'asset/source' // 对txt文件采用asset/source类型处理
}
]
}
}
运行pnpm dev
命令打包后,发现在bundle文件中直接采用module.exports导出了文本内容。
这里需要说明一下:
默认不加配置时,也是作为asset/source类型转为文本内容,但只是作为字符串嵌入,未对外导出。
显式配置为asset/source后,会把txt当做一个模块,使用module.exports导出文本内容,供其他模块使用。
输出独立文件 vs 输出data URI
修改webpack配置,对txt文件采用asset类型处理。
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /.txt$/,
- type: 'asset/source'
+ type: 'asset' // 对txt文件采用asset类型处理
}
]
}
}
运行pnpm dev
命令打包后,发现txt文件是以data URI形式导出的。
默认规则是:小于8kb的文件将被视为 inline 模块类型,否则将被视为 resource 模块类型。
我们在webpack配置中修改一下分界的大小(1Byte):
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /.txt$/,
- type: 'asset'
+ type: 'asset', // 对txt文件采用asset类型处理
+ parser: {
+ dataUrlCondition: {
+ maxSize: 1 // 1byte
+ }
+ }
}
]
}
}
运行pnpm dev
命令打包后,发现txt文件是单独文件的形式导出的。
总结一下:webpack5直接通过对应的type类型设置文件导出的形式。
Vite中处理资源模块
输出独立文件 vs 输出data URI
为了更好地理解vite打包处理资源模块,这里不使用cli方式,继续在项目中演示。可能有小伙伴会问,webpack和vite能在一个项目中共存吗?项目中是不会这么使用的,但对于一个demo来说,只要区分使用命令,就不会有影响。
首先安装vite:pnpm i vite -D
,创建vite构建命令
// package.json
{
"name": "demo",
"version": "1.0.0",
"description": "V6.0.1 webpack5和vite如何处理资源模块",
"main": "index.js",
"scripts": {
"dev": "webpack --mode development --config webpack.config.js",
+ "build": "vite build"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4",
+ "vite": "5.2.11"
},
"browserslist": "> 0.05%, not dead"
}
在根目录下创建vite配置文件vite.config.js
。
// vite.config.js
export default {
}
可以看到这里没有指明entry(入口文件),是因为vite基于ESM规范,也就是采用script标签中的type=module
进行打包构建。所以需要在根目录下新建一个index.html,并且script的src属性指向入口文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module" src="/src/index.js"></script>
</body>
</html>
运行pnpm build
命令打包后,发现txt文件是以data URI的形式导出的。
与webpack类似,导出 独立文件 或 data URI形式是按文件大小自动选择的。vite中是通过 assetsInlineLimits属性设置(默认为4kB)。但不同的是,在vite中当静态资源超过assetsInlineLimits值时,即使采用了内联语法(?inline)后,依然不会强制生成data URI形式。
修改一下vite配置:
// vite.config.js
export default {
build: {
assetsInlineLimit: 1 // 1个字节
}
}
运行pnpm build
命令打包后,发现txt文件是以独立文件的形式导出的。
输出源代码
修改index.js文件:
- import text from './index.txt'
+ import text from './index.txt?raw'
console.log(text);
运行pnpm build
命令打包后,发现txt文件是以文本字符串的形式直接嵌入的。
总结:本文通过一个最小的Webpack和vite项目demo,举例演示了在webpack5中采用内置属性将静态资源模块以不同形式导出,并且说明了在vite中如何处理静态资源模块。
demo源码:github
日拱一卒,功不唐捐。