转译:是什么、流程及代码转换工具

作者: IT Sectr 发布日期: 2026-05-19 阅读时间: 8 分钟

转译 — 将源代码从一种编程语言转换为另一种相同抽象级别的语言。与编译为机器码不同,转译在高级语言之间转换代码:TypeScript 转换为 JavaScript,Kotlin 转换为 Java,Dart 转换为 JavaScript。根据 Babel Documentation,Babel 是最流行的转译器,每周下载量超过 3500 万次,支持数百个插件。

要点

  • 转译 — 在相同抽象级别的语言之间转换代码(源码到源码编译)
  • Babel — 将现代 JavaScript (ES6+) 转换为兼容 ES5 以用于旧浏览器的转译器
  • TypeScript 通过 tsc 编译为 JavaScript — 删除类型并转换为 ES 的转译器
  • Kotlin/Native 和 Kotlin/JS — 将 Kotlin 转译为原生代码和 JavaScript 以进行跨平台开发
  • Dart 编译为 JavaScript (dart2js) 用于 Web,编译为原生代码 (dart2native) 用于移动平台

什么是转译?

转译(源码到源码编译)— 将程序从一种编程语言翻译成另一种编程语言,同时保持抽象级别的过程。转译器接收 A 语言的源代码,生成可在目标环境中执行的等效 B 语言代码。典型示例:TypeScript 到 JavaScript,SASS 到 CSS,Haxe 到多种目标语言。

转译与编译的不同之处在于,输出代码保持在高级别且可被人读取(尽管并非为此目的而设计)。编译器(GCC、LLVM、javac)将代码转换为机器码或字节码 — 不可读的格式。转译器生成可进一步编译或压缩的代码。

为什么需要转译。主要原因是兼容性。开发人员希望使用现代语言(带类型的 TypeScript、带 null safety 的 Kotlin),但目标平台只支持 JavaScript 或 Java。转译允许用现代语言编写代码,并部署目标环境能理解的代码。

流行的转译器

转译器源 → 目标应用
BabelES6+/TypeScript → ES5Web 开发、React、Vue
tsc (TypeScript Compiler)TypeScript → JavaScript任何 TypeScript 应用程序
kotlinc-jsKotlin → JavaScriptKotlin/JS、React Kotlin Wrappers
dart2jsDart → JavaScriptFlutter Web、AngularDart
SWCTypeScript/JS → ES5Next.js、基于 Rust 构建

转译 vs 编译:主要区别

抽象级别 — 主要区别。转译器在同一级别的语言之间转换代码(高级 → 高级)。编译器从高级别转换到低级别(机器码、字节码)。LLVM IR 是一种中间表示,但仍比源代码 C++ 或 Rust 级别低。

结果的可读性 — 第二个区别。转译的结果(来自 TypeScript 的 JavaScript)可读且可在浏览器中调试。编译的结果(来自 C++ 的机器码)不适合阅读 — 其分析需要反汇编器。Source maps 通过将转译后的代码与源代码连接来帮助调试。

CI/CD 上下文中的转译

CI/CD 管道中,转译在构建阶段执行。对于 TypeScript 项目,tsc 或 Babel 在 Docker 容器中运行,生成 JavaScript 和 source maps,然后压缩并部署到服务器或应用商店。配置转译结果的缓存很重要 — tsc --incremental 保存运行之间的依赖关系图,将构建时间减少 30–50%。

对于移动项目(React Native),通过 Metro Bundler 的转译在每次发布时在 CI 服务器上执行。为了加速,使用缓存目录(tmp/metro-cache)和通过 --workers 进行并行构建。GitHub Actions 和 GitLab CI 支持在运行之间缓存 node_modules 和 .cache 目录,这对于减少管道时间至关重要。

执行速度也有所不同。编译为机器码提供最大性能。转译保留了抽象级别的开销:来自 TypeScript 的 JavaScript 以与普通 JavaScript 相同的速度执行。优化(TypeScript --strict)在分析阶段起作用,而不是执行阶段。

流行的转译场景

