本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
DevOps理论中有一个很重要的观点:在复杂的系统中工作时,我们不可能预测到所有的结果。
因此错误或缺陷在所难免,我们要将错误视作机会,学习和自我改进的机会,当我们深刻理解了错误,我们就能避免下一次更严重的错误。
Vue DevUI 是 Vue3 版本的 DevUI 组件库,基于 Ng DevUI。
Vue DevUI 使用最新的技术栈进行开发:
- 使用
Vite
搭建基础工程(【我要做开源】Vue DevUI开源指南04:使用Vite搭建一个支持TypeScript/JSX的Vue3组件库工程 ) - 使用
VitePress
搭建文档系统(【我要做开源】Vue DevUI开源指南05:给Vue3组件库添加VitePress文档系统) - 使用
Vue3
+TypeScript
+JSX
进行组件开发(【我要做开源】Vue DevUI开源指南03:如何给 tree 组件增加展开/收起功能) - 使用
Jest
+@vue/test-utils
进行单元测试 - 使用
eslint
/stylelint
/ls-lint
进行代码规范检查
在开发 Vue DevUI 的过程中,我们也遇到不少问题:
- 有些是我们的contributor提的issue
- 有些在和村长直播过程中发现的问题
- 还有一些和VitePress文档系统相关
以下是本文将要分享的问题列表:
- 8.16 vitepress中使用自定义指令导致的问题
- 9.18 defineEmit导致的文档启动白页问题
- 10.3 使用window浏览器变量导致的vitepress ssr构建问题
问题一:vitepress中使用自定义指令导致的问题
问题背景和描述
第一个问题最早可以追溯到8月16日,由vue devui
的早期贡献者wailen提出 I45VB6,当时vue devui
的文档系统刚刚切换到vitepress
一个多星期。
以下是wailen
同学当时提的issue:
当时通过执行yarn build
文档构建命令就可以很轻易地复现该错误:
报错信息如下:
SyntaxError: Custom directive is missing corresponding SSR transform and will be ignored.
以下是当时wailen
的截图:
不过当时vue devui
项目刚开始活跃,大家都忙着提交pr、提交issue、检视和合入代码,没有太关注到这个issue,而且当时咱们的网站还没有通过域名访问,不需要部署实际的主机,也就不需要执行yarn build
构建生产包,因此都没关注到这个问题。
问题分析
看截图的报错信息,是vitepress
构建过程中遇到了语法错误导致构建失败,提示自定义指令缺少服务端渲染的转换器
:
SyntaxError: Custom directive is missing corresponding SSR transform and will be ignored.
很幸运,报错提示定位到了具体的文件:
file: D:/code/vue-devui/sites/components/loading/index.md:124:3
这个文件是Loading
组件的md文档,以下是会导致构建错误的内容:
<div
v-dLoading="promises.value"
:backdrop="true"
message="One moment please..."
style="margin-top: 20px; width: 100%; height: 80px; padding: 10px;"
>loading will show here2</div>
可以看到这个只用了一个v-dLoading
的自定义指令,而vitepress
文档使用的构建方式SSR服务端渲染,SSR过程中没有相应的transform
转换器来解析这个vue的自定义指令,所以构建文档报错啦。
解决方案
知道问题的原因,解决起来就很容易啦。
- 一种方案是为这个自定义指令编写相应的transform
- 另一种方案是安装patch-vue-directive-ssr补丁
我们选择第二种方案:
yarn add -D patch-vue-directive-ssr
patch-vue-directive-ssr
补丁包专门用于修补@vue/compiler-ssr
,以使用SSR/SSG方式构建vue自定义指令。
问题二:defineEmit 导致的文档启动白页问题
问题背景和描述
这个问题最早发现于9月18日和村长在B站直播的那个晚上,以下是直播的录播地址:
【我要做开源】华为大佬亲授,Vue DevUI开源指南01:提交我的第一次pr
这个问题发生在执行yarn dev
命令启动组件库文档的时候,执行完yarn dev
命令,在浏览器地址栏输入http://localhost:3000/
访问文档,出现白页。
问题分析
打开浏览器控制台,发现红色的报错,提示了一个语法错误:
Uncaught SyntaxError: The requested module '/vue-devui/node_modules/.vite/vue.js' does not provide an export named 'defineEmit'
依然非常幸运,这个报错定位到了具体的文件:
/vue-devui/sites/.vitepress/devui-theme/components/NavBar.vue
这个文件从vue
中导入了defineEmit
这个方法:
<script setup lang="ts">
import { defineEmit } from 'vue'
import NavBarTitle from './NavBarTitle.vue'
import NavLinks from './NavLinks.vue'
import ToggleSideBarButton from './ToggleSideBarButton.vue'
defineEmit(['toggle'])
</script>
错误就发生在这里。
非常巧,正好直播那天晚上,我们将vue devui
的vue
版本升级到了vue@3.1.5
,从3.1.5
这个版本开始,vue的一些api发生了变化,比如这里的defineEmit -> defineEmits
。
解决方案
知道了原因,答案呼之即出。
直接把
defineEmit
改成defineEmits
即可。
以下是当时直播间手速最快的 hzttw 同学提的 pr:
问题三:使用 window/document 等浏览器变量导致的 vitepress ssr 构建问题
问题背景和描述
这也是一个非常典型的问题,最早发现于国庆节期间,当时我打算将 vue devui 的网站部署到域名,但我又不想购买云主机,所以打算白嫖码云的:部署到gitee.io
域名。
部署之前得先构建网站的生产包,没想到那么久没执行yarn build
命令,执行完直接报错了,先是包了问题一那个问题:
SyntaxError: Custom directive is missing corresponding SSR transform and will be ignored.
这个问题好解决,直接安装 patch-vue-directive-ssr 补丁包即可:
yarn add -D patch-vue-directive-ssr
安装完补丁包这个问题解决,再次构建还是出错,报了另一个错 I4D06D:
ReferenceError: window is not defined
问题分析
很不幸,这个报错没有定位到具体的文件。
以下是报错的详细信息:
✓ building client + server bundles...
✖ rendering pages...
build error:
ReferenceError: window is not defined
at /vue-devui-theme/node_modules/vitepress/dist/client/app/temp/app.js:932:3
at Module.<anonymous> (/vue-devui-theme/node_modules/vitepress/dist/client/app/temp/app.js:937:2)
at Module._compile (internal/modules/cjs/loader.js:999:30)
at Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at extensions..js (/vue-devui-theme/node_modules/esbuild-register/dist/node.js:2696:24)
at Object.newLoader [as .js] (/vue-devui-theme/node_modules/esbuild-register/dist/node.js:2262:9)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Module.require (internal/modules/cjs/loader.js:887:19)
at require (internal/modules/cjs/helpers.js:74:18)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
都是构建报错,我们对比下问题一的报错信息:
[vite:vue] Custom directive is missing corresponding SSR transform and will be ignored.
file: /Users/kagol/Documents/Kagol/code/vue-devui-theme/sites/components/loading/index.md:124:3
✖ building client + server bundles...
build error:
SyntaxError: Custom directive is missing corresponding SSR transform and will be ignored.
at Object.createCompilerError (/Users/kagol/Documents/Kagol/code/vue-devui-theme/node_modules/@vue/compiler-core/dist/compiler-core.cjs.js:19:19)
...
还是发现了一些不同,问题一的报错出现在build bundles
阶段,而现在这个报错build bundles
是成功的:
✓ building client + server bundles...
但是render pages
阶段失败了:
✖ rendering pages...
这里涉及到 vitepress ssr 构建的知识。
通过阅读vitepress
源码,我们了解到我们执行vitepress build docs
命令时,实际上构建的过程分成两个步骤:
- 调用
bundle
方法,使用vite
进行ssr
构建,也就是构建日志中的building client + server bundles...
- 调用
renderPage
方法,使用vue router
的router.go(routePath)
进行页面的渲染,也就是构建日志中的rendering pages...
但是渲染页面的时候,vitepress
并不知道具体是哪个文件出错,所以没法给出定位到具体文件的详细提示信息。
这时就需要靠有经验的程序员的直觉进行问题定位了。
由于是服务端渲染,并没有浏览器环境,只是一个nodejs的环境,因此window
变量肯定是不存在的,所以提示:
ReferenceError: window is not defined
但到底是哪个文件导致的报错呢?
先尝试全局搜索下关键字window
,一共有20个文件包含window
:
再加个点window.
缩小下范围,还有17个文件包含window.
:
通过慢慢分析每一个文件,就能解决这个问题。
解决方案
这个棘手的问题最终由Zcating同学解决。
fix(build): 修复 vitepress 打包时出现的问题
Zcating
同学是devui
开源组织的核心成员,从去年Ng DevUI
刚开始开源以来就一直非常活跃,而且给我们的掘金专栏投过6篇RxJS
原理分析的文章,vue devui
组件库的第一个组件Button
就是Zcating
同学贡献的。
除了Button
组件,Zcating
同学还是Modal
/Overlay
等多个组件的田主,不仅频繁活跃地检视代码,而且承担着vue devui
最复杂组件Table
的设计和开发工作。
Zcating
同学也在运营一个公众号:zcx的工作室
,欢迎大家关注呀~
主要解决手段包括:
- 定义
inBrowser
方法,在使用了window等浏览器变量的地方提前返回 - 将包含window等浏览器变量的代码移到
onMounted
生命周期事件中
感兴趣的小伙伴可以看下Zcating同学的pr:
fix(build): 修复 vitepress 打包时出现的问题
欢迎一起建设 DevUI 开源项目
我们 DevUI
团队有多个开源项目,现在都在招募contributor
,欢迎大家一起参与开源中来!(感兴趣的小伙伴可以添加DevUI
小助手的微信:devui-official
,将你拉到我们的核心开发群)
- Ng DevUI: github.com/DevCloudFE/…
- Vue DevUI: gitee.com/devui/vue-d…
- DevUI Admin github.com/DevCloudFE/…
DevUI
官网:devui.design/
也欢迎关注我和村长的【Vue DevUI开源指南】系列直播!
Vue DevUI开源指南系列直播打算分成两条线:
- 组件设计和实现
- 组件库的工程化
目前【组件设计和实现】已经完成了3期(还未结束):
- 【我要做开源】华为大佬亲授,Vue DevUI开源指南01:提交我的第一次pr
- 【我要做开源】华为大佬亲授,Vue DevUI开源指南02:做一个有模有样的Tree组件
- 【我要做开源】华为大佬亲授,Vue DevUI开源指南03:学会“单测”才会有安全感!完成Tree组件!
【组件库工程化】已经完成了2期(正在进行中):
- 【我要做开源】华为大佬亲授,Vue DevUI开源指南04:组件库工程化建设之项目初始化、jsx支持
- 【我要做开源】华为大佬亲授,Vue DevUI开源指南05:开源组件库中的文档建设,vitepress使用过程中的踩坑经历,克服这些困难你将收获多多!
- 【我要做开源】Vue DevUI开源指南06:手把手带你开发一个脚手架
已经跟村长老师达成共识,只要村长老师的直播间不倒,只要还有小伙伴愿意参与进来,这个系列就会一直做下去!
欢迎大家持续关注、分享出去~我们一起来从0到1做一个vue3开源组件库!
每周五晚上九点,我们在村长的直播间,不见不散!