调研esm动态加载作为插件载入方式

林一二2023年06月14日 20:17

方案

ESM导入字符串形式的MJS模块插件

过程和问题

  • 在服务端可以正常加载模块并拿到导出的内容
  • 需要验证在浏览器端是否可以加载,及经过其他打包工具打包后的前端项目是否能够加载
    • fetch 远端的 mjd 需要服务端开启 cors,但是我常用的 serve 这个功能有毛病
      • 先手动复制到 storybook 的 asset 里解决
    • 但 storybook 加载静态资源的方式只有 import 这一种,实际找不到带有 /static 的 URL 路径
      • 其实是类似 /src/stories/assets/comments.svg 这样的路径,GET http://localhost:6006/src/stories/assets/comments.svg 即可
    • 点按钮会运行加载的逻辑,打了log但火狐开发者工具里怎么也看不到log
      • storybook在火狐里有问题,可能一直加载的是缓存的旧版。改为用Edge浏览器开发就好了
    • 的确能够加载
  • 但是openai的sdk打包后引用了crypto库,导致在前端导入后报错 TypeError: Failed to resolve module specifier "/@id/__vite-browser-external:crypto". Invalid relative url or base scheme isn't hierarchical. 因为里面的 import{randomFillSync as a}from"crypto";
    • 得试试不带node依赖的,或分为前后端程序,带后端依赖的程序只有在有nodejs后端Provider时才加载
      • 来自 npm 的依赖 import e from"ajv"; 也会导致 TypeError: Failed to resolve module specifier "/node_modules/.cache/.vite-storybook/deps/ajv.js?v=5dd5b90d".,因为 rollup 在打包插件时如果没有开 json(), commonjs(), nodeResolve({ preferBuiltins: true }),,就会默认作为 external dependency,使用 import/require 的方式引入,详见memeloop 的 rollup.config.ts
      • 但如果不 external,就会开始引入 crypto,可能因为编译目标是node,得改成Browser,或者插件都得自动打面向两种环境的两个包
      • 讨论了一下,我们先只支持服务端的插件,客户端的按目前测试情况未来是可以支持的,只是先不做
      • 不过通过 nodeResolve({ preferBuiltins: true, browser: true }), 是可以打出浏览器用的包。
      • 只要不像openai那样声明了自己只能在node环境用,就能打出Browser包

最终效果

mjsPluginUrl http://localhost:6006/src/stories/assets/memeloop-plugin-base.mjs LoadPlugins.stories.tsx:53:15
importedPlugin 
Object { BaseNode: class BaseNode, BaseNodeType: {…}, HookCheckError: class HookCheckError, PluginMemberType: {…}, ValidationError: class ValidationError, deserializeNodeDefinitionJSON: deserializeNodeDefinitionJSON(e, t), deserializeRuntimeNodeData: deserializeRuntimeNodeData(e, t), isStateMachineNode: isStateMachineNode(e), serializeNodeDefinitionJSON: serializeNodeDefinitionJSON(e), serializeRuntimeNodeData: serializeRuntimeNodeData(e)
 }
``

研究插件化架构 动态数据付费创意工坊线上线下分类项目 开发区块链游戏 基于状态机的插件化的AI流程工具Memeloop 开发游戏

Undefined widget 'supertag-form'