Gyron.js 编辑器 2.0

1,917 阅读4分钟

Gyron.js 编辑器的出现是为了社区在遇到问题时制作快速可复现的版本供其它人尝试和解决,并且可以作为一个解决问题的指标。还有一点就是编辑器还可以快速尝试新功能而不需要进行繁琐的搭建工作,几秒就可以快速开始。后续规划中还会增加协同功能,可以协助其它人解决问题。

Gyron.js 编辑器是一个功能强大且易于使用的在线代码编辑器。它使用 TypeScript 编写,被设计为可扩展性的。此外,它还提供了本地虚拟文件系统和加载本地资源的功能,使得代码编辑更加便捷和高效。

如何使用 Gyron.js 编辑器

要使用 Gyron.js 编辑器,您可以按照以下步骤进行:

  1. 打开您的浏览器并访问 gyron.cc/explorer
  2. 在编辑器的左侧面板中输入您的代码,在右侧面板中查看代码的运行结果。

默认会有一个 index.tsx 的文件作为入口文件,并且不可以删除。在文件中会导出一个变量 APP 作为 root 节点,然后其它组件可以作为其子组件使用。

自动保存的冷却周期为 5 秒,在输入完成之后等待 5 秒会自动重新运行,届时,您的修改将会应用在右侧预览区域。

在编辑器上部分有一个新增文件的按钮,点击后可以选择新建 tsx 文件或者 less 文件,新建完成后在其它模块就可以使用。

如果你想将编写好的代码分享给其他人的时候可以点击右上角的分享按钮,这个时候会将本地代码组装成一个地址拷贝到粘贴板,然后直接发送给想分享的人即可。如果拷贝失败,可以在窗口的 url 处自己手动拷贝。

所有功能都将在 iframe 中被运行起来,会隔绝外部环境。

智能提示和自动补全

Gyron.js 编辑器提供了智能提示和自动补全功能以帮助您更快速地编写代码。它可以自动识别变量名、函数、类等,帮助您快速输入代码并减少错误。

原理讲解

Gyron.js 编辑器是基于 esbuild 构建的 esm 文件,在其基础之上封装了"本地文件"的支持,所有本地文件的导入都将会被自定义插件接管并解析,然后您就可以在编辑器中新建文件然后导入使用了。

其中 tsx 和 less 都是有自定义解析器进行解析,其中 tsx 文件会被babel-plugin-jsx解析,然后返回一个能够被浏览器正确执行的代码。

esbuild 是支持浏览器端的,由于其 wasm 体积过于大影响首次体验所以 Gyron.js 把构建过程搬到了服务器端。

app.post("/api/build", async (req, res) => {
  const { main, sources } = req.body;

  try {
    const { plugin } = buildBrowserEsmWithEsbuild(main, {
      sources,
    });
    const content = await transformWithBabel(main.code, main.name, main, true);
    const bundle = await build({
      stdin: {
        contents: content.code,
        sourcefile: main.name,
      },
      bundle: true,
      write: false,
      format: "esm",
      plugins: [plugin],
    });

    if (bundle.warnings.length) {
      res.send({
        data: bundle.warnings.map((item) => item.text).join("\n"),
        code: 1,
      });
    } else {
      res.send({
        data: {
          text: bundle.outputFiles[0].text,
          metafile: bundle.metafile,
        },
        code: 0,
      });
    }
  } catch (e) {
    console.error(e.message);
    res.send({
      data: e.message,
      code: 1,
    });
  }
});

上述就是接口的实现,其中最关键就是 buildBrowserEsmWithEsbuild 函数做的事情,会将前端传递过来的资源数据传递给函数生成一个 esbuild 插件,然后再调用 esbuild.build 方法进行构建。

然后 buildBrowserEsmWithEsbuild 做了什么工作呢?

export function buildBrowserEsmWithEsbuild(main: ConfigSource, config: Config) {
  const buildModuleRuntime: Plugin = {
    name: "buildModuleRuntime",
    setup(build) {
      build.onResolve({ filter: /\.\// }, (args) => {
        return {
          path: args.path,
          namespace: "localModule",
        };
      });
      build.onLoad(
        { filter: /\.\//, namespace: "localModule" },
        async (args) => {
          const source = findSourceCode(config.sources, args.path);

          if (source) {
            const filename = getFileName(args, source.loader);
            const result = await transformWithBabel(
              source.code,
              filename,
              main,
              true
            );
            return {
              contents: result.code,
            };
          }
          return {
            contents: "",
            loader: "text",
            warnings: [
              {
                pluginName: "buildModuleRuntime",
                text: `Module "${args.path}" is not defined in the local editor`,
              },
            ],
          };
        }
      );
    },
  };

  return {
    plugin: buildModuleRuntime,
    main: main,
  };
}

如果你了解 esbuild 的插件的话其中就很容易理解了,只需要关注其返回值是什么就可以了。

好了,目前这版编辑器的功能大致介绍完成,如果你感兴趣可以来 github 或者发邮件给我,如果有好的想法或者坑位也可以联系我。后面的文章将介绍 Gyron.js 3.0 协同编辑,其中用到的技术比较复杂,希望屏幕前的你能够喜欢。

文档引用