Ionify vs Vite:你的构建工具内部到底发生了什么

发布: (2026年4月8日 GMT+8 03:24)
6 分钟阅读
原文: Dev.to

Source: Dev.to

大多数开发者使用 Vite 并信任它。它速度快、设计良好,而且不干扰开发。
但 Vite 的架构——以及所有其他主流构建工具——都内置了一个根本性的假设,而 Ionify 对此提出了挑战。

假设: 每次构建都从零开始。

无状态构建问题

当你运行 vite build 时,大致会发生以下过程:

  1. Vite 启动 esbuild/Rollup(现在常常由 Rolldown + Oxc 提供动力)。

  2. 每个文件独立地经过其插件链

    main.tsx   → TS plugin → JSX plugin → output
    utils.ts   → TS plugin → output
    index.css  → CSS plugin → output
  3. 所有内容被打包。

下次再运行时,同样的过程会再次执行。系统并不会记住已经执行过的内容;TS 插件并不知道 JSX 插件已经处理过某个文件,打包器也不知道哪些文件发生了变化。该流水线 天生无状态。这不是 bug——这是为了简化和可预测性而做出的刻意选择,但在大规模项目中会带来真实的性能成本。

Ionify 对此的不同思考方式

与其反复转换文件,Ionify 直接处理它们

内容可寻址存储 (CAS)

每个模块都会获得一个内容哈希:

SHA-256(source content + config version) → CAS key

结果存放在 CAS 目录中:

.ionify/
  cas/
    /
      /
        transformed.js
        transformed.js.map

相同的内容 + 相同的配置 → 相同的哈希 → 完全跳过转换。未更改的模块根本不进行转换。

持久化图

Vite 在每次启动开发服务器时都会重新构建模块图。Ionify 持久化 该图:

.ionify/
  graph.db   ← sled‑backed embedded KV store (Rust)

当文件发生变化时,Ionify 会在逆向依赖索引上执行 BFS,精确找出受影响的模块。在一个拥有 500 个模块的项目中,修改一个工具文件可能只会使 12 个模块失效,而不是全部 500 个。

版本隔离:配置更改使所有缓存失效

持久缓存必须处理配置更改。Ionify 通过从配置计算出的确定性 版本哈希 来解决此问题,确保任何配置修改都会使相关缓存失效。

四层 CAS 架构

随着系统的演进,Ionify 引入了四个不同的缓存层,每个层解决不同的问题。

第 1 层 — 模块转换缓存

按内容哈希键存储已转换的模块输出。

第 2 层 — 依赖制品存储

缓存已编译的第三方依赖。

第 3 层 — 压缩 CAS

对构建产出进行预压缩(Brotli‑11、gzip‑9),一次压缩后永久提供。

第 4 层 — 块输出 CAS

缓存由打包器生成的最终块文件。

实际配置:从 Vite 迁移

以下是一个来自已从 Vite 切换的生产项目的 ionify.config.ts 示例:

import { defineConfig } from 'ionify'

export default defineConfig({
  entry: '/src/main.tsx',
  server: {
    https: true,
  },
  resolve: {
    // Same aliases as tsconfig — Ionify reads these natively
    // Note: if your tsconfig.json is JSONC (comments/trailing commas),
    // auto‑alias parsing currently fails — specify manually here
    alias: {
      '@@': '/',
      '@@/Core': '/Core/src',
      '@': '/src',
    },
    extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'],
    conditions: ['import', 'module', 'browser', 'default'],
    mainFields: ['module', 'jsnext:main', 'jsnext', 'main'],
  },
  optimizeDeps: {
    include: ['moment-hijri'],   // pre‑warm known‑problem deps
    sharedChunks: 'auto',
    packSlimming: 'auto',
    vendorPacks: 'auto',
  },
  build: {
    target: 'esnext',
  },
})

该项目包含超过 10 k 个模块。迁移到 Ionify 后:

  • 冷构建: 3.2 秒(比 Vite 的 3.7 秒更快)
  • 热构建: 2.2 秒(比 Vite 的 3.7 秒更快)

根本区别

构建工具核心假设
Vite每次构建都是独立的。
Ionify上一次构建的大部分工作仍然有效。

这两种假设都合理。Vite 的方式导致系统更简单、更可预测。Ionify 的方法让第二次、第十次以及 CI 构建都能受益于之前的工作,使得图中 “transform” 部分大多为空——这不是因为复杂性被隐藏,而是因为大多数转换根本没有执行。

Ionify 目前已在生产环境中使用。

0 浏览
Back to Blog

相关文章

阅读更多 »