大型前端项目结构设计

11,827 阅读8分钟

将模块化的思想进行到底

这个结构也是我们项目目前正在使用的,应对两三百个页面的web项目是没有任何问题的,在扩展性,多人合作方面是非常优秀的。废话不多说,先上结构,再说为什么要这么做。

├── service                         # 后端接口管理
│   ├── index.js                    # 接口管理出入口
│   └── ...                         # 具体的不同业务/服务接口文件【S-1】
├── assets                          # 项目依赖资源管理
│   └── imgs                        # 图片资源
│   ├── style                       # 样式资源
│   └── js                          # 依赖的第三方sdk之类的js资源
├── components                      # 项目组件目录
│   ├── public                      # 公共组件/基础组件(比如基础的按钮/输入框等)
│   │   ├── index.js                # 基础组件的注册文件【可选】
│   │   ├── README.md               # 组件使用说明文档【可选】
│   │   └── ...                     # 组件
│   └── ....                        # 基础性的业务组件(有详细说明)【C-1】
├── pages                           
│   ├── modules                     # 具体业务所归属的文件夹(可以用业务名称作为文件夹名字)
│   │   ├── components              # 业务所用到的组件
│   │   ├── views                   # 业务的所有页面
│   │   ├── utils                   # 业务的工具集
│   │   ├──	static                  # 业务所用到的静态资源
│   │   ├── service                 # 业务的后端接口管理
│   │   ├── store                   # 业务所用到的状态库(本结构基于Vue,这里是业务的Vuex)
│   │   └── index.js                # 业务的唯一出口(包含路由与状态库)
│   └── ....                        # 其他业务【P-1】
├── config                          # 项目的基础配置
│   ├── index.js                    # 配置文件的出入口
│   └── ...                         # 具体的配置文件【C-2】
├── router                          # 项目的路由管理
│   ├── index.js                    # 路由出口
│   └── ...                         # 与路由有关的其他文件【R-1】
├── store                           # 项目状态库的管理
│   ├── index.js                    # 项目状态库的出入口
│   └── ...                         # 具体的基础模块【S-2】
├── utils                           # 项目所用的工具集(封装的请求,表单的验证函数,时间格式化.....的工具)
│   ├── index.js                    # 工具的入口
│   └── ...                         # 具体的各个工具(请求封装、正则、验证......)【U-1】
├── main.js                          
├── App.vue

首先,这个结构是基于Vue来设计的,设计思路来源于小程序分包加载机制。示例的结构主要为src 目录下。

虽然给出的结构是基于Vue,但是其他像小程序,React等也是可以使用的,核心思想都是将具体的一个一个的业务作为一个独立模块的,然后将一个一个的模块组成一整个项目。

接下来对标注的序号做下说明

  • S-1:

    • s-1部分的接口管理,主要用来存放项目的基础接口,例如数据埋点等,不影响具体业务功能使用的接口

    • 如果这类的接口数量非常大,可以根据不同的类型划分或者根据所属的服务划分(我们的项目后端是微服务架构,前端接口根据服务划分的)为多个文件,然后将其导出;再在index.js中将不同类型的接口文件导入后做整体导出。

    • 如果这类接口数量并不大,则可以直接在index.js中进行管理导出。

    • 如果说再可预见的范围内这类接口不会变多,甚至可以完全不要service 文件夹,将index.js 命名为service.js 放在根目录(src)下

  • C-1:

    • 基础性的业务组件可以为整个项目共有的唯一的登录注册所用的组件,也可以为整个项目共有的header或者导航等组件
    • 如果你选择将这些基础性的组件,比如登录注册业务的组件放在业务的模块中;在components 中仅存放公共/基础组件,那可以直接将public 中的文件放在components 下,去掉pubilc 文件夹
  • P-1:

    • modules 为每一个具体的业务,拥有独立的路由,独立的状态库,独立的工具库... modules 的目的就是将一个业务作为一个整体封闭起来,只留一个对外的出口index.js ,如此,当公司有一个同类型的项目出现同样的业务,可以非常方便的进行迁移。

    • static 存放静态资源,utils 存放工具集,如果你的业务静态资源只有不多的一些图片,工具集只有一两个文件,完全可以将两个文件夹保留一个即可。

    • store 是业务的状态库,基于 Vuexmodule 设计,内部可以根据需要再自行划分,但终都需要进行导出。

    • index.js 是业务唯一的对外出口,凡是需要供外部使用的(业务页面的路由,业务的状态库)文件,到需要导入至index.js 后再来做整体导出。

  • C-2:

    • config 是一个可选的配置,主要用来存放项目相关的配置。
    • 如果说你的项目是要提供给不同的客户来使用,每个客户都有自己特殊的需求,比如系统的logo需要使用客户特定的logo,系统的title需要使用客户提供的内容,甚至客户说我需要ACE三个业务,不要BDF三个功能,我们都可以给不同的客户写入不同的配置,在根据不同的配置来打包生成不同功能的系统具体内容可以看我的另一篇文章:vue不同环境打包命令配置 中的场景二
  • R-1:

    • 路由这里没什么需要特殊说明的,就是将各业务暴露的路由导入即可。
    • 如果其他与路由相关的文件,甚至可以直接将路由文件移至src 下,删除router 文件夹
  • S-2:

    • store 中放的是基础的、不影响业务使用的、无耦合数据,以及store 对外提供的出口文件
    • index.js 及将各业务对外暴露的store导入进来,处理之后再做整体导出。
  • U-1:

    • utils 下也就是基础性的工具集,例如封装的请求等

