babel
Babel 是一个 JavaScript 编译器,提供了JavaScript的编译过程,能够将源代码转换为目标代码。
AST -> Transform -> Generate
核心功能
- 语法转换:将新版本的 JavaScript 语法转换为旧版本的语法
- Polyfill:通过引入额外的代码,使新功能在旧浏览器中可用
- JSX: 将JSX语法转换成普通的JavaScript语法
- 插件: 为Babel提供自定义功能
案例
1. 语法转换:将新版本的 JavaScript 语法转换为旧版本的语法
npm install --save-dev @babel/core @babel/cli @babel/preset-env
转换代码,只需要调用bebel的transform函数,将code和option传入即可
import Babel from '@babel/core';
import presetEnv from '@babel/preset-env';
import fs from 'node:fs';
const file = fs.readFileSync('./test.js', 'utf-8');
const result = Babel.transformSync(file, {
presets: [presetEnv],
});
fs.writeFileSync('./test-compiled.js', result.code);
转化过后:
"use strict";
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
//语法
var a = function a() {
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2;
return 1 + params;
};
var b = [1, 2, 3];
var c = [].concat(b, [4, 5]);
var Babel = /*#__PURE__*/_createClass(function Babel() {
_classCallCheck(this, Babel);
});
new Babel();
//API
var x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].filter(function (x) {
return x % 2 === 0;
});
var y = Object.assign({}, {
name: 1
});
我们可以发现,对于数组的新特性,没有进行编译,我们要支持新特性例如 Object.assign Array.prototype.find 等
安装:
npm i core-js -D
index.js
import Babel from '@babel/core';
import presetEnv from '@babel/preset-env';
import fs from 'node:fs';
const file = fs.readFileSync('./test.js', 'utf-8');
const result = Babel.transformSync(file, {
presets: [
//usage 会根据配置的浏览器兼容,以及你代码中用到的 API 来进行 polyfill,实现了按需添加
//
[presetEnv, { useBuiltIns: "usage", corejs: 3 }]
],
});
fs.writeFileSync('./test-compiled.js', result.code);
编译过后
"use strict";
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.symbol.iterator.js");
require("core-js/modules/es.symbol.to-primitive.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.date.to-primitive.js");
require("core-js/modules/es.number.constructor.js");
require("core-js/modules/es.object.define-property.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
require("core-js/modules/es.array.concat.js");
require("core-js/modules/es.array.filter.js");
require("core-js/modules/es.object.assign.js");
require("core-js/modules/es.object.to-string.js");
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
//语法
var a = function a() {
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2;
return 1 + params;
};
var b = [1, 2, 3];
var c = [].concat(b, [4, 5]);
var Babel = /*#__PURE__*/_createClass(function Babel() {
_classCallCheck(this, Babel);
});
new Babel();
//API
var x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].filter(function (x) {
return x % 2 === 0;
});
var y = Object.assign({}, {
name: 1
});
swc
SWC 既可用于编译,也可用于打包。对于编译,它使用现代 JavaScript 功能获取 JavaScript / TypeScript 文件并输出所有主流浏览器支持的有效代码。
简单点来说swc实现了和babel一样的功能,但是它比babel快。
为什么快
- 编译型
Rust 是一种编译型语言,在编译时将代码转化为机器码(底层的 CPU 指令)。这种机器码在执行时非常高效,几乎不需要额外的开销。
核心功能
- JavaScript/TypeScript 转换 可以将现代 JavaScript(ES6+)和 TypeScript 代码转换为兼容旧版 JavaScript 环境的代码。这包括语法转换(如箭头函数、解构赋值等)以及一些 polyfill 的处理
- 模块打包 SWC 提供了基础的打包功能,可以将多个模块捆绑成一个单独的文件
- SWC 支持代码压缩和优化功能,类似于 Terser。它可以对 JavaScript 代码进行压缩,去除不必要的空白、注释,并对代码进行优化以减小文件大小,提高加载速度
- SWC 原生支持 TypeScript,可以将 TypeScript 编译为 JavaScript
- SWC 支持 React 和 JSX 语法,可以将 JSX 转换为标准的 JavaScript 代码。它还支持一些现代的 React 特性
安装
npm i -D @swc/cli @swc/core
案例
1. 语法转换:将新版本的 JavaScript 语法转换为旧版本的语法
index.js
// 利用swc进行代码转换
import { transformFileSync } from "@swc/core";
import {writeFileSync} from "fs"
const result = transformFileSync("./test.js",{
jsc: {
parser: {
syntax: "ecmascript",
},
target: "es5"
}
})
writeFileSync("./test-compiled.js",result.code)
转换过后
//语法
function _array_like_to_array(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
return arr2;
}
function _array_without_holes(arr) {
if (Array.isArray(arr)) return _array_like_to_array(arr);
}
function _class_call_check(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _iterable_to_array(iter) {
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _non_iterable_spread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _to_consumable_array(arr) {
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
}
function _unsupported_iterable_to_array(o, minLen) {
if (!o) return;
if (typeof o === "string") return _array_like_to_array(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(n);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
}
var a = function() {
var params = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 2;
return 1 + params;
};
var b = [
1,
2,
3
];
var c = _to_consumable_array(b).concat([
4,
5
]);
var Babel = function Babel() {
"use strict";
_class_call_check(this, Babel);
};
new Babel();
//API
var x = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
].filter(function(x) {
return x % 2 === 0;
});
var y = Object.assign({}, {
name: 1
});