koa开发实践1:基于 gulp 搭建 typescript 自动构建环境

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: koa开发实践1:基于 gulp 搭建 typescript 自动构建环境

nodeJS server-side-developkoa开发实践1:基于 gulp 搭建 ts 自动构建环境


1. 目标概述

我们这一节的目标是同过gulp于相关工具构建一个基于 TypeScript 的 koa 项目开发环境,并且希望这个环境能够自动的监听 TypeScritp 源代码的变化,在发生源代码改变时执行自动编译为用于 NodeJS 的 JavaScript 代码,并启动服务。

2. 目录结构的确定

2.1 src 目录

为了方便,我们确定所有基于 TypeScript 编写的 源文件 同意放置在一个名为 src 的目录下,src 是 source(源)的简称,用这个名字放构建前的源代码也是惯例。

2.2 dist 目录

- [src]
     | - logger.ts
     | - app.ts
- gulpfile.ts
- packa.json
- tsconfig.json

dist 目录是 我们构建后生成的 JavaScript 项目的目录,这些文件应当是直接便于 NodeJS 运行的,并且方便将其整体交付到 生产环境进行部署。

3. gulpfile.ts 文件

3.1 什么是 gulpfile

gulpfile 是用于 gulp 运行的文件,一般而言,它的名字为 gulpfile.js,且不可自行改动。gulp 模块为我们提供了一个脚本,它接受一个路径,当这个路径中包含名字为 gulpfile.js 的文件时,将读取该文件中的 JavaScript 源代码以脚本方式运行。

3.2 使用 @esbuild-kit/cjs-loader 工具运行 gulpfile

以往我们使用 gulpfile.js 文件作为 gulp 的 cli 入口,而 gulpfile.ts 是不能直接被 gulp 所识别的,这时我们需要做一个动态转换进行运行,该工具就是 @esbuild-kit/cjs-loader,其原理为:

通过使用 esbuild 按需即时将 ESM 和 TypeScript 转换为 CommonJS

可以通过以下命令进行安装到你的项目中:

npm i @esbuild-kit/cjs-loader
# or yarn
yarn add -D @esbuild-kit/cjs-loader
# ro pnpm
pnpm i @esbuild-kit/cjs-loader -D

我们当然不会对于整个项目使用这种按需即时转换的方式运行,但是这种方式却尤其适合运行单个的文件。以往我们运行 gulpfile 的方式是:

gulp

你只需要在 package.json 中配置 script 字段中配置:

"gulp:build": "gulp"

3.3 编写 gulpfile.ts

// gulpfile.ts
import path from "path";
import ts from "gulp-typescript";
import { src, dest, series } from "gulp";
import { deleteAsync } from "del";
const BASE_DIR = __dirname;
const DIST_DIR = path.join(BASE_DIR, 'dist');
const APP_JS = path.join(DIST_DIR, 'app.js')
// 清除旧文件
async function clearOldFiles(): Promise<void> {
  await deleteAsync(["dist/**/*"]);
  return;
}
// 编译 ts 文件为 js 文件
function buildTypescript(): NodeJS.ReadWriteStream {
  return src("./src/**/*.ts")
    .pipe(
      ts({
        noImplicitAny: false,
        removeComments: false,
        esModuleInterop:true,
        declaration: true,
        target: "es2017",
        module: "commonjs",
        outDir: './dist',
        lib: ["DOM", "ES2015", "ES2016", "ES2017", "ES2018", "ES2022"],
        declarationDir: './dist/types'
      })
    )
    .pipe(dest("./dist"));
}
// 注册默认任务
const build = series([
  clearOldFiles, // 启动时先删除旧文件
  series([
    buildTypescript, // 编译 ts 为 js
  ]),
]);
export default build;

gulp-typescript 模块不会让你的 src 目录下的文件有合适的类型约束,你可以简单地单独建立一个 tsconfig.json 文件,写下相同配置:

{
  "compilerOptions": {
    "target": "es2017",
    "module": "commonjs",
    "rootDir": "./",
    "lib": ["DOM", "ES2015", "ES2016", "ES2017", "ES2018", "ES2022"],
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitAny": false,
    "skipLibCheck": true,
  },
  "include":[
    "./src/**/*"
  ]
}

3.4 配置 script 字段

// package.json
script:{
  // ...
  "ts:build": "gulp --require @esbuild-kit/cjs-loader"
}

4. 编写 koa 的 hello work

4.1 使用日志记录器 logger

