前段时间有写过一个TypeScript在node项目中的实践。
在里边有解释了为什么要使用TS,以及在Node中的一个项目结构是怎样的。
但是那仅仅是一个纯接口项目,碰巧赶上近期的另一个项目重构也由我来主持,经过上次的实践以后,尝到了TS所带来的甜头,毫不犹豫的选择用TS+React来重构这个项目。
这次的重构不仅包括Node的重构(之前是Express的项目),同时还包括前端的重构(之前是由jQuery驱动的多页应用)。
因为目前项目是没有做前后分离的打算的(一个内部工具平台类的项目),所以大致结构就是基于上次Node项目的结构,在其之上添加了一些FrontEnd的目录结构:
. ├── README.md ├── copy-static-assets.ts ├── nodemon.json ├── package.json + ├── client-dist + │ ├── bundle.js + │ ├── bundle.js.map + │ ├── logo.png + │ └── vendors.dll.js ├── dist ├── src │ ├── config │ ├── controllers │ ├── entity │ ├── models │ ├── middleware │ ├── public │ ├── app.ts │ ├── server.ts │ ├── types + │ ├── common │ └── utils + ├── client-src + │ ├── components + │ │ └── Header.tsx + │ ├── conf + │ │ └── host.ts + │ ├── dist + │ ├── utils + │ ├── index.ejs + │ ├── index.tsx + │ ├── webpack + │ ├── package.json + │ └── tsconfig.json + ├── views + │ └── index.ejs ├── tsconfig.json └── tslint.json其中标绿(也可能是一个+号显示)的文件为本次新增的。
其中client-dist与views都是通过webpack生成的,实际的源码文件都在client-src下。就这个结构拆分前后分离其实没有什么成本
在下边分了大概这样的一些文件夹:
index.ejs 项目的入口html文件,采用ejs作为渲染引擎
index.tsx 项目的入口js文件,后缀使用tsx,原因有二:
1. 我们会使用ts进行React程序的开发
2. .tsx文件在vs code上的icon比较好看 :p
tsconfig.json 是用于tsc编译执行的一些配置文件
components 组件存放的目录
config 各种配置项存放的位置,类似请求接口的host或者各种状态的map映射之类的(可以理解为枚举对象们都在这里)
utils 一些公共函数存放的位置,各种可复用的代码都应该放在这里
dist 各种静态资源的存放位置,图片之类文件
webpack 里边存放了各种环境的webpack脚本命令以及dll的生成
前后端复用代码的一个尝试
实际上边还漏掉了一个新增的文件夹,我们在src目录下新增了一个common目录,这个目录是存放一些公共的函数和公共的config,不同于utils或者cofnig的是,这里的代码是前后端共享的,所以这里边的函数一定要是完全的不包含任何环境依赖,不包含任何业务逻辑的。
类似的数字千分位,日期格式化,抑或是服务监听的端口号,这些不包含任何逻辑,也对环境没有强依赖的代码,我们都可以放在这里。
这也是没有做前后分离带来的一个小甜头吧,前后可以共享一部分代码。
要实现这样的配置,基于上述项目需要修改如下几处:
src下的utils和cofnig部分代码迁移到common文件夹下,主要是用于区分是否可前后通用
为了将对之前node结构方面的影响降至最低,我们需要在common文件夹下新增一个index.ts索引文件,并在utils/index.ts下引用它,这样对于node方面使用来讲,并不需要关心这个文件是来自utils还是common
// src/common/utils/comma.ts export default (num: number): string => String(num).replace(/\B(?=(\d{3})+$)/g, ',') // src/common/utils/index.ts export { default as comma } from './comma' // src/utils.index.ts export * from '../common/utils' // src/app.ts import { comma } from './utils' // 并不需要关心是来自common还是来自utils console.log(comma(1234567)) // 1,234,567然后是配置webpack的alias属性,用于webpack能够正确的找到其路径
// client-src/webpack/base.js module.exports = { resolve: { alias: { '@Common': path.resolve(__dirname, '../../src/common'), } } }同时我们还需要配置tsconfig.json用于vs code可以找到对应的目录,不然会在编辑器中提示can't find module XXX
// client-src/tsconfig.json { "compilerOptions": { "paths": { // 用于引入某个`module` "@Common/*": [ "../src/common/*" ] } } }