面试官:如何直接在浏览器环境编译ES6+/TS代码?

背景

我们都知道 Babel 本身是一个 JavaScript 编译器,主要用于将现代 JavaScript(比如 ECMAScript 2015+TypeScriptJSX等)转换为向后兼容的 JavaScript,方便在较旧的浏览器环境中下运行。而且Babel 的编译过程是在构建过程(Webpack,Vite,Gulp等构建工具)进行,不会在浏览器中实时编译

大家好,我是芝士,欢迎点此扫码加我微信 Hunyi32 交流,最近创建了一个低代码/前端工程化交流群,欢迎加我微信 Hunyi32 进群一起交流学习,也可关注我的公众号[ 前端界 ] 持续更新优质技术文章

浏览器默认不支持 Babel 的原因主要是性能考虑和开发流程。Babel 的设计初衷应该就是作为一个编译工具,在构建阶段使用,而不是在浏览器中实时执行。

但是我们有时候想在浏览器环境中实现 JavaScript/TS的编译过程,比如在线编辑器中 CodePen ES10等 代码的执行需要先编译后执行等,这时候浏览器实现编译是一个必不可少的需求。

接下来我们文章的主角 @babel/standalone 就出现了。

@babel/standalone 的出现

这个模块的英文名字也挺有趣的 standalone(独立的),@babel/standaloneBabel 的一个独立版本,最早在 Babel 6 版本发布之后推出的。它的目的就是为了在浏览器环境中直接使用 Babel,将现代 JavaScript 代码(例如 ES6、TypeScript、JSX 等)编译为浏览器可执行的 JavaScript

@babel/stonelone 使用

如果是在 React 项目中,可以直接导入 @babel/stonealone 模块

tsx 复制代码
import { transform, registerPreset, registerPlugin } from '@babel/standalone/babel'; 

transform, registerPreset, registerPlugin 我认为是 @babel/standalone中最常用的函数,下文中会一一讲解。

实现代码编译

使用 transform 函数实现代码编译转换

js 复制代码
const code = ` const add = (a, b) => a + b; console.log(add(2, 3)); `;
const result = transform(code,{
    sourceType: 'script',
    filename: 'result.ts', 
    presets: [],
    plugins: [],
})

babel/standalone 常用函数

transform

transform 第二个参数中常用配置

  1. sourceType:指定输入代码的类型,它可以是 'script'(表示普通的 JavaScript 脚本)、'module'(表示 ES 模块)。
  2. filename:输入代码的文件名,这在某些情况下可能会影响 Babel 的处理行为,例如对于某些依赖于文件路径的插件,而且建议增加filename属性,在编译报错时候更清晰用于展示文件名称和调试问题。
  3. presets:一个数组,用于指定要应用的 Babel 预设。 4.plugins:一个数组,用于指定要应用的 Babel 插件。
配置预设

registerPreset 函数用于注册预设

registerPreset 函数允许你注册任意的 Babel 预设,这样你就可以在浏览器环境中使用这些预设来转换代码。例如,如果你想使用 @babel/preset-env@babel/preset-typescript,你需要先通过 registerPreset 函数注册它们,然后在调用 transform 方法引用这些预设。

以注册 @babel/preset-env预设并使用为例子

js 复制代码
import { transform, registerPreset, registerPlugin } from '@babel/standalone/babel'; 
import presetEnv from '@babel/preset-env';

// 注册@babel/preset-env 预设
registerPreset('my-preset', {
    presets: [
      [
        presetEnv,
        {
          targets: {
             chrome: '58',
             ie: '11',
          },
         },
       ],
     ],
}); 
// 在transform中使用注册的自定义预设名称 env-preset
const code = ` const add = (a, b) => a + b; console.log(add(2, 3)); `;
const result = transform(code,{
    sourceType: 'script',
    filename: 'result.ts', 
    presets: ['my-preset'],
})
配置插件

registerPlugin 函数也可以用于注册任意的 Babel 插件。使用 @babel/standalone你可以在浏览器中加载并注册任意的 Babel 插件,包括自己自定义的 Babel 插件

