在 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
檔案。
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
- 指定輸出目錄
// tsconfig.json { "compilerOptions": { "outDir": "./dist" } }
- 添加腳本
{ "scripts": { "build-ts": "tsc" } }
拷貝靜态資源/模版檔案
檔案的拷貝工作通過
shell
腳本實作。
- 安裝
shelljs
npm i -D shelljs @types/shelljs
- 在根目錄上建立
copyStatic.ts
// copyStatic.ts import * as shelljs from "shelljs"; // -R:遞歸 shelljs.cp("-R", "public", "dist"); shelljs.cp("-R", "views", "dist");
- 添加運作腳本
// 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
讓我們開發時隻需關注代碼即可,不再需要手動重新開機服務。
- 安裝
nodemon
$ npm i nodemon -D
- 配置腳本
// package.json { "script": { "start": "node ./dist/bin/server.js", "watch": "nodemon ./dist/bin/server.js" } }