面试官:如何直接在浏览器环境编译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 协议层封装实现,让你无感使用

相关推荐
轻口味5 分钟前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami8 分钟前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
wakangda39 分钟前
React Native 集成原生Android功能
javascript·react native·react.js
吃杠碰小鸡42 分钟前
lodash常用函数
前端·javascript
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
泰伦闲鱼1 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
m0_748250031 小时前
Web 第一次作业 初探html 使用VSCode工具开发
前端·html
一个处女座的程序猿O(∩_∩)O1 小时前
vue3 如何使用 mounted
前端·javascript·vue.js
m0_748235951 小时前
web复习(三)
前端
User_undefined1 小时前
uniapp Native.js原生arr插件服务发送广播到uniapp页面中
android·javascript·uni-app