Convert to it构建体系全解:Vite+Bun+TypeScript工程化实践
【免费下载链接】convertTruly universal online file converter项目地址: https://gitcode.com/GitHub_Trending/convert7/convert
Convert to it! 是一款号称"真正通用"的浏览器端在线文件转换器,它的构建体系基于Vite + Bun + TypeScript三件套,实现了 Web 站点、Docker 容器与 Electron 桌面端的多端工程化实践。本文为你完整拆解这套构建体系的设计思路与落地细节,帮助前端新手理解一个大型 Web 工程是如何被"工程化"组织起来的。
📦 项目总览:一个能"万物互转"的文件转换器
传统在线转换工具只支持同类格式互转(图片转图片、视频转视频),且必须把文件上传到服务器。Convert to it! 的做法完全不同:所有转换都在浏览器本地通过 WebAssembly 和 JS 库完成,文件不出设备,且支持跨媒介转换(比如把视频转成 PDF)。
这种"全能"体验背后,是一套清晰的工程结构:
| 路径 | 作用 |
|---|---|
| src/main.ts | Web 端入口,负责 UI 与转换调度 |
| src/FormatHandler.ts | 定义统一的格式处理器接口 |
| src/handlers/index.ts | 注册全部 70+ 个转换工具(Handler) |
| src/TraversionGraph.ts | 转换路径图,支持多步"接力"转换 |
| vite.config.js | Vite 构建配置(WASM 资源拷贝、路径别名) |
| tsconfig.json | TypeScript 编译配置 |
| buildCache.js | 基于 Puppeteer 的格式缓存构建脚本 |
| docker/ | Docker 多阶段构建与 Nginx 部署配置 |
| test/ | 图遍历与转换冒烟测试 |
💡 每个转换工具都被抽象成统一的
FormatHandler接口(见 README 中的贡献指南),新增一种格式支持,本质上就是往src/handlers/里加一个文件。
⚡ 构建工具链:为什么是 Vite + Bun?
打开 package.json 可以看到,项目所有脚本都以Bun作为运行时,而Vite负责打包:
bun run dev # 启动 Vite 开发服务器(热更新) bun run build # tsc 类型检查 + Vite 生产构建 bun run cache:build # 构建格式缓存(详见下文) bun run docker # 一键 Docker 构建并启动 bun run desktop:start # 构建并运行 Electron 桌面端这个组合有三个工程上的好处:
- Vite 的秒级启动:项目依赖了 FFmpeg、ImageMagick、Pandoc 等大量 WASM 重型库,冷启动依赖扫描极耗时,Vite 的 ESM 原生开发和
optimizeDeps机制让开发体验依然流畅。 - Bun 的统一运行时:不仅跑脚本,还用
Bun.serve内置 HTTP 服务器承载缓存构建流程(见 buildCache.js),省去额外安装 Node 服务框架。 - 类型门禁:
build脚本先执行tsc再vite build,保证任何类型错误都无法进入产物。
🧬 TypeScript 工程化:strict 模式下的取舍
tsconfig.json 是一份相当"教科书式"的现代 TS 配置:
strict: true+noFallthroughCasesInSwitch:开启严格模式,杜绝常见低级错误;moduleResolution: "bundler"+noEmit: true:典型的"Bundler 模式"——TS 只负责类型检查,真正的编译交给 Vite;allowJs: true:允许直接引入 JS 库(如 WASM 胶水代码),同时用types补齐类型定义;exclude清单:将 src/handlers/qoi-fu、src/handlers/espeakng.js 等"vendored"第三方源码排除在编译之外——这些目录是作为 Git 子模块引入的外部代码,不属于项目自身的质量约束范围;paths别名:通过自定义路径把qoi-fu、qoa-fu指向预转译的 JS 文件,巧妙绕过第三方 TS 源码与项目编译选项不兼容的问题。
这种"对外部代码做隔离,对内部代码零妥协"的边界划分,是大型项目 TS 工程化的常见手法。
🧩 Vite 配置精髓:WASM 资源的静态拷贝
对于以 WASM 为核心的项目,vite.config.js 里最重要的不是打包,而是资源调度:
vite-plugin-static-copy批量拷贝 WASM:FFmpeg 核心、ImageMagick、Pandoc、typst 渲染器、libopenmpt 音频库……近 20 个.wasm文件及对应 JS 胶水,全部被拷贝到产物的wasm/与js/目录,运行时按需懒加载;optimizeDeps.exclude:把@ffmpeg/ffmpeg、sqlite-wasm等 WASM 库排除出预构建,避免 Rollup 预处理破坏其加载逻辑;base: "/convert/":部署在子路径下(Nginx 会将/302 重定向到/convert/),前端资源路径与此严格对齐。
页面入口 index.html 保持极简——只有<script type="module" src="src/main.ts">一行,真正的模块化启动逻辑全部在 src/main.ts 中完成。
🤖 亮点工程:用 Puppeteer 自动生成"格式缓存"
项目最巧妙的工程实践在 buildCache.js:
页面首次加载时,需要枚举所有 Handler 的支持格式来生成"可从 → 可转至"格式列表,这个过程很慢(控制台会打印
Built initial format list.)。
为让用户不再等待,构建脚本做了一次"自举":
- 用
Bun.serve起一个静态服务器,托管dist/产物; - 用 Puppeteer 启动无头 Chromium(Docker 构建时复用系统 Chromium,通过
PUPPETEER_SKIP_DOWNLOAD避免重复下载); - 加载页面并监听控制台日志,等到
Built initial format list.出现后,调用页面上的window.printSupportedFormatCache()取出缓存 JSON; - 写入
dist/cache.json(--minify模式还会做压缩),运行时的加载屏就此消失。
用构建时的浏览器代替运行时的浏览器计算,这是典型的"离线预计算"优化思路,非常值得学习。
🐳 Docker 部署:多阶段构建 + Nginx 瘦身
docker/Dockerfile 是标准的多阶段构建模板:
- 构建阶段:基于
oven/bun:1镜像,安装 Chromium(供 Puppeteer 使用),bun install --frozen-lockfile锁定依赖,再执行bun run build与bun run cache:build; - 运行阶段:切换到仅几十 MB 的
nginx:stable-alpine,只把dist/拷贝进去,彻底剥离构建工具链。
配套的 docker/nginx/default.conf 做了两件事:把根路径 302 到/convert/子路径,并为 SPA 提供try_files回退。
本地自测时,可用 docker/docker-compose.override.yml 覆盖为本地构建镜像:
docker compose -f docker/docker-compose.yml -f docker/docker-compose.override.yml up --build -d服务将在http://localhost:8080/convert/启动(端口映射见 docker/docker-compose.yml)。
🖥️ Electron 桌面端:一套代码,三端复用
得益于纯 Web 技术栈,桌面端几乎是"白送"的:
- src/electron.cjs 注册了自定义
app://特权协议,把 URL 请求映射回本地dist/文件,实现了类 HTTP 的本地资源加载(含路径穿越防护); bun run desktop:build通过环境变量IS_DESKTOP=true触发 Vite 的差异构建;- package.json 中的
build字段由 electron-builder 接管,一键产出 Windows NSIS 安装包、macOS DMG 与 Linux AppImage。
Web 站、容器、桌面 App 共用同一份dist/产物——这正是 Vite + TS 工程化带来的"一次构建,多端分发"红利。
✅ 测试体系:两级测试策略
test/ 目录采用两级结构(见 README 的 Testing 章节):
- 项目级冒烟测试:如 test/TraversionGraph.test.ts 验证转换图遍历算法,test/commonFormats.test.ts 校验格式定义;
- Handler 级单元测试:放在 test/handlers/,配合 test/MockedHandler.ts 这个"假处理器",可以脱离真实 WASM 依赖,单独测试解析、序列化等纯逻辑。
🚀 快速上手:本地开发环境搭建
# 1. 克隆仓库(必须带子模块,否则缺少部分依赖) git clone --recursive https://gitcode.com/GitHub_Trending/convert7/convert # 2. 安装 Bun 后安装依赖 bun install # 3. 启动开发服务器 bunx vite⚠️ 若修改后页面"没反应",很可能是格式缓存在作怪——可禁用
cache.json验证(参考 README 的 Local development 章节)。
📝 总结
Convert to it! 的构建体系给出了一个大型前端工程的优秀范本:
- Vite解决"依赖极重"项目的打包与开发效率问题;
- Bun统一运行时,让脚本、服务器、打包一气呵成;
- TypeScript strict + bundler 模式在严格与实用之间取得平衡;
- Puppeteer 自举缓存展示了"构建时做重活"的巧妙思路;
- 多阶段 Docker + 自定义协议 Electron让同一份产物通吃三端。
理解这套体系,你对"Web 工程化"四个字应该会有全新的认识 🎯
【免费下载链接】convertTruly universal online file converter项目地址: https://gitcode.com/GitHub_Trending/convert7/convert
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考