结构的功能说明也就这些。

为什么要这么设计呢,最大的原因还是解耦和提高复用性,于我所在公司而言,我们有多个相似的管理系统,可能有部分业务在这个系统上有,其他系统上产品说也要上这个功能,那根据这个结构,我就可以直接将对应的功能模块复制到另一个系统中去,然后将业务暴露的出口接入到另一个系统中,直接就可以完成功能的迁移。

使用微前端来管理大型项目

上面的结构是我们项目正在使用的,hold住两三百各页面的项目还是比较轻松的,但项目在可预期的范围内正在往更大型进化,难保上面的结构还能继续支撑。所以我们需要探寻更合理的架构来支撑我们的项目,计划引入微前端的概念。

微前端是什么

微前端的概念来源于后端微服务架构,对于一个超大型的项目,直接管理是肯定不方便的。所以我们可以将一个超大型项目根据业务来拆分成多个小项目,将每一个小项目交给不同团队去开发,不依赖具体的技术栈,最终将这些小项目组成一个完整系统。这就是微前端。

有什么优点

项目管理方便,这是肯定的,将一个大型项目层层拆分,不同团队开发不同业务,各团队自行管理,相对直接去管理一整个大型项目更方便。

不依赖特有的技术栈, 微服务化的前端,每一个项目都可以根据开发团队的习惯来使用他们更熟悉的技术栈。

解耦, 微前端后,各个项目的耦合性更低,业务间的影响会更小。

增量升级, 无论是改bug,还是升级迭代,我们只需要在对应的业务中去改,改完之后独立发版,哪怕出现重大事故,只需要屏蔽对应业务即可,不会造成整个项目崩塌。

独立部署

如何将各项目组合集成

相对于拆分而言,如何将完成后的各个小项目组合成一个整体,这部分就不太容易了,但这部分更加重要。

iframe, 第一种集成思路是使用iframe 来集成,在iframe 中加载不同的项目包。

nginx, 第二种思路是通过nginx 配置代理,将不同的路由通过nginx 转发到不同的项目。

前两种是最容易想到的集成方案,各有优缺点,也各有不同的适用场景。

云上打包编译, 这个思路来源于Jenkins ,每个项目向外暴露一个配置文件,告诉打包系统需要如何打包加载。

本地打包云上集成, 集本地打包完成后,将配置文件和打包后的文件上传云上,打包系统根据根据配置文件来决定需要舍弃那些文件,如何加载文件。

上面这两种集成方式,目前只是一个实现思路,可能还需要主系统或者各业务项目提供一些对外变量,告诉浏览器各业务需要渲染在什么位置。

总结

微前端之后肯定是大型项目架构的首选,遗憾的是目前并没有开源的微前端解决框架/方案,所以如果你的项目需要使用微前端来解决问题,在目前阶段。可能需要大家一起来踩坑了,诸君共踩!!