No复制粘贴!多项目共用基础设施
一个完整的网站,不可能只包含一个jQuery,或是某个MVVM框架,其中必定包含了许多解决方案,例如:如何上传?如何兼容IE?如何跨域?如何使用本地存储?如何做用户信息反馈?又或者具体到如何选择日期?等等等等……这里面必定包含了UI框架、JS框架、各种小工具库,不论是第三方的还是自己团队研发的。而以上所述的种种,就构成了一套完整的解决方案,也称基础设施。
基础设施有个重要的特征,那就是与业务逻辑无关,不论是OA还是CMS又或是CRM,只要整体产品形态类似,我们就可以使用同一套基础设施。
框架
框架这个概念很泛,泛得让人心生困惑,但抽象出来说,框架就是一套定义代码在哪里写、怎么写的规则。不能说我们要怎么去用框架,反倒是框架控制我们怎么去填代码。
本系列前面的十来篇文章,分开来看是不同的点,但如果所有文章合起来,并连同示例项目(),实际上阐述的就是一套完整的多页应用框架(或称架构)。这套框架规定了整个应用的方方面面,举几个例子:
- 每个页面的文件放在哪个目录?
- 页面的HTML、入口文件、css、图片等等应该怎么放?
- 编码规范(由ESLint来保证)。
当然,这只是我的框架,我希望你们可以看懂了,然后根据自己的需求来调整,变成你们的框架。甚至说,我自己在做不同类型的项目时,整体架构也都会有不少的变化。
缘起
数月前,我找同事要了一个他自己写的地区选择器,拉回来一看遍地都是ESLint的报错(他负责的项目没有用ESLint,比较随意),我这人有强迫症的怎么看得过眼,卷起袖子就开始改,改好也就正常使用了。过了一段时间,来了新需求,同事在他那改好了地区选择器又发了一份给我,我一看头都大了,又是满地报错,这不是又要我再改一遍吗?当时我就懵了,只好按着他的思路,对我的版本做了修改。从此,也确立了我们公司会有两份外观功能都一致,但是实现却不一样的地区选择器。
很坑爹是吧?
上面说的是组件级的,下面我们来说架构级别的。
试想只是两个项目就已经这样了,如果是三个、四个,甚至六个、七个呢?堪忧啊堪忧啊!
快速创建新项目
不知道你们有没有这样子的经验:接到新项目时,灵机一动“这不就是我的XX项目吗?”,然后赶紧搬出XX项目的源码,然后删掉业务逻辑,保留可复用的基础设施。
也许你会说,这不已经比从零开始要好多了吗?总体上来说,是吧,但还不够好:
- 你需要花时间重温整个项目的架构,搞清楚哪些要删、哪些要留。
- 清理完代码想着跑跑看,结果一大堆报错,一个一个来调烦的要命,而且还很可能是删错了什么了不得的东西,还要去原先额项目里搬回来。
以上这些问题,你每创建一个新项目都要经历一遍,我问你怕了没有。
脚手架不是可以帮助快速创建新项目吗?
是的没错,脚手架本身就算是一整套基础设施了,但依然有下列问题:
- 维护一套脚手架你知道有多麻烦吗?公司项目一忙起来,加班都做不完,哪顾得上脚手架啊。最后新建项目的时候发现脚手架已经落后N多了,你到底是用呢还是不用呢?
- 甭跟我提Github上开源的脚手架,像我这么有个性的人,会直接用那些吗?
- 不同类型的项目技术选型不一样,比如说:需不需要兼容低版本IE;是web版的还是Hybrid App的;是前台还是后台。每一套技术选型就是一套脚手架,难道你要维护这么多套脚手架吗?
上述问题,通过共用基础设施,都能解决
- 既然共用了基础设施,要怎么改肯定都是所有项目一起共享的了,不论是组件层面的还是架构本身。
- 假设你每个不同类型的项目都已经准备好了与其它项目共用基础设施,那么,你根本不需要花费多余的维护成本,创建新项目的时候看准了跟之前哪个项目是属于同一类型的,凑一脚就行了呗,轻松。
在之前的文章里,我使用的一直都是这个脚手架项目作为示例,而为了实践多项目共用基础设施,我对该项目的架构做了较大幅度的调整,升级为2.0.0版本。为免大家看前面的文章时发现示例项目货不对板,感到困惑,我新开了一个repo来存放调整后的脚手架:Array-Huang/webpack-seed-v2,并且,我在两个项目的README里我都注明了相应的内容,大家可不要混淆了哈。
下面就以从到Array-Huang/webpack-seed-v2的改造过程来介绍如何实现多项目共用基础设施。
改造思路
改造思路其实很简单,就是把预想中多个项目都能用得上的部分从现有项目里抽离出来。
如何抽离
移动到哪里了呢?自然是移动到与项目目录同级的地方,这样就方便多个项目引用这个核心了。
如果你跟我一样,在原项目中定义了大量路径和alias的话,移动这些文件/目录就只是个改变量的活了:
选自:
抽离的方法很简单,那么关键就看到底是哪些部分可以抽离、需要抽离了,这一点看我就比较清晰了:
先来看根目录:
再来看看目录
最后总结一下,是哪些资源被抽离出来了:
- webpack配置中属于架构的部分,比如说各种loader、plugin、“核心”部分的alias。
- “核心”部分所需的配置,比如我这项目里为了定制bootstrap而建的配置。
- 各种与UI相关的资源,比如UI框架/样式、UI组件、字体图标。
- 自研库/适配器。