使用dumi构建开发文档
文档站点生成工具有很多,比如 docsify,VuePress,gitbook,Vite,dumi,Storybook,Docz,Docusaurus,Halo 等,甚至我目前写博客用的 Hexo,都能作为文档站点生成工具。
今天我来试一下 dumi 好不好用。
一、快速上手
注:本文为阉割版教程,仅展示单纯的
文档静态站点
的搭建和使用方法,关于组件开发项目
请移步官网自行浏览
1. 环境准备
首先得有 node,并执行命令确保 node 版本是 10.13 或以上。
1 | node -v |
2. 脚手架初始化
为了方便使用,dumi 提供了两种不同的脚手架,两者的区别可以查看 Config - mode。我们需要先找个地方建个空目录,然后再使用脚手架:
1 | mkdir myapp && cd myapp |
(1) 静态站点脚手架
静态站点脚手架即一个多语言的站点模式脚手架,仅包含文档。
1 | npx @umijs/create-dumi-app |
(2) 组件开发脚手架
组件库开发脚手架除了包含 dumi 和基础的文档外,还包含一个简单的组件、umi-test 和 father-build,可轻松实现开发组件、编写文档、编写测试用例、打包组件的全流程。
本文仅演示
静态站点脚手架
及相关操作,关于组件开发脚手架
请前往官方文档自行浏览
3. 仓库模板初始化
执行以下命令安装所需要的依赖:
1 | npm install |
安装完成后文件夹会多出 node_modules
和 package-lock.json
文件,package-lock.json
是在执行 npm install
命令的时候生成的一个文件,文件中会记录项目的名称、版本号以及相关的依赖信息等。
如果是组件开发脚手架,可以使用 dumi-template
仓库进行初始化,访问 https://github.com/umijs/dumi-template 了解更多。它是为组件开发场景而生的文档模板,点击 Github 仓库 Use this template
(使用这个模板) 即可创建一个模板仓库。
如果是简简单单的静态站点脚手架,用上面执行npx @umijs/create-dumi-app
后默认生成的文件夹结构就可以。
4. 开始开发
执行npx dumi dev
,在浏览器其中打开 http://localhost:8080
就可以进行预览,并可以开始编写文档了。
(1) 编写文档
查看我们的项目目录,可以发现 docs
文件,这里就是我们编写文档的地方。
项目初始化时,默认只有 index.md
,也就是上面我们访问 ·http://localhost:8080· 页面中所称呈现的内容。
接着我们在 docs
目录下新增/修改 Markdown
文档,它就会帮我们自动渲染到前端页面中。
5. 构建与部署
执行 npm run build
(静态站点脚手架), 或 npx dumi build
即可对我们的文档站点做构建,构建产物默认会输出到 dist
目录下,我们可以将 dist
目录部署在 now.sh、GitHub Pages 等静态站点托管平台或者某台服务器上。
二、基础使用
仅展示部分,完整教程请移步官方文档
1. 自定义导航、分组和标题
如果希望控制导航/分组/页面标题的生成,可以通过在 Markdown 文件顶部编写 FrontMatter 实现:
1 | --- |
在 site 模式下,我们也可以通过配置项对导航和左侧菜单进行增量自定义,请参考 配置项 - navs 以及 配置项 - menus。
2. 使用内置组件
在书写Markdown的时候可以使用一些语法写出dumi内置的一些特定样式的页面组件元素。
(1) Alert
使用 Alert
创建一个提示框,type 可选 warning
、info
、success
、error
,默认为 info。
1 | <Alert type="info"> |
(2) Badge
使用 Badge
可以创建一个标签:
1 | <Badge>这是一个标签</Badge> |
标题上也能加标签:
1 | #### 标签测试 <Badge>Hello</Badge> |
(3) embed
dumi 对 HTML 默认的 embed
标签做了扩展,可以在一个 Markdown 文档中嵌入另一个 Markdown 文档的内容:
1 | <!-- 引入全量的 Markdown 文件内容 --> |
三、进阶使用
仅展示部分,完整教程请移步官方文档
1. 多语言
让文档站点变成多语言这件事,对 dumi 用户来说是开箱即用的。比如我们使用英文编写了 docs/index.md
作为站点的首页,现在希望增加站点的中文版本,只需要创建一个带 zh-CN
locale 后缀的同名 Markdown 文件即可:
1 | <root> |
这样一来,当用户访问 www.example.com
时 dumi 会渲染英文版首页,访问 www.example.com/zh-CN
时 dumi 会渲染中文版首页,对于其他页面也是一样的,就像你正在浏览的 dumi 的官网一样。
(1) 默认语言
在 dumi 的默认配置中,en-US
是默认语言,zh-CN
是第二种语言,如果你需要修改这个配置,比如修改默认语言、或者添加更多语言,请查看 配置项 - locales 配置项。
(2) 翻译缺失
文档的翻译工作通常都是渐进式进行的,势必会存在『文档翻译到一半』的过渡期,为了让这个过渡期更加友好,dumi 会将默认语言的文档作为未翻译语言的兜底文档,举个例子:
1 | <root> |
很显然 missing.md
对应的中文文档 missing.zh-CN.md
是缺失的,用户在访问 www.example.com/zh-CN/missing
页面时,dumi 会把英文 missing.md
的内容呈现给用户。
四、配置项
完整教程请移步官方文档
在项目根目录创建 .umirc.ts
或 config/config.ts
文件,都可对 dumi 进行配置:
1 | // 配置文件 |
base
- Type:
string
- Default:
/
- 设置**路由前缀,通常用于部署到非根目录。
比如,你有路由 /
和 /users
,然后设置了 base
为 /foo/
,那么就可以通过 /foo/
和 /foo/users
访问到之前的路由。
publicPath
- Type:
publicPath
- Default:
/
- 配置 webpack 的 publicPath。当打包的时候,webpack 会在静态文件路径前面添加
publicPath
的值,当你需要修改静态文件地址时,比如使用 CDN 部署,把publicPath
的值设为 CDN 的值就可以。如果使用一些特殊的文件系统,比如混合开发或者 cordova 等技术,可以尝试将publicPath
设置成./
相对路径。
但相对路径
./
有一些限制,例如不支持多层路由/foo/bar
,只支持单层路径/foo
如果你的应用部署在域名的子路径上,例如 https://www.your-app.com/foo/
,你需要设置 publicPath
为 /foo/
,如果同时要兼顾开发环境正常调试,你可以这样配置:
1 | import { defineConfig } from 'umi'; |
navs
- 类型:
Object | Array
- 默认值:
自动生成的导航
- 该配置项用于自定义导航栏的展示,仅
site
模式下可用,分多语言模式和单语言模式,使用方式:
1 | // config/config.ts 或 .umirc.ts |
1 | // 多语言配置方式如下 |
favicon
- 类型:
string
- 网站图标,配置 favicon 地址(href 属性)。
比如,
1 | export default { |
如果要使用本地的图片,图片请放到
public
目录
HTML 中会生成,
1 | <link rel="shortcut icon" type="image/x-icon" href="/assets/favicon.ico" /> |
history
history:{type:'hash'}
这个路由的配置也很重要。hash模式下,地址栏多出一个‘#’号,#后边的字符不会被发送给服务端,改变#后边的内容也就不会重新发送请求,会发生位置的改变(跳到当前页面的某个位置)。在这种模式下,不修改服务器Nginx的配置就可以解决部署时首页可以打开,但是输入路由地址就404打不开的问题。开启这种模式就可以去掉配置中的base
路由前缀了。
- Type:
object
- Default:
{ type: 'browser' }
- 配置 history 类型和配置项。
包含以下子配置项:
- type,可选
browser
、hash
和memory
- options,传给
create{{{ type }}}History
的配置项,每个类型器的配置项不同
注意,
- options 中,
getUserConfirmation
由于是函数的格式,暂不支持配置 - options 中,
basename
无需配置,通过 dumi 的base
配置指定
proxy
- Type: object
- Default: {}
- 配置代理能力,可以实现跨域。(注意:proxy 配置仅在 dev 时生效)
1 | export default { |
然后访问 /api/users
就能访问到 http://jsonplaceholder.typicode.com/users
的数据。
五、FrontMatter
仅展示部分,完整教程请移步官方文档
FrontMatter 是指文件最顶部
对正文进行配置的部分,在 dumi 中,FrontMatter 均以 YAML 语法进行编写。
1. Markdown配置项
title
- 类型:
String
- 默认值:正文第一个标题
- 用于配置该页面的标题,将会被用作该页面标题的子标题以及左侧菜单。
- 类型:
sidemenu
- 类型:
Boolean
- 默认值:
true
- 控制侧边栏菜单的显示或隐藏。
- 类型:
toc
- 类型:
false | 'content' | 'menu'
- 默认值:
'content'
- 控制锚点目录的显示或位置,值为
false
时不展示,值为content
时展示在内容区域的右侧(Affix Menu),值为menu
时会将当前路由的锚点目录展示在左侧菜单中。
- 类型:
order
- 类型:
Number
- 默认值:
null
- 控制该文档的显示顺序,数值越小排序越靠前。
- 类型:
legacy
- 类型:
String
- 默认值:
null
- 指定该文档的旧路径(从根路径开始指定),避免从其他文档迁移到 dumi 后原路径访问
404
。
- 类型:
group
- 类型:
Object
- 默认值:
null
- 该配置用于对当前页面进行分组,这样可以在侧边栏菜单进行分组显示,我们可以通过下方三项 FrontMatter 配置项显示地对 group 进行配置,也可以基于 dumi 的文件夹嵌套来自动生成 group,例如:dumi 会自动为
1
2
3
4
5
6.
└── src/
├── components/
├── index.md
├── a.md
├── b.mdindex.md
、a.md
、b.md
指定group.title
为Components
、group.path
为/components
。并且我们可以通过 FrontMatter 对生成的默认配置进行选择性复写,比如:则最终生成的1
2
3
4---
group:
title: 组件
---group.path
还是/components
,但group.title
则变成了组件
。
- 类型:
group.title
- 类型:
String
- 用于配置侧边栏菜单中该组别的菜单项名称,如果未配置则会默认读取
group.path
并转换为title
,例如将/components
转换为Components
。
- 类型:
group.path
- 类型:
String
- 必选,配置该组别的路由前缀,当
location.pathname
匹配到该前缀时,菜单组会进行 active 标记。
- 类型:
group.order
- 类型:
Number
- 默认值:
null
- 控制该文档组的显示顺序,数值越小排序越靠前。
- 类型:
nav
- 类型:
Boolean
- 默认值:
true
- 控制侧边栏菜单的显示或隐藏。
- 类型:
nav.title
- 略,与
group.title
一致。
- 略,与
nav.path
- 略,与
group.path
一致。
- 略,与
nav.order
- 略,与
group.order
一致。
- 略,与
hero
- 类型:
Object
- 默认值:
null
- 在 site 模式下可用,配置 hero 后,该页面将会以首页形式呈现。
- 类型:
hero.image
- 类型:
String
- 默认值:
null
- 配置首页首屏区域的标题配图。
- 类型:
hero.title
- 类型:
String
- 默认值:
null
- 配置首页首屏区域的大标题。
- 类型:
hero.desc
- 类型:
String
- 默认值:
null
- 配置首页首屏区域的简介文字描述。
- 类型:
hero.actions
- 类型:
Array
- 默认值:
null
- 配置首页首屏区域的操作按钮,最后一个按钮会作为主按钮展示,配置格式如下:
1
2
3
4hero:
actions:
- text: Getting Started
link: /getting-started
- 类型:
features
- 类型:
Object
- 默认值:
null
- 在 site 模式下可用,配置后该页面将会以首页形式呈现,用于每行 3 个的形式展示组件库的特性,配置格式如下:
1
2
3
4
5features:
- icon: 图标的 URL 地址,建议切图尺寸为 144 * 144(可选)
title: 性能强大
link: 可为标题配置超链接
desc: 可以配置 `markdown` 文本
- 类型:
footer
- 类型:Markdown
- 默认值:
null
- 配置当前页面的 footer 区域,建议首页做配置即可,目前暂不支持统一对所有页面进行配置。
translateHelp
- 类型:
Boolean | String
- 默认值:
false
- 是否在该页面顶部展示『帮助翻译』的提示框。当设置
String
类型时,会自定义提示语内容。
- 类型:
hide
- 类型:
Boolean
- 默认值:
false
- 如果你暂时不希望在生产环境的站点中展示某些文档,可以打开这个配置临时隐藏它,该配置不会影响开发环境的渲染。
- 类型:
2. demo配置项
相关内容请访问官方文档
略…
六、常见问题
仅展示部分官方贴出来的,以及我在使用时踩坑遇到的问题,更多内容请移步官方文档
1. 访问子页面时刷新404
本地开发没问题,但部署完成后访问子页面再刷新就 404 了
这是由于打包产物默认只输出一个 index.html
作为入口 HTML 文件,服务器在 serve /
时可以找到文件但 /some-route
却没有对应的 /some-route/index.html
,所以会出现 404。
【解决方法一】:
设置config.exportStatic
为{}
根据路由按文件夹结构输出所有 HTML 文件即可,此配置项的更多用法可参考 Umi 文档:Config - exportStatic。也就是说设置完这个,可以让构建产物从只有一个index.html
,拆分成根据路由按文件夹结构输出所有 HTML 文件,子页面的网址在服务器中就有相应html文件了,自然会正常打开而不是404。【解决方法二】:
在配置文件.umirc.ts
中进行添加history:{type:'hash'}
路由配置,开启hash模式。hash模式下,地址栏多出一个‘#’号,#后边的字符不会被发送给服务端,改变#后边的内容也就不会重新发送请求,会发生位置的改变(跳到当前页面的某个位置)。在这种模式下,不修改服务器Nginx的配置就可以解决部署时首页可以打开,但是输入路由地址就404打不开的问题。开启这种模式就可以去掉配置中的base
路由前缀了。(此方法也可适用于非根目录部署
)【解决方法三】:
非根目录部署
的话可以修改 Umi 的 base 配置项 和 视实际情况 修改 publicPath 配置项。同时也要参照方法一中设置config.exportStatic
为{}
以免刷新页面时 404。1
2
3
4
5
6export default {
base: '/文档起始路由',
publicPath: '/静态资源起始路径/',
exportStatic: {}, // 将所有路由输出为 HTML 目录结构,以免刷新页面时 404
// 其他配置
};文档项目独立时, 通常 base 和 publicPath 配置项相同。
2. 代码块语言语法高亮
dumi 语法高亮使用的 prism-react-renderer ,是一款基于 PrismJS 实现的 React 组件。
在撰写代码块时我发现,Markdown代码块语法的三个反引号后面要跟小写的语言名称,dumi才能正常识别并进行高亮。
3. 添加全局CSS样式和JS脚本
如何添加全局 CSS 样式和统计脚本?
可在配置文件 .umirc.ts
中使用 Umi 的 styles 和 scripts 等配置项。
styles
- Type:
Array(string)
- Default:
[]
- 配置额外 CSS。
比如:
1 | export default { |
会生成 HTML,
1 | <head> |
links
- Type:
Array
- Default:
[]
- 配置额外的 link 标签。
比如想外联引入 public
文件夹下的css文件进行样式覆盖,可以这样写,并可以引入多个文件:
1 | export default { |
会在页面head标签中生成HTML:
1 | <link rel="stylesheet" type="text/css" href="./css/dumi.css" /> |
scripts
- Type:
Array
- Default:
[]
- 同
headScripts
,配置<body>
里的额外脚本。
比如想外联引入 public
文件夹下的css文件进行样式覆盖,可以这样写,并可以引入多个文件:
1 | export default { |
会在页面尾部生成HTML:
1 | <script src="./js/BFUI-dumi.js" defer="true"></script> |
headScripts
- Type:
Array
- Default:
[]
- 配置
<head>
里的额外脚本,数组项为字符串或对象。
大部分场景下用字符串格式就够了,比如:
1 | export default { |
会生成 HTML,
1 | <head> |
如果要使用额外属性,可以用对象的格式,
1 | export default { |
会生成 HTML,
1 | <head> |
4. 本地图片资源引用方式
(1) 配置文件中使用
在配置文件 .umirc.ts
中编辑 favicon
或 logo
等配置项的时候,如果想要引用本地图片,可以在项目根目录的 public
文件夹下 新建一个 images
目录用于存放图片,然后按照下方格式引入。也就是说,由于 .umirc.ts
和 public
都处于项目根目录中,属于同级文件,所以在 .umirc.ts
里采用相对定位 ./
就可以直接进入 public
文件夹。
1 | export default { |
不知是否是因为浏览器的设置问题,部署后用
Chrome
可以正常显示logo图片,但是Edge
却因为CORS策略而报错:Access to image at 'http://XXXXX.top/BFUI/images/logo.png' from origin 'http://XXXXX.top' has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private address space 'local'.
Failed to load resource: net::ERR_FAILED
(2) 在FontMatter中使用
比如在文档的首页 /docs/index.md
中配置 features
内容时,可能需要使用图片,可以参考下方代码。也就是说,在文档的FontMatter中直接 ./
进入的也是根目录下的public资源文件夹。
1 | --- |
(3) 在Markdown正文中使用
在Markdown文件正文中使用本地图片的时候,需要看的是该 .md
文件与 public
文件夹的相对位置。比如某项目文件夹它俩的结构是:
1 | + docs |
那么引用的时候写成 ../public/
才能进入public资源文件夹,这完全是相对定位的写法。
1 | ![BFUI-banner](../public/images/BFUI-banner.png) |
在Markdown中这种方式使用,会在dist中自动生成
static
文件夹存放图片
5. 在dumi中生成目录树结构
可以看到dumi官方文档的示例中有可以自动展开/收起的目录树结构,该效果怎么实现呢?
通过查询它的github代码可以发现在Markdown中写法是这样的(仅供参考):
1 | <Tree> |
对应生成的dumi目录树效果是这样的:
七、配置文件示例
以下内容是我某个项目的文件夹结构和配置代码,可以对使用 dumi 提供一些参考。
在dumi文档项目根目录中,public
文件夹用于存放静态资源文件,文件夹结构如下:
1 | + public |
在项目根目录创建 .umirc.ts
或 config/config.ts
文件,都可对 dumi 进行配置,下方的 .umirc.ts
代码,可以提供部分配置书写方式的参考。
1 | import { defineConfig } from 'dumi'; |
参考内容:
- dumi官方文档 - 指南
- Cannot find module ‘xxx’ 错误的解决方案
- dumi 搭建文档型博客
- 新出的 MFSU 方案,1s+ 完成启动
- UmiJS-插件化的企业级前端应用框架
- 在umi中如何访问静态资源
- vue 项目在 nginx 非根目录下部署访问没有目录名,刷新404的问题 (附npm install报错解决)
- vue 项目在 nginx 非根目录下部署时访问404的问题
- Umi&React打包部署到非根目录及刷新报错404的问题解决
- umi 部署html到非根目录下
- vue的history路由模式配置及后台配置
- 全局样式支持格式,styles是否可以支持import等方式
- Umi配置proxy解决跨域问题