記錄nodejs使用express搭建一個api服務器程序(2)-優化目錄結構,增加配置文件,個性化build

此文章是我自己用來記錄如何搭建一個以express爲基礎的api服務器框架的過程,並不是什麼新手教程,並不會每一步都寫得非常詳細,如果您要閱讀此文,需要一點nodejs和編寫代碼的基礎知識

文接上篇 鏈接: 地址 https://blog.csdn.net/goodboy31985/article/details/106208989
在上文基礎上,修改和完善api服務器的框架

修改最終的編譯目錄和啓動文件

將tsc命令執行後的輸出目錄改爲項目根目錄下的app/ 文件夾(原爲 dist/),這樣功能更加明確,
並且將項目入口文件從app.ts 改爲 start.ts
修改tsconfig.json中的輸出目錄
在這裏插入圖片描述
在這裏插入圖片描述
同時將通過vscode調試的功能配置文件中的入口文件也修改下
在這裏插入圖片描述
最終項目啓動時,只要運行 node ./app/start.js 即可啓動項目,比較清晰明瞭,此步驟按照個人習慣即可

增加配置文件,方便項目參數配置

之前我們的服務器端口是直接寫在代碼中的,但是這樣靈活性很差,一般會使用一個配置文件,將一些參數寫在配置文件中,項目啓動時直接從配置文件中讀取,這樣項目部署的時候能更加靈活.

增加config.json5文件做完項目的配置文件

這裏,我就增加一個config.json5的配置文件,以後一些可配置的內容,比如數據庫地址,數據庫名稱,密碼等,都可以寫在配置中,可以更加靈活得進行部署
注意 我使用的是json5 格式,因爲他是支持註釋的
在這裏插入圖片描述

//config.json5
{ 
    //服務器設置
    "server": {
        "port": 40000, //端口
    }
}

這裏暫時只配置一個端口,以後有需要可以增加其他內容
使用json5文件進行配置,由於json文件先天的格式優勢,外加可以進行註釋,就能讓配置文件更加清晰和方便

讓vscode認識json5文件

可以下載vscode的擴展 JSON5 syntax,方便我們編寫文件
在這裏插入圖片描述

在程序啓動時讀取配置

配置文件在項目啓動時就應該被讀取,因此,我把讀取配置文件的代碼,寫在項目入口start.ts的最前面,另外將config作爲一個模塊輸出,讓整個項目都可以使用
爲了能夠解析帶有註釋的json5文件,需要安裝json5的包
使用 npm install --save json5 進行安裝
修改start.ts文件,讀取配置

//start.ts

import fs from "fs";
import json5 from "json5";
import path from 'path'

//項目根目錄
export const rootDir = __dirname + "/";

//加載配置文件
//讀取json5文件內容
let jsonFile = fs.readFileSync(path.join(rootDir, "./config.json5")).toString();
//解析爲json文件,並作爲模塊輸出
export let config = json5.parse(jsonFile);

async function main()
{

    console.log(config)
    //ApiServer.GetInstance().Init();
    //await ApiServer.GetInstance().Run();
}

main();

運行一下,看看是否能夠正確讀取到json文件的內容
在這裏插入圖片描述
已經成功輸出了json內容

修改文件結構,項目更加清晰

爲了讓項目的文件結構更加清晰,我將ApiServer文件讓入一個文件夾中,這樣一來,項目的app目錄下就只有start和config兩個文件,其他都在文件夾中,包括以後新增的文件也根據功能劃分到文件中,文件結構更加清晰
注意:一旦文件被移動了位置,所有引用到該文件的地方,都會受到影響,需要進行修改
另外在src中,增加一個public文件夾,放一些靜態文件,比如圖片,音頻文件等,此文件夾中的內容,可以使用express.static(“path”)功能,讓用戶直接獲取到文件
最終的目錄結構如下
在這裏插入圖片描述
start.ts 文件

//start.ts

