Appearance
文件类型
Bun 内置文件加载器详解
Bun 打包器内置了一系列默认加载器,让我们可以直接处理多种文件类型。通常来说,Bun 的打包器和运行时都支持相同的文件类型集合。
支持的文件类型
Bun 原生支持以下文件类型:
.js
.cjs
.mjs
- JavaScript 文件.mts
.cts
.ts
.tsx
.jsx
- TypeScript 和 JSX 文件.toml
.json
- 配置和数据文件.txt
.wasm
.node
.html
- 其他常用文件类型
加载器工作原理
Bun 通过文件扩展名来确定应该使用哪个内置加载器来解析文件。每个加载器都有一个名称,如js
、tsx
或json
。这些名称在构建插件时用于扩展 Bun 的自定义加载器功能。
您可以使用loader
导入属性显式指定要使用的加载器:
ts
// 使用toml加载器处理my_file文件
import my_toml from "./my_file" with { loader: "toml" };
内置加载器详解
让我们深入了解 Bun 提供的各种加载器及其特性。
JavaScript 加载器
js
加载器
适用于:.cjs
和 .mjs
文件。
这个加载器会解析 JavaScript 代码并应用一系列默认转换,如:
- 消除死代码(Dead-code elimination)
- 树摇(Tree shaking)优化
目前 Bun 不会尝试降级语法(即不会转换新语法为兼容旧浏览器的代码)
jsx
加载器
适用于:.js
和 .jsx
文件。
与js
加载器功能相同,但支持 JSX 语法。默认情况下,JSX 会被转换为纯 JavaScript。转换的具体方式取决于tsconfig.json
中的jsx*
编译器选项。
TIP
JSX 编译选项有关 JSX 编译选项的更多信息,可以参考TypeScript 的 JSX 文档。
TypeScript 加载器
ts
加载器
适用于:.ts
、.mts
和 .cts
文件。
这个加载器会移除所有 TypeScript 语法,然后按照js
加载器的方式处理代码。需要注意的是,Bun 不执行类型检查。
tsx
加载器
适用于:.tsx
文件。
同时转译 TypeScript 和 JSX 语法为纯 JavaScript。
数据文件加载器
json
加载器
适用于:.json
文件。
JSON 文件可以直接导入到代码中,非常方便:
ts
import pkg from "./package.json";
console.log(pkg.name); // => "my-package"
在打包过程中,解析后的 JSON 会作为 JavaScript 对象内联到 bundle 中:
ts
var pkg = {
name: "my-package",
// ... 其他字段
};
console.log(pkg.name);
如果将.json
文件作为打包器的入口点,它将被转换为一个.js
模块,并通过export default
导出解析后的对象。
json
{
"name": "小明",
"age": 35,
"email": "[email protected]"
}
js
export default {
name: "小明",
age: 35,
email: "[email protected]",
};
toml
加载器
适用于:.toml
文件。
TOML 文件同样可以直接导入。Bun 使用其高性能的原生 TOML 解析器来处理这些文件。
ts
import config from "./bunfig.toml";
console.log(config.logLevel); // => "debug"
// 通过导入属性指定加载器:
// import myCustomTOML from './my.config' with {type: "toml"};
在打包过程中,解析后的 TOML 会作为 JavaScript 对象内联到 bundle 中,工作方式与 JSON 加载器类似:
ts
var config = {
logLevel: "debug",
// ...其他字段
};
console.log(config.logLevel);
如果将.toml
文件作为入口点,它将被转换为一个.js
模块,并通过export default
导出解析后的对象。
toml
name = "小明"
age = 35
email = "[email protected]"
js
export default {
name: "小明",
age: 35,
email: "[email protected]",
};
其他文件类型加载器
text
加载器
适用于:.txt
文件。
文本文件可以直接导入。加载器会读取文件并将其内容作为字符串返回。
ts
import contents from "./file.txt";
console.log(contents); // => "你好,世界!"
// 将html文件作为文本导入
// 使用"type"属性可以覆盖默认加载器
import html from "./index.html" with { type: "text" };
在打包过程中,文件内容会被内联到 bundle 中作为字符串:
ts
var contents = `你好,世界!`;
console.log(contents);
如果将.txt
文件作为入口点,它将被转换为一个.js
模块,并通过export default
导出文件内容。
txt
你好,世界!
js
export default "你好,世界!";
napi
加载器
适用于:.node
文件。
在运行时,原生插件可以直接导入:
ts
import addon from "./addon.node";
console.log(addon);
在打包器中,.node
文件使用file
加载器处理。
sqlite
加载器
使用方式:通过with { "type": "sqlite" }
导入属性指定。
在运行时和打包器中,SQLite 数据库可以直接导入。这会使用bun:sqlite
API 加载数据库。
ts
import db from "./my.db" with { type: "sqlite" };
此功能仅在`target`为`bun`时支持。
默认情况下,数据库是与 bundle 分离的(外部引用),这样您可以使用在其他地方加载的数据库,因此磁盘上的数据库文件不会被打包到最终输出中。
您可以使用"embed"
属性更改此行为:
ts
// 将数据库嵌入到bundle中
import db from "./my.db" with { type: "sqlite", embed: "true" };
当使用独立可执行文件时,数据库会被嵌入到单文件可执行文件中。
否则,要嵌入的数据库将被复制到outdir
中,并使用哈希文件名。
html
加载器
HTML 加载器处理 HTML 文件并打包引用的资源。它会:
- 打包并为引用的 JavaScript 文件生成哈希(
<script src="...">
) - 打包并为引用的 CSS 文件生成哈希(
<link rel="stylesheet" href="...">
) - 为引用的图片生成哈希(
<img src="...">
) - 保留外部 URL(默认情况下,任何以
http://
或https://
开头的 URL)
例如,给定以下 HTML 文件:
html
<!DOCTYPE html>
<html>
<body>
<img src="./image.jpg" alt="本地图片" />
<img src="https://example.com/image.jpg" alt="外部图片" />
<script type="module" src="./script.js"></script>
</body>
</html>
它将输出一个带有打包资源的新 HTML 文件:
html
<!DOCTYPE html>
<html>
<body>
<img src="./image-HASHED.jpg" alt="本地图片" />
<img src="https://example.com/image.jpg" alt="外部图片" />
<script type="module" src="./output-ALSO-HASHED.js"></script>
</body>
</html>
在内部,它使用lol-html
提取脚本和链接标签作为入口点,以及其他资源作为外部资源。
HTML 加载器支持处理的选择器列表包括:
audio[src]
- 音频元素iframe[src]
- 内联框架img[src]
- 图片源img[srcset]
- 响应式图片源link[rel='stylesheet'][href]
- 样式表链接link[rel='icon'][href]
- 网站图标script[src]
- 脚本源source[src]
- 媒体源video[src]
- 视频源- 以及更多...
sh
加载器
适用于:.sh
文件。
此加载器用于解析Bun Shell脚本。它仅在启动 Bun 本身时受支持,因此在打包器或运行时中不可用。
sh
$ bun run ./script.sh
file
加载器
适用于:所有未识别的文件类型。
文件加载器将导入解析为导入文件的路径/URL。它通常用于引用媒体或字体资源。
ts
import logo from "./logo.svg";
console.log(logo);
在运行时,Bun 检查logo.svg
文件是否存在,并将其转换为磁盘上logo.svg
位置的绝对路径。
bash
$ bun run logo.ts
/path/to/project/logo.svg
在打包器中,情况略有不同。文件会原样复制到outdir
中,导入会被解析为指向复制文件的相对路径。
ts
var logo = "./logo.svg";
console.log(logo);
如果为publicPath
指定了值,导入将使用该值作为前缀来构建绝对路径/URL。
公共路径 | 解析后的导入 |
---|---|
"" (默认) | /logo.svg |
"/assets" | /assets/logo.svg |
"https://cdn.example.com/" | https://cdn.example.com/logo.svg |
复制文件的位置和文件名由[`naming.asset`](https://bun.sh/docs/bundler#naming)的值确定。
文件加载器使用场景
下面是一个常见问题和解决方案示例,展示如何在实际项目中利用 Bun 的文件加载器:
问题:在 React 项目中如何正确导入各种资源?
在前端开发中,我们经常需要导入多种类型的文件,如配置文件、图片、样式表等。
解决方案:
创建一个典型的 React 项目结构,并正确导入各种资源:
my-app/
├── src/
│ ├── assets/
│ │ ├── logo.svg
│ │ └── background.png
│ ├── config/
│ │ ├── settings.json
│ │ └── app.toml
│ ├── components/
│ │ └── Header.tsx
│ └── App.tsx
└── package.json
在App.tsx
中导入不同类型的文件:
tsx
import React from 'react';
// 导入图片资源
import logo from './assets/logo.svg';
import background from './assets/background.png';
// 导入配置文件
import settings from './config/settings.json';
import appConfig from './config/app.toml' with { type: "toml" };
// 导入组件
import Header from './components/Header';
function App() {
return (
<div style={{ backgroundImage: `url(${background})` }}>
<Header />
<img src={logo} alt="Logo" width={100} />
<h1>{settings.appName}</h1>
<p>版本: {appConfig.version}</p>
<p>环境: {appConfig.environment}</p>
</div>
);
}
export default App;
分析过程
- 图片资源:使用
file
加载器处理,返回 URL 路径 - JSON 配置:使用
json
加载器解析,返回 JavaScript 对象 - TOML 配置:使用
toml
加载器解析,返回 JavaScript 对象 - React 组件:使用
tsx
加载器处理 TypeScript 和 JSX 语法
在开发过程中,Bun 会自动选择正确的加载器处理不同类型的文件,使得导入体验非常流畅。在构建时,Bun 会正确打包这些资源,并优化最终的输出。
解决 TypeScript 导入错误
使用 TypeScript 时,当导入非 JavaScript/TypeScript 文件时,可能会遇到类似这样的错误:
TypeScript错误
Cannot find module './logo.svg' or its corresponding type declarations.
解决方法是创建一个类型声明文件(*.d.ts
),在项目中的任何位置都可以(文件名不重要),内容如下:
ts
declare module "*.svg" {
const content: string;
export default content;
}
这告诉 TypeScript,任何来自.svg
的默认导入应该被视为字符串类型。
最佳实践与建议
明确指定加载器:当文件扩展名与其内容不匹配时,使用
with { loader: "xxx" }
来明确指定加载器类型为非标准资源添加 TypeScript 声明:为了获得更好的 TypeScript 支持,为常用的非代码资源(如图片、SVG、字体等)创建类型声明文件
利用 JSON 和 TOML 导入:将配置集中在 JSON 或 TOML 文件中,可以使代码更整洁、更易维护
了解资源处理方式:理解在运行时和打包时资源处理的区别,特别是对于媒体文件和外部资源
TIP
当处理大量资源时,考虑使用 Bun 的插件系统创建自定义加载器,以满足特定的项目需求。
总结
Bun 的内置文件加载器系统使处理各种文件类型变得简单高效。通过了解不同加载器的工作原理和最佳实践,您可以充分利用 Bun 的功能来构建高性能的应用程序。
最重要的是,这种无缝的文件处理方式允许开发者专注于应用逻辑,而不必担心文件类型兼容性和转换问题。