Vue Playground在线交互式解释器支持less

参考 vue 官方 Vue Playground

q1.png

Vue Playground,它提供一个在线的可交互编辑环境,实现在线上直接调试文档提供的案例代码, 而且十分的轻量。

1、什么是REPL(交互式解释器)

REPL(Read Eval Print Loop:交互式解释器) 表示一个我们可以在其中输入命令或者代码,并且可以接收到解释器响应的一个环境。主要有四大特征组成。

  • 读取 Read - 读取用户输入,解析输入的数据结构并存储在内存中。
  • 执行 Eval - 执行输入的数据结构
  • 打印 Print - 输出结果
  • 循环 Loop - 循环操作以上步骤直到用户退出。

也就是说我们现在所用的所有代码编辑器其实都是一个REPL(交互式解释器)

2、什么是在线REPL(交互解释器)

我们日常使用的代码编辑器大多是通过软件包下载到本地安装的,因为在本地系统环境下可以得到更好更流畅的交互和编译体验。但是在某些场景下,网页版的交互解释器更具有优势,比如

  • 我有一段代码,我想分享给别人看看,通过网页URL的形式明显比传输代码包的形式更方便
  • 我写了一个组件,需要有个预览地址或者内嵌一个iframe预览链接放在我的文档里面
  • 我想在最简环境下复现一个bug,但是我又觉得重新开一个项目太麻烦,我希望有一个网页,打开就能直接写代码,最好我常用的依赖都内置在上面
  • 可以把在线编辑的代码下载下来在本地运行

很巧,上面这些场景Vue的Playground都比较好的解决了

3、存在的问题

虽然 Vue 的 Playground 具备了在线交互解释器的所有特征,但是他只预置了Vue的运行环境,假设我想预置更多的模块,比如我想让他天然支持less,支持scss,应该怎么做呢?

4、如何实现

首先打开Vue Playground的源码可以发现,整个交互解释器的核心在@vue/repl这个依赖中,Vue Playground也只是对@vue/repl进行了集成。

@vue/repl 源码

4.1 下载源码

直接 git clone https://github.com/vuejs/repl.git

4.2 安装库

安装库 pnpm i

安装less pnpm i less -D

安装less type pnpm i --save-dev @types/less

4.3 修改源码

(1) 导入 less

./src/transform.ts

import { Store, File } from './store'
import {
  SFCDescriptor,
  BindingMetadata,
  shouldTransformRef,
  transformRef,
  CompilerOptions
} from 'vue/compiler-sfc'
import { transform } from 'sucrase'
// 新增 导入 less
import less from 'less'

...

(2)在 compileFile 方法里面加入.less判断

export async function compileFile(
  store: Store,
  { filename, code, compiled }: File
) {
  if (!code.trim()) {
    store.state.errors = []
    return
  }

  if (filename.endsWith('.css')) {
    compiled.css = code
    store.state.errors = []
    return
  }

  // 加入 less文件判断
  if (filename.endsWith('.less')) {
    const outStyle = await less.render(code) // 使用less.render将 less code 转换成css
    compiled.css = outStyle.css
    store.state.errors = []
    return
  }

  ...
}

(3)移除判断 lang


if (
    descriptor.styles.some((s) => s.lang) ||
    (descriptor.template && descriptor.template.lang)
  ) {
    store.state.errors = [
      `lang="x" pre-processors for