什么是日志器——顾名思义就是用于记录日志的该工具。一个日志记录器可以在终端分级别高亮输出日志,也可以将其导出文件进行后续调试,这对于一个项目后期的调试和维护尤其重要。

你可以简单地自己实现一个 logger:

import { green, yellow, red  } from 'jc-color';
function logger(message: string, level: string) {
  const time = new Date().toLocaleString();
  switch (level) {
    case 'info':
      green(`[INFO] [${time}] ${message}`).print();
      break;
    case 'warn':
      yellow(`[WARN] [${time}] ${message}`).print();
      break;
    case 'error':
      red(`[ERROR] [${time}] ${message}`).print();
      break;
    default:
      console.log(message);
  }
}
logger('This is an info message', 'info');
logger('This is a warning message', 'warn');
logger('This is an error message', 'error');

当然如果实现一个基于类的日志器在使用的时候会更让人舒服一些:

import { blue, cyan, yellow, red  } from 'jc-color';
class Logger {
  static debug(message: string) {
    blue(`[DEBUG] [${new Date().toISOString()}] ${message}`).ptint();
  }
  static info(message: string) {
    cyan(`[INFO] [${new Date().toISOString()}] ${message}`).ptint();
  }
  static warn(message: string) {
    yellow(`[WARN] [${new Date().toISOString()}] ${message}`).ptint();
  }
  static error(message: string) {
    red(`[ERROR] [${new Date().toISOString()}] ${message}`).ptint();
  }
}
Logger.debug('This is a debug message');
Logger.info('This is an info message');
Logger.warn('This is a warning message');
Logger.error('This is an error message');

你也可以使用一些线程的日志模块,比如 log4js:

npm i log4js
# or
yarn add log4js
# or
pnpm i log4js
// src/logger.ts
import log4js  from 'log4js'
log4js.configure({  
    appenders: {  
        fileout: { type: "file", filename: "fileout.log" }, 
        datafileout: {
            type: "dateFile", 
            filename: "mylog.log", 
            pattern: ".yyyy-MM-dd hh-mm-ss-SSS"
        },
        consoleout: { type: "console" }, 
    }, 
    categories: {    
        default: { appenders: ["fileout", "consoleout"], level: "debug" },   
        anything: { appenders: ["consoleout"], level: "debug" }
    }
});
export const logger = log4js.getLogger();

4.2 编写应用入口文件 app.ts

在 src 目录下创建 TypeScript 文件 app.ts,如果你喜欢也可以叫做其他的名字,但需要是 ts 后缀。

// src/app.ts
import Koa from 'koa';
import { logger } from './logger.ts
const port = 3000;
function bootstrap() {
  const app = new Koa();
  app.use(async (ctx, next) => {
    await next();
    ctx.response.type = 'text/html';
    ctx.response.body = '<h1>Hello, World!</h1>';
  });
  app.listen(port, ()=>{
    logger.debug(`app started at: http://localhost:${port}`);
  })
}
bootstrap()

5. 再次配置 script 字段

现在我们需要从编译地文件中运行服务器地入口文件,他就是 dist/app.js。你可以在 package.jsonscript 字段中这样配置:

{
  script:{
    // ...
    "start": "node ./dist/app.js",
  }
}

这样你就可以在项目的根目录下使用如下命令启动服务器了:

pnpm run start

在之前我们配置过一个将 src 目录下 TypeScript 源代码编译为 JavaScript 的脚本:

{
  script:{
    // ...
    "ts:build": "gulp --require @esbuild-kit/cjs-loader",
  }
}

因此现在我们需要运行两次命令:

  • 第一次:运行编译命令编译TypeScript项目为JavaScript项目:
pnpm run ts:build
  • 第二次:运行启动命令,启动服务器:
pnpm run start

这似乎太麻烦了,因此我们再加一条命令,这条新命令不干别的,只是按照顺序把上面两个命令都运行一遍:

{
  script:{
    "ts:build": "gulp --require @esbuild-kit/cjs-loader",
    "start": "node ./dist/app.js",
    "dev": "pnpm run ts:build && pnpm run start"
  }
}

6. nodemon 全自动化响应运行

在前一节中我们已经可以使用一个命令就完成整个服务器代码的编译和运行两个过程了。但是在开发中,我们对源代码地改变是频繁的。往往在更改源代码后都想更快地看到最新的效果,这时我们就不得不随之频繁地点开终端,运行命令——哪怕命令已经很简单了,但仍然很麻烦。

