1

曲折的 Vue 3 重构后台之路

 2 years ago
source link: https://innei.ren/posts/programming/mx-space-vue-3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

这篇文章上次修改于 07/01/21,可能其部分内容已经发生变化,如有疑问可询问作者。

3个月前,曾经有过想法重构现在的后台。Vue 3 也正式发布很久了,所以是时候重构到 Vue 3 了。但是由于当时尝试了很多 UI 库之后都没有找到一个好用的库。没有一个库能很好的支持 TSX。所以在多次更换 UI 库之后放弃了。
三个月之后的现在,偶然看到一个新库 naive ui,第一感觉这个库没有特别之处, UI 上和 antd 基本一致,就是换了个颜色?之后看了一下代码,嗯,全都是用TypeScript 写的。于是就有了试试的想法。一番 demo 之后决定捡起三个月前的项目重构成 naive-ui。

CommonJS 在 prod 中的问题

刚开始基本都是一帆风顺,很快的就重构了之前用 element-ui 写的没法看的 table组件。但是之后在build之后的prod环境下出了问题。dev 和 prod不一致。prod 开发一直白屏,控制台却没有任何报错和警告。这让我直接慌了,难道又要失败了?后来发现可能是 router guard 这块有问题,注释掉 guard 之后,果然就有报错了。但是还是不知道哪里的问题,因为没有 sourcemap。
我在解决问题之后构建了一个最小化复现项目,你想要来看看是什么原因导致的吗?
reproduction
https://github.com/Innei/vite-build-reproduction
这个是一个 CommonJS 模块,是这样导入的。
ts
1import * as camelcaseKeys from 'camelcase-keys'
在开发环境是一点问题都没有啊。生产环境就报错了。那么为什么会在 router guard 中出问题了,是因为在 router guard 中做了请求的鉴权,然后 response 做了一次 camelCase 处理用到了这个库。奇怪的是没有报错,而是在 router guard 一直在做死循环。
router guard 的代码如下,请求库采用 umi-request,鉴权接口用 github api 代替:
ts
1router.beforeEach(async (to) => {
2  if (to.meta.isPublic) {
3    return
4  } else {
5    // 在这里发送请求, 一般用于鉴权. 由于是复现, 随便用了接口请求
6    const res = await RESTManager.api.users.octocat.repos.get()
7    console.log(res)
8    if (!res) {
9      return '/login'
10    }
11  }
12})
13
14// ...
15
16//RESTManager.instance.interceptors.response.use(async (response, option) => {
17//  const newRes = await response.clone().json()
18//  return camelcaseKeys(newRes)
19//})
一般情况下,res 会输出响应体然后到达目标 route,但是输出的响应体却是空的,然后一直在跳转 /login,往复。但是并没有报 camelcaseKeys is not a function. 这就很奇怪。
然后我就在想既然是 CommonJS 的问题,就加个 rollup-plugin-commonjs 插件试试,然后就在 prod 中出现了,这样的报错。
我直接懵了,这又是啥,这又是哪个库。后来我又想,不应该啊,vite 都 v2 怎么可能处理不了 CommonJS 模块,然后我就升级了一下 vite 版本(因为是 3 个月前的项目),但是还是不行。最后我用 create-vite-app 新建了一下 demo,一样的代码(最小化版本)试一下,是 ok 的。那一定是我哪里配置有问题。vite.config 肯定是没问题的,一共就没几行。后来在对比 tsconfig.config.json 时,发现少了一行,"esModuleInterop": true,,这谁想得到,最会被人忽略的地方。加上之后一切都变好了。然后我去看了下 3 个月前的官方给的模板,果然,没有加这一行。啊,原来是官方害了我。

快乐的 naive-ui 之旅

naive-ui 还是写起来很舒服的,全程 tsx 无红线,类型提示没有问题。最重要的是遇到什么 bug 随时能和作者对接,深入探讨。顺便还水了几个pr。和之前 element-ui 写起来真的是一个天上一个地下。当然这个库还在初期,还需要社区的大力贡献。全程 tsx 写起来真的是很舒服了,除了 vue 本身一点局限性,不能 pass 任意 props 之外,其他写起来比 react fc 还舒服。
直接和作者对接

build 内存溢出的问题

终于,5 天时间重构的差不多了,是时候投入生产了。但是在一次提交之后,github ci 过不去了,原因是 build 的时候出现了 build out of memory。
这次提交了一个组件中导入了大量的不同的图标库。有 5 个图标库,而用具名导入的方式会导入整个模块,在 build 环境下进行 tree shake。所以一下导入了 5 个库之后出现了 out of memory。(一个图标库大概几十 M-100M,还是很大的)。
解决办法是全部改写成默认导出。如下
大功告成,github ci 不再出现内存溢出的问题,自动化部署完成。
大家不管在开发环境还是生产环境的 build 中遇到 node 占用内存过大,可以优先看看是不是某些库因为全量导入导致的哦。
最后来几张图吧。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK