天天看點

快速搭建一個 TypeScript + Node 服務端開發環境

在 ts + react 系列 中,資料都是本地的

mock

,那麼如何搭建一個真實的

API server

呢?

按照慣例,先搭建一個基于

ts + express

的服務端開發環境:

初始化

express-generator

express-generator:快速建立

Express

應用程式架構。

可以使用

npx

指令(在

Node.js 8.2.0

中可用)運作應用程式生成器。

$ npx express-generator ts-express
           

對于早期的

Node

版本,可将應用程式生成器作為全局

npm

軟體包安裝,然後啟動它。

$ npm install -g express-generator
$ express ts-express
           

typescript

安裝 typescript

$ npm i -D typescript
           

生成配置檔案 tsconfig.json

$ tsc --init
           

工程改造(js2ts)

将工程裡的

.js

檔案 都重命名為

.ts

檔案。

快速搭建一個 TypeScript + Node 服務端開發環境

bin/www

是整個服務端的啟動腳本。

// bin/www
// 修改服務端端口 3000 -> 40001
var port = normalizePort(process.env.PORT || "4001");
           

改完之後,肯定出現了大量報錯,莫慌,我們一起來修改:

Cannot find name ‘require’.

require

未定義,因為缺少聲明檔案

$ npm i --save-dev @types/node @types/express
           

參數類型未定義

express

聲明檔案最終的導出方式是

export =

,它對應的導入方式是

import =

/

import from

/*
 ** node_modules/@types/express/index.d.ts
 */
...
export = e;
           

而我們的導入方式是

require

/*
 ** app.ts
 */
var express = require("express");
           

統一将子產品的導入改為

import from

,并安裝聲明檔案

$ npm i -D @types/http-errors @types/cookie-parser @types/morgan @types/debug
           

app.use

export interface IRouterHandler<T> {
  (...handlers: RequestHandler[]): T;
  (...handlers: RequestHandlerParams[]): T;
}
           

app.use

參數的類型是一個函數重載,但是

error handler

傳入四個參數時,并沒成功定位到

ErrorRequestHandler

類型。是以我們加一個類型斷言

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get("env") === "development" ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render("error");
} as express.ErrorRequestHandler);
           

對象可能為 null

添加類型保護

addr?

function onListening() {
  var addr = server.address();
  var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr?.port;
  debug("Listening on " + bind);
}
           

參數 “val” 隐式具有 “any” 類型

指定

string

類型

function normalizePort(val: string) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}
           

參數 “error” 隐式具有 “any” 類型

指定

any

類型

function onError(error: any) {
  ...
}
           

編譯 ts2js

因為

node

是不可以編譯

ts

檔案的,是以

build

時需要編譯

.ts

.js

  1. 指定輸出目錄
    //  tsconfig.json
    {
      "compilerOptions": {
        "outDir": "./dist"
      }
    }
               
  2. 添加腳本
    {
      "scripts": {
        "build-ts": "tsc"
      }
    }
               

拷貝靜态資源/模版檔案

檔案的拷貝工作通過

shell

腳本實作。

  1. 安裝

    shelljs

    npm i -D shelljs @types/shelljs
               
  2. 在根目錄上建立

    copyStatic.ts

    // copyStatic.ts
    import * as shelljs from "shelljs";
    
    // -R:遞歸
    shelljs.cp("-R", "public", "dist");
    shelljs.cp("-R", "views", "dist");
               
  3. 添加運作腳本
    // package.json
    {
      "script": {
        "copy-static": "ts-node copyStatic.ts"
      }
    }
               

    ts-node

    需要提前安裝
    $ npm i -D ts-node
               

npm run build

添加

build

腳本

// package.json
{
  "script": {
    "build-ts": "tsc",
    "copy-static": "ts-node copyStatic.ts",
    "build": "npm run build-ts && npm run copy-static"
  }
}
           

編譯時,排除

copyStatic.ts

// tsconfig.json
{
  "exclude": ["copyStatic.ts"]
}
           

啟動伺服器

// package.json
{
  "script": {
    "start": "node /dist/bin/server.js"
  }
}
           
$ npm start
           

打開

http://localhost:4001/

,就可以看到

express

頁面了。

watch 監控模式

nodemon

是一個自動重新開機

node

應用的工具,當監聽的檔案或監聽目錄下的檔案發生修改時,自動重新開機應用。

我們修改檔案後,第一步需要重新

build

,第二步需要重新開機服務。

nodemon

讓我們開發時隻需關注代碼即可,不再需要手動重新開機服務。

  1. 安裝

    nodemon

    $ npm i nodemon -D
               
  2. 配置腳本
    // package.json
    {
      "script": {
        "start": "node ./dist/bin/server.js",
        "watch": "nodemon ./dist/bin/server.js"
      }
    }
               

繼續閱讀