「时光不负,创作不停,本文正在参加2021年终总结征文大赛」
前言
虽说是2021年总结,但故事却还从2020年10月开始讲起
正文
关于工作
2020年10月,我从一家10105.5的公司跳槽到目前的一家965的PaaS公司,也经历了一系列的挑战。
我所在的部门是一个大前端部门,部门内有安卓/ios开发,web/bff开发,electron开发以及C++开发。
而我所在的二级部门是其中的「web/bff开发」,最开始进去的主要从事一个从0到1的h5项目。
微服务
首先去了解了一下公司项目的部署方式。
公司内部的部署团队研发了一套容器化部署框架,因此这个h5项目也需要完成满足公司容器化部署框架的微服务,并注册到公司的容器服务集群中。
于是我就开始了我的h5项目微服务的搭建,其中涉及到了一些我之前没有使用过的技术:
- helm chart
- jenkins
- yaml(抱歉,我居然以前连yaml都没写过
- kubectl命令
- docker命令
由于公司没有专用的test,pre,prd环境,公司内部提供类似阿里云的云平台,可申请机子自用。因此我搭建了一套项目环境(内心OS,为啥没运维呢)
在jenkins pipeline失败了N多次,slb-nginx访问失败了N多次,ingress设置失败了N次,helm install失败了N多次后,我的pod终于安装好了!
微前端
在微服务pod完成后,我开始setup这个h5项目。
emm,项目其实没啥好说的,就正常的React + React Hooks + TypeScript。额外有一点是,这个项目是作为未来要在重点项目里实现的「客户端开放性」而预研的微前端技术。
而难点在于部署,按照刚才说的微服务的部署,难道我要每一个子应用都部署一个微服务吗,这也太坑爹了吧。
于是我想到一种方式:
- 在微服务pod的入口处架一个nginx的docker container
- 在微服务pod里注册其他的子应用的docker container
- 用nginx把流量导到对应的子应用docker container暴露的端口内
试了下,bingo!这样就可以我想怎么玩就怎么玩,而不需要跟每次新增子应用都要走上面微服务的部署流程了。这样每新增一个子应用,就只需要在nginx config里增加这个location,在helm chart里增加这个container,正常走构建出对应的镜像就好了。
monorepo
嗯,既然有1个主应用+N个子应用+一个nginx,那就弄一个monorepo吧。
通过 monorepo 策略组织代码,我的代码仓库的目录结构看起来会是这样:
├── lerna.json
├── package.json
├── composition # 子应用
├── app1 # 子应用1
│ ├── index.ts
│ ├── node_module/
│ └── package.json
├── app2 # 子应用2
│ ├── index.ts
│ ├── node_module/
│ └── package.json
...
├── core # 主应用
└── packages/ # 这里将存放所有可复用的代码
├── api # 可复用的请求以及req,res类型
│ ├── index.ts
│ ├── node_module/
│ └── package.json
├── common # 可复用的hook,utils,context,const,store,types
│ ├── index.ts
│ ├── node_modules/
│ └── package.json
├── components # 可复用的组件
│ ├── index.ts
│ ├── node_module/
│ └── package.json
├── icons # 可复用的icons
│ ├── index.ts
│ ├── node_module/
│ └── package.json
├── locales # 可复用的国际化
│ ├── index.ts
│ ├── node_module/
│ └── package.json
...
monorepo的优势就不说了,只是在对的场景使用对的技术,毕竟软件开发没有「银弹」
性能优化
使用了lighthouse对首屏进行了优化检测,在几个层面做了优化
-
措施1:优化LCP
- 优化弹出框,替换过大背景图片。对图片做preload。加快图片下载
-
措施2:减少无用JS、CSS,减小TBT,提升SI
- 借助Webpack Bundle Analyzer帮助我们分析项目
- 彻底code split
- 前端路由懒加载
- split chunk
- 微前端预加载
-
措施3:首图图片减小自定义首屏时间
-
措施4:资源预加载
- webpack插件来打包时增加preload属性
-
措施5:减少CLS
其实布局有偏移还是很常见的。比如我们的用户信息数据,在我的页面的用户信息卡片里,是异步接口获取的。所以看到可能会是页面先加载了一部分,然后拿到数据后进度条显示并生成进度条。这种异步的内容减少CLS的方式:
- 可以想办法把这个异步接口合并到主接口里来解决,或者设置一个默认的图片占位。等数据来了再替换掉
- useSWR:异步更新缓存策略
-
措施6:浏览器缓存机制(协商缓存)
结合强缓存和协商缓存,合理地缓存静态资源,比如当我们的资源内容不可复用时,直接为
Cache-Control设置no-store,拒绝一切形式的缓存;否则考虑是否每次都需要向服务器进行缓存有效确认,如果需要,那么设Cache-Control的值为no-cache;否则考虑该资源是否可以被代理服务器缓存,根据其结果决定是设置为private还是public;然后考虑该资源的过期时间,设置对应的max-age和s-maxage值;最后,配置协商缓存需要用到的Etag、Last-Modified等参数。
插件框架
4个月后,我进入了公司的重点项目,进行客户端开放性的插件框架的开发
于是我给这个插件框架定义了几条属性
- 插件开发的接入成本低
- 重点项目本身需要支持插件开发的套壳开发
- 插件框架对该重点项目的侵入性低
于是,在侵入性极低的前提下,我完成了插件框架。
倒也没啥难度,就二次封装了一下qiankun。
- 做好拉取配置,格式化,注册,激活,依赖注入,切换,卸载等工作流的hook
- 通过依赖注入,完成了提供主应用的能力给子应用的runtimeAPI
- 适配了electron客户端的插件加载
- 在框架中实现了插件开发的套壳开发,即使用一个支持了插件框架的重点项目的线上环境,使用sessionStorage注入一个定制的key和按开发文档规范配置的value,即可在线上环境里看到该插件,并热更新
关于技术
总结自己在这一年学习到了什么好像上文就已经概括了,说一些对明年的展望吧
React 18
毕竟要围绕自身工作的方向展开学习,而不是盲目学习前沿的技术
vue3
虽然不用,但是要学?
vite
让我感受一下极速的开发环境吧
Nest.js
在公司用到了,感觉很香,需要学习一下异常过滤器,管道,守卫,拦截器等
关于生活
今年是我跟她的第五个年头了,很幸运能在最美好的年华里遇到她
我们携手走过重庆的洪崖洞,漫步在成都的宽窄巷子,一起站在上海外滩FLIGHT集装箱里闭上眼睛,在大理苍山上举杯相拥
人潮拥挤
离别是常态,相逢只是意外
感激生命里
尚有你能让我满足到落泪
后记
推荐一首来自「发光曲线」的《小雷音之歌》
有一种向死而生的光线,每一個不曾起舞的日子,都是对生命的辜负
他应该漂亮,我应该对他充满信任,他应该成为我的爱情、我的偷盗、我的犯罪欲望的同谋
我是uWydnA,我们 2022 年再见,也祝读到此处的你,诸事顺利