运行时配置

运行时配置和配置的区别是他跑在浏览器端,基于此,我们可以在这里写函数、tsx、import 浏览器端依赖等等,注意不要引入 node 依赖。

配置方式

约定 .dumi/app.(js|ts|jsx|tsx) 为运行时配置。

TypeScript 提示

如果你想在写配置时也有提示,可以通过 dumi 的 defineApp 方法定义配置。

import { defineApp } from 'dumi';
export default defineApp({
layout: () => {
return {
title: 'dumi',
};
},
});
// or
import { RuntimeConfig } from 'dumi';
export const layout: RuntimeConfig['layout'] = () => {
return {
title: 'dumi',
};
};

配置项

modifyCodeSandboxData

修改在 CodeSandbox 中打开 demo 的数据,比如修改依赖、增加文件等。

export function modifyCodeSandboxData(memo, props) {
// 根据需要修改 memo 并返回新值
return memo;
}

入参:

  • memo:基于 demo 元数据自动生成的 CodeSandbox 数据,该数据会在序列化以后发往 CodeSandbox,你可以根据需要加工该数据
  • props:当前 demo 所属预览器的 props,包含原始的 demo 元数据和预览配置,可作为加工 memo 的辅助信息

出参:必须为 CodeSandbox utils 支持的数据结构,可参考 CodeSandbox 相关源码

modifyStackBlitzData

修改在 StackBlitz 中打开 demo 的数据,比如修改依赖、增加文件等。

export function modifyStackBlitzData(memo, props) {
// 根据需要修改 memo 并返回新值
return memo;
}

入参:

  • memo:基于 demo 元数据自动生成的 StackBlitz 数据,该数据会由 StackBlitz SDK 发送给 StackBlitz 平台,你可以根据需要加工该数据
  • props:当前 demo 所属预览器的 props,包含原始的 demo 元数据和预览配置,可作为加工 memo 的辅助信息

出参:必须为 StackBlitz SDK 支持的数据结构,可参考 StackBlitz SDK 文档

onRouteChange

在初始加载和路由切换时做一些事情。

比如用于做埋点统计,

export function onRouteChange({
location,
clientRoutes,
routes,
action,
basename,
isFirst,
}) {
bacon(location.pathname);
}

比如用于设置标题,

import { matchRoutes } from 'dumi';
export function onRouteChange({ clientRoutes, location }) {
const route = matchRoutes(clientRoutes, location.pathname)?.pop()?.route;
if (route) {
document.title = route.title || '';
}
}

patchRoutes

export function patchRoutes({ routes, routeComponents }) {
console.log('patchRoutes', routes, routeComponents);
}
  • routes: 打平的路由列表。
  • routeComponents: 路由对应的组件映射。

注:如需动态更新路由,建议使用 patchClientRoutes() ,否则你可能需要同时修改 routesrouteComponents

patchClientRoutes

修改被 react-router 渲染前的树状路由表,接收内容同 useRoutes

比如在最前面添加一个 /foo 路由,

import Page from './extraRoutes/foo';
export function patchClientRoutes({ routes }) {
routes.unshift({
path: '/foo',
element: <Page />,
});
}

比如在最前面添加一个重定向路由:

import { Navigate } from 'dumi';
export const patchClientRoutes = ({ routes }) => {
routes.unshift({
path: '/',
element: <Navigate to="/home" replace />,
});
};

比如添加一个嵌套路由:

import Page from './extraRoutes/foo';
export const patchClientRoutes = ({ routes }) => {
routes.push({
path: '/group',
children: [{
path: '/group/page',
element: <Page />,
}],
});
};

比如和 render 配置配合使用,请求服务端根据响应动态更新路由,

let extraRoutes;
export function patchClientRoutes({ routes }) {
// 根据 extraRoutes 对 routes 做一些修改
patch(routes, extraRoutes);
}
export function render(oldRender) {
fetch('/api/routes')
.then((res) => res.json())
.then((res) => {
extraRoutes = res.routes;
oldRender();
});
}

注意:

  • 直接修改 routes,不需要返回

render

覆写 render。

比如用于渲染之前做权限校验,

export function render(oldRender) {
fetch('/api/auth').then(auth => {
if (auth.isLogin) { oldRender() }
else {
location.href = '/login';
oldRender()
}
});
}

rootContainer

修改交给 react-dom 渲染时的根组件。

比如用于在外面包一个 Provider,

export function rootContainer(container) {
return React.createElement(ThemeProvider, null, container);
}

args 包含:

  • routes,全量路由配置
  • plugin,运行时插件机制
  • history,history 实例

TABLE OF CONTENTS