js 复制代码
import { transform, registerPreset, registerPlugin } from '@babel/standalone/babel'; 
import presetEnv from '@babel/preset-env';

// 注册自定义插件该改变Identifier类型节点名称
registerPlugin('my-custom-plugin', 
    { visitor: { 
        Identifier(path) { 
            if (path.node.name === 'oldName') {
                path.node.name = 'newName'; 
            } 
        }, 
     }, 
});
// 注册@babel/preset-env 预设
registerPreset('my-preset', {
    presets: [
      [
        presetEnv,
        {
          targets: {
             chrome: '58',
             ie: '11',
          },
         },
       ],
     ],
}); 
// 在transform中使用注册的自定义预设名称 my-preset
// 在transform中使用注册的自定义插件 my-custom-plugin
const code = ` const add = (a, b) => a + b; console.log(add(2, 3)); `;
const result = transform(code,{
    sourceType: 'script',
    filename: 'result.ts', 
    presets: ['my-preset'],
    plugins: ['my-custom-plugin'],
})

常用的预设有哪些

  1. @babel/preset-env 自动将现代 JavaScript(ES6+)代码转换为兼容目标环境的旧版本 JavaScript,以支持较旧的浏览器或环境。 (最常用!!!!)
  2. @babel/preset-react:将 React JSX 语法转换为 JavaScript,使浏览器能够正确解析和执行 React 组件。
  3. babel/preset-typescript : 将 TypeScript 代码转换为纯 JavaScript,并移除类型注释,以便在浏览器中运行。

这里我其实也有一个疑问,除了常见的预设可以在官网看到 否支持在浏览器环境中运行?但是有预设的不会写且没有正规官网,这种只能靠验证 transform 编译时看是否报错吗?不过目前除了几个常用的其他也未用到过,小伙伴们有更好的办法可以和我说下。

@babel/stonealone的应用场景

在线代码编辑器

许多在线代码编辑器(如CodePen)允许用户编写和运行 JavaScript。这些编辑器通常是支持现代 JavaScript 语法特性的,为了所有浏览器可以兼容执行这些代码,编辑器需要将现代 JavaScript语法转换为旧版本的JavaScript,这时候可能会用到 @babel/standalone

比如 编辑器中书写箭头函数会被转换

js 复制代码
// ES6代码
const greet = (name) => `Hello, ${name}!`;

// Babel会将其转换为ES5
var greet = function(name) {
  return "Hello, " + name + "!";
};

一些在线教程或学习网站

很多教学和学习网站(比如一些官方学习网站,在线看执行结果),可能会需要测试和演示一些现代 JavaScript 语法。这时候也可以用到 @babel/standalone ,不需设置复杂的开发环境,就能快速样式 ES6 特性或者 TypeScript语法

比如线课程和编程教程网站使用 @babel/standalone 来展示现代 JavaScript 语法,如箭头函数、解构赋值、模块导入等,并实时显示转换后的代码或执行结果。

js 复制代码
// ES6+代码
const [a, b] = [1, 2];
console.log(`a: ${a}, b: ${b}`);

// Babel将其转换为ES5
var _ref = [1, 2],
    a = _ref[0],
    b = _ref[1];
console.log('a: ' + a + ', b: ' + b);

大家好,我是芝士,最近创建了一个低代码/前端工程化交流群,欢迎点此扫码加我微信 Hunyi32 交流,也可关注我的公众号[ 前端界 ] 持续更新优质技术文章

总结

其实这也是上一篇文章整个项目中的一个知识点,预告下篇文章 WebWorker 协议层封装实现,让你无感使用

相关推荐
辻戋1 小时前
从零实现React Scheduler调度器
前端·react.js·前端框架
徐同保1 小时前
使用yarn@4.6.0装包,项目是react+vite搭建的,项目无法启动,报错:
前端·react.js·前端框架
Qrun2 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp2 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.3 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl5 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫6 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友6 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理8 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻8 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js