import fs from "fs";
import json5 from "json5";
import path from 'path'
import { ApiServer } from "./ApiServer/ApiServer";

//項目根目錄
export const rootDir = __dirname + "/";

//加載配置文件
//讀取json5文件內容
let jsonFile = fs.readFileSync(path.join(rootDir, "./config.json5")).toString();
//解析爲json文件,並作爲模塊輸出
export let config = json5.parse(jsonFile);

async function main()
{
    ApiServer.GetInstance().Init();
    await ApiServer.GetInstance().Run();
}

main();

ApiServer.ts 文件

// ApiServer/ApiServer.ts

import express, { Application } from "express"
import { config, rootDir } from "../start";
import path from 'path'



export class ApiServer
{
    //單例
    private static instance: ApiServer = null;
    private constructor()
    {

    }
    public static GetInstance()
    {
        if (ApiServer.instance == null)
        {
            ApiServer.instance = new ApiServer();
        }
        return ApiServer.instance;
    }

    //此類的核心成員
    private app: Application = null;

    //初始化
    Init()
    {
        this.app = express();
        //此處使用config.server.port 這是從配置文件中獲取的內容
        //如果配置文件中有port定義,就使用配置文件中的,如果沒有,則使用默認50000
        let serverPort = config.server.port || 50000;
        let server = this.app.listen(serverPort, () => { console.info(`Example app listening on port ${serverPort}`) })

        //讓express 能夠處理 async/await 中拋出的異常
        const layer = require('express/lib/router/layer');
        Object.defineProperty(layer.prototype, 'handle', {
            enumerable: true,
            get()
            {
                return this.__handle;
            },
            set(fn)
            {
                if (fn.length === 4)
                {
                    this.__handle = fn;
                }
                else
                {
                    this.__handle = (req, res, next) =>
                    {
                        Promise.resolve(fn(req, res, next)).catch(next);
                    }
                }
            }

        });
    }

    Run()
    {

        //測試消息
        this.StartTestResponse();

        //public文件夾下的靜態資源,可以直接進行訪問
        this.app.use(express.static(path.join(rootDir, 'public')));
    }

    //測試消息
    StartTestResponse()
    {
        this.app.all('/api/test', (req, res) =>
        {
            res.writeHead(200, {
                'Content-Type': 'text-plain'
            });
            res.end('Hello World\n' + new Date().toString());
        })
    }

}

此時調試一下程序
服務器已經成功運行,並且端口號爲40000
在這裏插入圖片描述
在這裏插入圖片描述

增加build文件,讓非ts文件也放進build目錄

但是此時還有一個問題,當我們使用tsc命令編譯項目的時候,發現public文件夾 和 config.json5文件,並沒有複製到app文件夾中,tsc命令只是將ts文件編譯爲js並輸出到指定目錄,而忽略其他文件
在這裏插入圖片描述
此時如果我們直接將app文件夾部署到服務器上,必然會出現錯誤
解決方法是 我們可以另外編寫一段代碼,編譯ts文件的同時,將我們需要的非ts文件,複製到對應的位置
我們在項目的根目錄新建一個build.js文件,在裏面編寫複製其他文件的功能
build.js

const fs = require('fs-extra');
const childProcess = require('child_process');


try
{
    // 刪除當前app文件夾中的所有內容
    fs.removeSync('./app/');
    // 複製配置文件到app目錄
    fs.copySync('./src/config.json5', './app/config.json5');
    // 複製public文件夾內容到app目錄
    fs.copySync('./src/public', './app/public');
    // 執行tsc命令 編譯ts文件
    childProcess.exec('tsc');
} catch (err)
{
    console.log(err);
}

此時,我們只要運行 node ./build.js 命令,就可以實現我們需要的功能(先安裝fs-extra包)
在這裏插入圖片描述
文件已經被全部複製到app目錄下了

本節內容主要是讓項目結構更加合理,並且增加了配置文件,可以更爲靈活得進行部署,下節我們將爲此框架增加更多的功能

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章