归来的技术栈
所有的设计都是从开发者面对的问题出发。
我要用有限的人手(就当是我一个人吧)进行全栈开发,中小型项目。从开发角度讲,要同时保证开发效率和业务模块的可移植性;从运行的角度讲,需要较高的可靠性但对性能要求不高。
向来是个全栈程序员。自从上次换了工作,到现在三年多。后端一直在用 PHP 和 Slim 框架,Composer 进行包管理,MySQL 做数据库,开发 restful 风格的接口,四平八稳;前端页面做成 SPA 形式,因缘际会用了 riot.js,理念和现在当红的 react 和 vue 相似,功能稍弱,但学习成本也低。
这个理念,正是这次想要更换技术栈的主要原因,上个月和朋友聊天时,说起了以前为什么会选择 riot.js,为了 riot.js 官网里的两句话:
We should focus on reusable components instead of templates
Templates separate technologies, not concerns
这个观点其实是 react 的开发者提出来的,我们要关注的是可重用的组件而不是模版,模版的概念是从技术角度出发的,而真正需要我们关心的是业务。第一次看到这个观点时,我是震撼的,因为那时我正在用 Angluar 1,老是要在文件(模型、视图、控制器)之间来回切换和定位,总觉得现状有问题,却又不知道如何改变。
那天聊完之后,我突然意识到,同样的理念可以走的更远一点,不用限定在组件的级别,用在业务模块的级别上也是可行的(尤其是对全栈开发者和中小型项目来说)。我们之前的项目根据前后端来划分目录结构,也是一种从技术角度出发的选择,而这让我遇到了一些问题。
先来看看以前的项目结构(隐藏了一些不必要的细节)
.
├── app
│ ├── lib
│ │ ├── admin
│ │ └── app
│ └── router.php
├── lib
├── pages
│ ├── admin.html
│ └── app.html
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
└── riot-tags
├── admin
└── app
/app/lib
目录下是后端的逻辑,/pages
目录下是前端入口页面(模版,通过PHP调用展示),/riot-tags
下是前端文件,其他前端需要用到的图片、公共样式和库都在 /public
下面。
假设另一个项目需要用到 admin 模块,我只能分别将 /app/lib/admin
,/pages/admin.html
,/riot-tags/admin
拷贝到新项目里去。但是 /public
目录下的内容就比较麻烦了,不同模块用到的东西都混在一起,已经很难分清哪个被谁用了。如果再在这些目录下按模块分目录,又会变得非常繁琐。
这样分配目录还会对开发者的心态产生潜移默化的影响,两个模块的后端文件之间靠的太近,会增加相互调用,写出高耦合度代码的倾向。
之前的工作是开发一个长期维护的平台,没有这方面的考量,而现在经常遇到将之前开发的系统中的功能挑几个出来,做成一个新系统的需求,因此模块的独立性和可移植性变得非常重要。
新的目录结构类似这种形式(隐藏了一些不必要的细节):
.
├── app.js
└── src
├── admin
│ ├── stylesheets
│ ├── javascripts
│ ├── index.html
│ ├── client.js
│ ├── riot-tags
│ └── server.js
└── app
├── stylesheets
├── javascripts
├── index.html
├── client.js
├── riot-tags
└── server.js
除了目录之外,现在的技术栈也存在其他方面的问题,由于同时用了 PHP 和 JavaScript 两种主要的开发语言,在小公司难招人的情况下,招两个都会的人更难;需要用到两个包管理工具,开发环境、运行环境、开发工具配置什么也都要搞两种;虽然已经把服务端搞得很瘦,常用逻辑的代码生成器也做了;但同时要维护两套东西确实不够DRY的。
说到底还是人不够。
所以,只能尽可能把技术栈缩小,另外通过把粒度做粗一点、牺牲一定的性能来换取开发时的便利和运行时的稳定。
于是,在国庆假期的时候,时隔三四年,再次拿起 node.js 和 express,是为“归来的技术栈”(不知道为什么突然想起了《归来的奥特曼》,挺应景的,所以取了这么个标题)。
这次把整个结构从头梳理了一遍,保留之前的成功之处,再引入一些新鲜血液。整个过程下来,积攒了不少东西,在此和大家分享。当然,由于各自面对的问题和环境不同,你不一定认同我的某些观点,但我仍希望能带给你一些有意思的东西。
先丢几个我非常认同的观点:
代码是写给人看的,其次才是给机器执行
软件的维护成本非常重要,软件生命周期越长越重要,直到变成最重要的
开发人员的时间比机器的更宝贵
写博客比写代码更花时间
这个系列会包含以下内容:
- 正确模块化,express 的 app.use
- 无状态的服务端
- json web token
- 一个小坑 - app.use 和 unless 的 useOriginalUrl
- 无状态的客户端
- 单页面应用和路由 - navigo
- 如何保存和校验密码 - bcrypt
- 打通前后端,简化操作 - pouchdb
- 打通前后端,简化操作 - restlike
- 简化开发流程,后端自动重启和热更新
- 简化开发流程,前端热更新 - webpack