阅读 16137

Node.js + TypeScript 写后端工具

前言

现在 Node.js 的生态越来越成熟,有好多公司直接使用 Node 构建其后端应用,放在线上跑。TypeScript 是微软的编程语言,近年来受到的关注也是越来越多。

作为一个常年写后端接口的人,便想:能不能利用这两者,来给自己的工作流,带来一点不一样的感觉。(由于这不是写客户端 JS,所以我们并不需要 webpack 等工具 )

步骤

初始化项目

假设项目目录是 project 。

cd project

mkdir src && touch README.md

cd src 

npm init

tsc --init

根据惯例,弄一个主入口 main (注:这里没有使用 index.js 这种设定 )
touch main.ts
复制代码

初始化完成的项目是这样的:

project/
    README.md
    src/
        package.json
        tsconfig.json
        main.ts
复制代码

安装必备的包

目前暂时只想到了如下的这些包:

npm install --save lodash @types/lodash

npm install --save @types/node

npm install --save-dev typescript 
复制代码

之后项目变成这样子:

project/
    README.md
    src/
        package.json
        tsconfig.json
        main.ts
        node_modules/
复制代码

配置 tsconfig.json

这一步最为重要。官网有一节专门讲这个:http://www.typescriptlang.org/docs/handbook/tsconfig-json.html 。要看懂还是需要花点时间的。

总而言之,需要告诉 tsc 如下几件事情:

  1. 项目的根目录在哪? (以 tsconfig.json 所在的目录为根目录,即项目根目录 )
  2. 输入在哪? (即:项目的哪些ts 文件是需要关心的,标准库/第三方库去哪里找)
  3. 输出在哪?(由于不是前端项目,所以我们只需要每一个 ts 输出对应的 js 文件即可)

这里是一个示例配置,有详细的注释说明,初始化 ts 项目时,可以直接拷贝之,以节约时间成本。

{
    // tsconfig 所在的根目录, 则是一个project
    "compilerOptions": {
        "module": "commonjs", // 模块系统
        "target": "es2015",   // 生成目标, 一般选择ES6,因为不是客户端环境,没必要还编译成  ES5
        
        // 一组严苛的编译选项
        "noImplicitAny": false,
        "strictNullChecks": true,
        "strict": true,
        "alwaysStrict": true,
        "sourceMap": false,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "pretty": true,
        
        "listFiles": true,  // 包含了哪些库,这个必要的时候还是很有用的
        "listEmittedFiles": true, 
        "lib": [            // 要那些 lib,按需选择即可
            "es2016"
        ],
        // "noUnusedLocals": true,
        // "noUnusedParameters": true,
        // "noFallthroughCasesInSwitch": true,
        // 指定库的搜索路径,这个比较有用,一般会指定 @types,还可以按需添加
        "typeRoots": [
            "./node_modules/@types"
        ]
        // 库搜索路径下, 仅使用哪些库, 一般没啥用
        // "types": [
            
        // ]
    },
    // file include会算出一个交集, 指明哪些是项目的 ts 文件
    "include": [
        "./**/*"
    ],
    // 排除项目下面不符合要求的文件,这个按需设定即可,可以放心排除乱七八糟的文件
    "exclude": [
        "node_modules",
        "**/*.spec.ts",
        "*.js"
    ]

    
}
复制代码

设计项目的目录结构 为了模拟真实的场景,我们的 main.ts 有如下内容:

function main() {
  
}

main();
复制代码

写一个 utils.ts,放入 src/core/utils.ts 中。

import * as path from 'path';                     // 测试能否正常使用 Node 的内置模块


/**
 * 一个正常的class
 * 
 * 不得不说, TS 使用起来真是舒服,各种该有的东西都替你考虑到了
 * 很舒心
 */
export class NodeModuleTester {
  public static readonly STATIC_VAR = 'STATIC';   // 测试static变量

  constructor(                                    // 测试构造方法
    private readonly f1: string,
    private readonly f2: number) {

  }

  public static testPath() {                      // 测试静态方法
    const curdir = './';

    console.log(path.resolve(curdir));
  }

}
复制代码

由于需要使用对应的 class,所以 main.ts 内容变成了这样:

import {NodeModuleTester} from './core/utils';

/**
 * main 入口
 * 
 * 测试!
 */
function main() {
  const tester = new NodeModuleTester("s1", 1);

  console.log(NodeModuleTester.STATIC_VAR);

  console.log(NodeModuleTester.testPath());
}

main();
复制代码

运行 由于 Node 是不认识 ts 的,我们的 ts 代码需要先转译成 js 代码。

不过别担心,我们使用的是微软的产品,一切都不是问题(意思就是:微软设计的东西,既有品味,又是异常简单好用,历来如此)。

我们只需要 cd src/ && tsc && node main.js 即可,简直不要太简单。如果还嫌麻烦,我们可以写到 npm script 中去,如下:

{
  "name": "src",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "runmain": "./node_modules/.bin/tsc && node main.js"   // 就是这个脚本!
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^9.4.6",
    "typescript": "^2.7.2"
  }
}

复制代码

然后我们只需要cd src/ && npm run runmain即可,更加地简单。

我的感悟

TypeScript 代码,既美观又优雅,加上微软强大的工程能力(造工具的能力),Node.js + TypeScript 几乎是一对完美的组合。

  • 有人可能比较担忧有的库没有对应 d.ts 。其实这完全不用担心,常用的库要么自带 d.ts (侧面验证了 TS已经越来越被大家接受),要么社区已经有维护好的 d.ts (@types下面的库),实在没办法,自己写 d.ts 也不过是分分钟的事情,并没有什么难度。