为了解决这样一个问题,实现 “一劳永逸” 地运行,我们选哟使用另外一个工具,那就是 nodemon。nodemon 是一个可以用于监视文件变化的模块,可以使用如下方式添加到你的开发依赖中:

npm i nodemon -D
# or
yarn add -D nodemon
# or
pnpm i nodemon -D

现在我们在 package.json 文件中再次对 script 字段进行更改:

{
  //...
  script:{
    // ...
    "ts:build": "gulp --require @esbuild-kit/cjs-loader",
    "start": "node ./dist/app.js",
    "dev": "nodemon -e ts --watch src --exec \"pnpm run ts:build && pnpm run start\""
  }
}

现在,你只需要运行一次dev命令,就可以愉快地进行 TypeScript 开发 Koa 服务器了:

pnpm run dev

7. 小结

本文带大家搭建了一个全自动化编译、运行 由 TypeScript 编写的 koa 服务器,它能够自动的清理 旧有的编译项目,监视 TypeScript 源代码变化,自动编译为 JavaScript 并在编译完成后 自动地启动服务器。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
JavaScript 前端开发 安全
TypeScript的优势与实践:提升JavaScript开发效率
【10月更文挑战第8天】TypeScript的优势与实践:提升JavaScript开发效率
|
1月前
|
JavaScript 前端开发 IDE
深入理解TypeScript:提升JavaScript开发的利器
【10月更文挑战第8天】 深入理解TypeScript:提升JavaScript开发的利器
28 0
|
3月前
|
开发框架 缓存 前端开发
基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用
基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用
|
4月前
|
前端开发 JavaScript 安全
TypeScript在React Hooks中的应用:提升React开发的类型安全与可维护性
【7月更文挑战第17天】TypeScript在React Hooks中的应用极大地提升了React应用的类型安全性和可维护性。通过为状态、依赖项和自定义Hooks指定明确的类型,开发者可以编写更加健壮、易于理解和维护的代码。随着React和TypeScript的不断发展,结合两者的优势将成为构建现代Web应用的标准做法。
|
14天前
|
Web App开发 JavaScript 前端开发
探索Deno:新一代JavaScript/TypeScript运行时环境
【10月更文挑战第25天】Deno 是一个新兴的 JavaScript/TypeScript 运行时环境,由 Node.js 创始人 Ryan Dahl 发起。本文介绍了 Deno 的核心特性,如安全性、现代化、性能和 TypeScript 支持,以及开发技巧和实用工具。Deno 通过解决 Node.js 的设计问题,提供了更好的开发体验,未来有望进一步集成 WebAssembly,拓展其生态系统。
|
4月前
|
JavaScript 前端开发 开发工具
TypeScript的介绍,let age:number = xxx,可以直接看出数据类型,Type由微软开发,可以在任何浏览器和系统中运行,比较适合大型项目,TypeScript的安装
TypeScript的介绍,let age:number = xxx,可以直接看出数据类型,Type由微软开发,可以在任何浏览器和系统中运行,比较适合大型项目,TypeScript的安装
|
1月前
|
JavaScript 前端开发 IDE
利用TypeScript增强JavaScript开发
【10月更文挑战第5天】TypeScript作为JavaScript的超集,通过添加静态类型系统和对ES6+特性的支持,解决了大型项目中常见的类型错误和代码维护难题。本文介绍TypeScript的核心优势,包括静态类型检查、现代JS特性支持及更好的IDE支持,并探讨如何逐步将其集成到现有项目中,提升开发效率和代码质量。通过使用DefinitelyTyped库和装饰器等功能,开发者可以更轻松地编写可靠且可维护的代码。希望本文能帮助你更好地理解和应用TypeScript。
|
1月前
|
传感器 JavaScript 前端开发
深入理解TypeScript:提升JavaScript开发效率
【10月更文挑战第8天】深入理解TypeScript:提升JavaScript开发效率
30 0
|
3月前
|
JavaScript 前端开发 编译器
TypeScript教程(一)在vscode中的配置TypeScript环境
本文是一篇TypeScript入门教程,介绍了在VS Code中配置TypeScript环境的步骤,包括安装Node.js、使用npm安装TypeScript、配置npm镜像源、安装VS Code的TypeScript扩展,以及创建和运行一个简单的TypeScript "Hello World"程序。
TypeScript教程(一)在vscode中的配置TypeScript环境
|
3月前
|
JavaScript 前端开发 安全
[译] 使用 TypeScript 开发 React Hooks
[译] 使用 TypeScript 开发 React Hooks