dumidumi
  • 指南
  • 配置项
  • 主题
  • 插件
⌘ K
介绍
如何工作
插件市场
开发
创建插件
插件 API
添加技术栈
最后更新时间:
帮助改进此文档
Open-source MIT Licensed | Copyright © 2019-present
Powered by self

添加技术栈

为 dumi 开发添加一个技术栈插件,需要实现以下功能,我们以添加 Vue 框架支持为例

实现非外部 Demo 代码的编译转换

该功能主要通过插件 API api.registerTechStack 实现,在 Vue 框架支持中,主要利用该 API 实现对 JSX/SFC 两种组件代码的转换,这里主要讲单文件组件(SFC)的转换:

对于一个.vue文件,可以采用官方的@vue/compiler-sfc进行编译,除了对于template及script的处理,还有对style的处理,最终我们需要将代码和样式统统整合为一段 JS 代码,并通过 dumi 提供的babel-plugin-iife插件,将模块代码包装成一个 IIFE 执行表达式交给 dumi。

生成运行时执行代码

不同框架在浏览器中运行时也各有不同,所以需要实现一下 API 供 dumi 在运行时调用

export interface ITechStackRuntimeApi {
techStackName: string;
// CodeSandbox 预览实现
openCodeSandbox?: (props: IPreviewerProps) => void;
// StackBlitz 预览实现
openStackBlitz?: (props: IPreviewerProps) => void;
// 组件挂载DOM节点实现
renderToCanvas?: (canvas: Element, component: any) => Promise<() => void>;
}

dumi 内部会通过useTechStackRuntimeApi去调用相关代码,但对于插件开发者则需要对这些方法进行实现:

以renderToCanvas为例,component其实就是 SFC 转换好的 JS 代码,我们不仅需要挂载样式,Vue 应用实例,还需要在最后提供一个应用销毁的方法

export async function renderToCanvas(canvas: Element, component: any) {
if (component.__css__) {
setTimeout(() => {
document
.querySelectorAll(`style[css-${component.__id__}]`)
.forEach((el) => el.remove());
document.head.insertAdjacentHTML(
'beforeend',
`<style css-${component.__id__}>${component.__css__}</style>`,
);
}, 1);
}
const app = createApp(component);
globalInject(app);
app.config.errorHandler = (e) => console.error(e);
app.mount(canvas);
return () => {
app.unmount();
};
}

在实现这些方法之后,则可以利用api.addRuntimePlugin, onGenerateFiles 将方法注入到 dumi 运行时中

// runtime.tsx
import { TechStackRuntimeContext } from 'dumi';
const vueTechStackRuntimeApi = {
techStackName: 'vue3',
openCodeSandbox,
openStackBlitz,
renderToCanvas,
};
export function rootContainer(container: React.ReactNode) {
return (
<TechStackRuntimeContext.Provider value={vueTechStackRuntimeApi}>
{container}
</TechStackRuntimeContext.Provider>
);
}

模块的解析

dumi 默认只能对js,jsx,ts,tsx文件进行依赖分析并生成相关 asset,对于.vue文件则束手无策。不过 dumi 提供resolveDemoModule选项来对文件进行处理,以.vue为例,可以这样配置

api.modifyConfig((memo) => {
memo.resolveDemoModule = {
'.vue': { loader: 'tsx', transform: 'html' },
};
return memo;
});

我们将.vue文件当做 html 处理,dumi 会抽取其所有 script 标签里的 js 代码,最后将其作为tsx进行依赖分析。

webpack 配置

最后还需要添加对外部 Demo 的编译及打包支持,这需要我们对 webpack 进行配置,由于 dumi 本身是 react 框架,所以不能粗暴地移除对 react 的支持,而是需要将 react 相关配置限定在.dumi中。