场景 1:TypeScript → JavaScript — 最广泛的场景。开发人员使用带类型的 TypeScript 编写,编译器 tsc 或 Babel 删除类型注释并生成纯 JavaScript。所有 Angular 项目和大多数 React 项目(2026)都使用 TypeScript 转译。根据 State of JS 2025 的统计,79% 的受访开发人员在主要项目中使用 TypeScript。

场景 2:Kotlin → JavaScript — 用于 Kotlin/JS 的全栈开发。Kotlin 代码通过 Kotlin Compiler 使用 IR(中间表示)编译为 JavaScript。Kotlin/JS 支持 TypeScript 类型声明 (.d.ts) 以与外部 JS 库集成。JetBrains 在其产品中使用 Kotlin/JS 用于 Web 界面。

场景 3:SASS/SCSS → CSS — CSS 预处理器的转译。Dart Sass(推荐实现)将 .scss 转译为 .css,展开 mixin、变量、嵌套规则和函数。这不是编译(CSS 仍然是 CSS),而是带有语法扩展的转译。

比较:转译 vs 编译 vs 解释

参数转译编译解释
输入 → 输出高级 → 高级高级 → 机器码代码 → 即时执行
示例TypeScript → JavaScriptC++ → ARM/x86Python → CPython runtime
输出代码可读
性能如目标语言最大低于编译
需要运行时否(纯目标代码)

Babel:现代 JavaScript 的转译

Babel — 最广泛使用的 JavaScript 转译器,将 ES6+/ESNext 代码转换为 ES5 兼容的 JavaScript。Babel 通过插件和预设系统工作:每个插件负责一种转换(箭头函数、async/await、可选链)。@babel/preset-env 根据目标浏览器(browserslist)自动确定必要的插件。

Babel 的架构由三个阶段组成:解析 (parsing) → 转换 (transformation) → 生成 (generation)。解析器 (Babylon/@babel/parser) 将源代码转换为 AST(抽象语法树)。转换器(插件)修改 AST。生成器 (@babel/generator) 从修改后的 AST 创建输出代码。

示例:通过 Babel 转译

js
// 源代码 ES6+
const greet = (name = "World") => {
  return `Hello, ${name}!`;
};

class User {
  constructor(name) {
    this.name = name;
  }
}

const data = { user: { address: { city: "Moscow" } } };
const city = data?.user?.address?.city;
js
// 经过 Babel 处理后 (target: > 0.25%, not dead)
"use strict";

var greet = function (name) {
  if (name === void 0) { name = "World"; }
  return "Hello, " + name + "!";
};

var User = function (name) {
  this.name = name;
};

var data = { user: { address: { city: "Moscow" } } };
var city = data != null
  ? data.user != null
    ? data.user.address != null
      ? data.user.address.city
      : void 0
    : void 0
  : void 0;

Babel 转换了:箭头函数为 function expression,默认参数 (name = “World”) 为 void 0 检查,模板字符串为连接,类为构造函数,可选链 (?.) 为三元运算符链。const 被替换为 var 以兼容 ES5 环境。

TypeScript:带类型系统的转译

TypeScript — 强类型语言,转译为 JavaScript。编译器 tsc(TypeScript Compiler)执行两项任务:类型检查和转译。重要的是要理解:类型检查和转译是独立的阶段。可以在没有类型检查的情况下执行转译 (--noEmitOnError false) 或在没有代码生成的情况下进行检查 (--noEmit true)。

TypeScript 转译删除所有类型注释、接口、类型别名和泛型参数 — 在 JavaScript 中它们不存在。枚举转换为对象,装饰器转换为函数调用,async/await 转换为生成器(如果 target 低于 ES2017)。tsconfig.json 管理 target(JavaScript 版本)、module(模块系统)、strict(类型检查程度)和 outDir(输出文件夹)。

用于转译的 TypeScript 配置

