同域名下通过一级路由区分实现“前端微构架”

前言

​ 公司的客户端项目比较庞大,并且由于改动相对频繁,导致更新频率较高,web项目高频率的更新就会引发一系列的问题,例如公众号缓存问题,尤其是ios手机容易出现白屏的情况,访问过程中的用户回退页面会出现白屏的情况,等等很多未知的bug,虽然更新在一瞬间完成,但是还是会影响到部分用户的使用,针对现存的条件以及项目需求

思考到如下优化方案

  1. 更新时间上尽量选择用户访问量小的时间段
  2. 程序内频繁变化的图片,文字的页面,尽量后台配置装修化,达到减少更新的效果,此处参考使用iframe+postMessage通信实现商城多页面可视化装修
  3. 项目能否进行拆分,权重不高的页面(例如:活动页面),与主程序分离,达到减少主程序包更新频率

思考与分析

第一条与第二条非本文重点,只做简要说明

  • 更新时间主要参照我们的客户端监控平台提供的检测数据,一般选择用户访问量较小的时候进行更新

  • 对于项目中频繁改动,但是数据格式固定的活动页,我们使用装修功能,达到不更新代码,只更新数据的效果

​ 而项目拆分就是我们本文要说到的重点,在调查过程中也了解过微前端,但是我们的客户端项目是uniapp完成的,考虑到技术难度与改动成本,最终放弃了微前端的方案

要怎么做到一个路径下面的项目拆分呢?

拆分的项目需要满足一下2个条件

  1. 拆分的项目必须在同域名下,不可出现跨域名的情况,不然就会出现无法共享localStorage的问题
  2. 本次改动不能影响到线上已经存在的业务,不能出现主程序的路由变动

为了满足以上2个条件,则主程序不能进行任何改动,同时需要在当前域名下,想办法再指向一个项目,在同一个域下,localStorage被共享,虽然是2个项目但是在同一个域下

最开始一直在思考客户端如何修改实现,但是一直没想到完美方案,后来,我们另辟蹊径,通过nginx实现通过子路由进行项目区分

nginx进行一级路由区分

通过nginx进行一级路由的判断实现访问不同的静态资源

理想情况下方案是可行的,nginx配置也比较简单

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
// .....
server_name xxxx.com
// .....
location / {
root /xxx/xxx/xxxx/packageA;
try_files $uri $uri/ /index.html;
}
location ~ /activity/ {
root /xxx/xxx/xxxx/packageB
try_files $uri $uri/ /index.html;
}
}

只要访问的项目路由 xxxx.com/activity/xxxxx,就会访问到项目包packageB,其他的一级路由都会访问到packageA

部署

因为项目activityB的访问路由是确定的,所以我们在webpack的配置中就需要对publicPath进行修改

1
publicPath: '/activity/',

​ 然后我们nginx会去访问项目包下面的index.html,而经过我们上面对publicPath的修改,打包之后的index.html里面的路径应用就变成了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" href="/activity/favicon.ico" />
<title>xxxxx</title>
<link href="/activity/css/app.xxxx.css" rel="stylesheet" />
</head>
<body>
<div id="app"></div>
<script src="/activity/js/chunk-vendors.xxx.js"></script>
<script src="/activity/js/app.xxxxx.js"></script>
</body>
</html>

此时打包上线就会遇到资源访问不到的问题,因为webpack编译出来的程序包里面没有activity这个文件夹,所以对indexPath,outputDir也要进行修改

最终我们的vue.config.js

1
2
3
4
5
6
7
8
9
10
11
module.exports = {
publicPath: '/activity/', // 资源路径
outputDir: './dist/activity', // 生产环境构建文件的目录
indexPath: '../index.html', // 指定生成的index.html的输出路径
configureWebpack: (config) => {
// ..
},
chainWebpack: (config) => {
// ..
},
}

到此为止,通过一级路由区分项目已经完成了全部配置

优点

  1. 对项目进行拆分,对于非核心程序的页面,例如活动页面等等,即可与主程序进行区分,上线活动页面不干涉主程序
  2. 项目分离后,单个项目的页面变少,单个代码包打包速度得到提升,增加项目可维护性

缺点

没办法共享公共逻辑代码,例如支付模块,登录模块,等等模块,因为跨项目了,当然这是有解决办法的,即公共模块打包成为npm包,但是这存在一定的工作量

最后

欢迎大家加入qq群吹吹水(群号:530496237)一起成长