转译 — 将源代码从一种编程语言转换为另一种相同抽象级别的语言。与编译为机器码不同,转译在高级语言之间转换代码:TypeScript 转换为 JavaScript,Kotlin 转换为 Java,Dart 转换为 JavaScript。根据 Babel Documentation,Babel 是最流行的转译器,每周下载量超过 3500 万次,支持数百个插件。
要点
转译(源码到源码编译)— 将程序从一种编程语言翻译成另一种编程语言,同时保持抽象级别的过程。转译器接收 A 语言的源代码,生成可在目标环境中执行的等效 B 语言代码。典型示例:TypeScript 到 JavaScript,SASS 到 CSS,Haxe 到多种目标语言。
转译与编译的不同之处在于,输出代码保持在高级别且可被人读取(尽管并非为此目的而设计)。编译器(GCC、LLVM、javac)将代码转换为机器码或字节码 — 不可读的格式。转译器生成可进一步编译或压缩的代码。
为什么需要转译。主要原因是兼容性。开发人员希望使用现代语言(带类型的 TypeScript、带 null safety 的 Kotlin),但目标平台只支持 JavaScript 或 Java。转译允许用现代语言编写代码,并部署目标环境能理解的代码。
| 转译器 | 源 → 目标 | 应用 |
|---|---|---|
| Babel | ES6+/TypeScript → ES5 | Web 开发、React、Vue |
| tsc (TypeScript Compiler) | TypeScript → JavaScript | 任何 TypeScript 应用程序 |
| kotlinc-js | Kotlin → JavaScript | Kotlin/JS、React Kotlin Wrappers |
| dart2js | Dart → JavaScript | Flutter Web、AngularDart |
| SWC | TypeScript/JS → ES5 | Next.js、基于 Rust 构建 |
抽象级别 — 主要区别。转译器在同一级别的语言之间转换代码(高级 → 高级)。编译器从高级别转换到低级别(机器码、字节码)。LLVM IR 是一种中间表示,但仍比源代码 C++ 或 Rust 级别低。
结果的可读性 — 第二个区别。转译的结果(来自 TypeScript 的 JavaScript)可读且可在浏览器中调试。编译的结果(来自 C++ 的机器码)不适合阅读 — 其分析需要反汇编器。Source maps 通过将转译后的代码与源代码连接来帮助调试。
在 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),而是带有语法扩展的转译。
| 参数 | 转译 | 编译 | 解释 |
|---|---|---|---|
| 输入 → 输出 | 高级 → 高级 | 高级 → 机器码 | 代码 → 即时执行 |
| 示例 | TypeScript → JavaScript | C++ → ARM/x86 | Python → CPython runtime |
| 输出代码可读 | 是 | 否 | 无 |
| 性能 | 如目标语言 | 最大 | 低于编译 |
| 需要运行时 | 否(纯目标代码) | 否 | 是 |
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 创建输出代码。
// 源代码 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;// 经过 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 — 强类型语言,转译为 JavaScript。编译器 tsc(TypeScript Compiler)执行两项任务:类型检查和转译。重要的是要理解:类型检查和转译是独立的阶段。可以在没有类型检查的情况下执行转译 (--noEmitOnError false) 或在没有代码生成的情况下进行检查 (--noEmit true)。
TypeScript 转译删除所有类型注释、接口、类型别名和泛型参数 — 在 JavaScript 中它们不存在。枚举转换为对象,装饰器转换为函数调用,async/await 转换为生成器(如果 target 低于 ES2017)。tsconfig.json 管理 target(JavaScript 版本)、module(模块系统)、strict(类型检查程度)和 outDir(输出文件夹)。
{
"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,但优化较少。
// 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 默认需要转译 — Metro Bundler 使用 Babel 将 JSX、TypeScript 和现代 JavaScript 转换为与 JavaScriptCore 和 Hermes 兼容的代码。没有 Babel,React Native 无法执行组件的 JSX 语法。
可以:带 @babel/preset-typescript 的 Babel 和 SWC 支持 TypeScript 转译。这比 tsc 更快,但 Babel 不执行类型检查 — 只删除类型注释。类型检查需要将 tsc --noEmit 作为单独命令或通过 fork-ts-checker-webpack-plugin 运行。
Source maps — 将转译后的代码与源代码连接的文件。允许在浏览器中调试 TypeScript:断点设置在 .ts 文件中,堆栈跟踪显示 .ts 行而不是 .js 行。没有 source maps,调试转译后的代码几乎是不可能的。
转译本身不会影响应用程序的性能 — 输出代码以与目标语言本地编写的代码相同的速度执行。只有转译器生成非最优代码时才会产生开销(例如,Babel 可能为数组方法创建庞大的 polyfill)。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。