json
{
  "compilerOptions": {
    "target": "es2015",
    "module": "esnext",
    "lib": ["es2015", "dom"],
    "strict": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "esModuleInterop": true,
    "sourceMap": true,
    "declaration": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

target: “es2015” 指示 tsc 生成具有 ES6 语法的 JavaScript(箭头函数、类、let/const)。module: “esnext” 保留 ES 模块 (import/export) 以供后续在 Webpack 中进行 Tree Shaking。strict: true 启用所有类型检查 (strictNullChecks、noImplicitAny、strictFunctionTypes)。declaration: true 为库的 TypeScript 使用者生成 .d.ts 文件。

移动开发中的转译

React Native 使用 Babel 和 Metro 将 JavaScript/TypeScript 转译为由 JavaScriptCore (iOS) 或 Hermes (Android) 执行的代码。Babel 插件添加 JSX 转换、Flow/TypeScript 注释和 React Native 特定的优化。Metro Bundler 还合并模块并为开发执行热模块替换。

Flutter 使用 Dart 转译。对于 Flutter Web,dart2js 将 Dart 转译为优化的 JavaScript。对于 Flutter Mobile,dart2native 将 Dart 编译为原生 ARM 代码。Flutter 还支持 Dart DevCompiler (dartdevc) 用于开发 — 它更快地将 Dart 转译为 JavaScript,但优化较少。

示例:用于 React Native 的 Babel 配置

js
// babel.config.js — React Native 转译
module.exports = {
  presets: [
    ["module:metro-react-native-babel-preset"],
  ],
  plugins: [
    ["module-resolver", {
      root: ["."],
      alias: {
        "@": "./src",
        "@components": "./src/components",
      },
    }],
    "react-native-reanimated/plugin",
  ],
  env: {
    production: {
      plugins: ["transform-remove-console"],
    },
  },
};

metro-react-native-babel-preset 包含 React Native 所需的所有插件:JSX、Flow/TypeScript、Metro 模块系统、async/await、class properties 和装饰器。module-resolver 插件为简短导入添加别名 (@/components/Button 替代 ../../components/Button)。在生产模式下,transform-remove-console 从代码中删除所有 console.log。

常见问题

用简单的话说,转译和编译有什么区别?

转译将代码从一种语言转换为另一种相同级别的语言(例如 TypeScript → JavaScript)。编译从高级别转换到低级别(C++ → 机器码)。转译的结果可读,编译的结果不可读。

React Native 需要转译吗?

React Native 默认需要转译 — Metro Bundler 使用 Babel 将 JSX、TypeScript 和现代 JavaScript 转换为与 JavaScriptCore 和 Hermes 兼容的代码。没有 Babel,React Native 无法执行组件的 JSX 语法。

可以在没有 tsc 的情况下使用 TypeScript 吗?

可以:带 @babel/preset-typescript 的 Babel 和 SWC 支持 TypeScript 转译。这比 tsc 更快,但 Babel 不执行类型检查 — 只删除类型注释。类型检查需要将 tsc --noEmit 作为单独命令或通过 fork-ts-checker-webpack-plugin 运行。

在转译上下文中,source maps 是什么?

Source maps — 将转译后的代码与源代码连接的文件。允许在浏览器中调试 TypeScript:断点设置在 .ts 文件中,堆栈跟踪显示 .ts 行而不是 .js 行。没有 source maps,调试转译后的代码几乎是不可能的。

转译如何影响性能?

转译本身不会影响应用程序的性能 — 输出代码以与目标语言本地编写的代码相同的速度执行。只有转译器生成非最优代码时才会产生开销(例如,Babel 可能为数组方法创建庞大的 polyfill)。

总结

  • 转译 — 在相同抽象级别的语言之间转换代码(源码到源码编译)
  • Babel — 主要的 JavaScript 转译器,带有插件系统和用于自动配置的 @babel/preset-env
  • TypeScript 通过 tsc 转译为 JavaScript,删除类型注释并转换现代语法
  • React Native 使用 Babel 和 Metro 将 JSX、TypeScript 和 ES6+ 转译为兼容代码
  • 转译 vs 编译:转译保持高级抽象,编译转换为机器码
  • Source maps 对于调试转译后的代码是必需的,并将生成的代码与源代码连接

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读