归来的技术栈

所有的设计都是从开发者面对的问题出发。

我要用有限的人手(就当是我一个人吧)进行全栈开发,中小型项目。从开发角度讲,要同时保证开发效率和业务模块的可移植性;从运行的角度讲,需要较高的可靠性但对性能要求不高。

向来是个全栈程序员。自从上次换了工作,到现在三年多。后端一直在用 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
浙ICP备15043004号-1