nodejs项目升级为ts

前言

最近把之前自用的一个小型nodejs框架(koa2+mongo)升级为了ts,在此记录一下大致步骤。

安装typescript

直接使用npm 安装

npm i -S -D typescript

建议不要只安装到全局,避免不同机器上的typescript版本不一致。
安装完之后,我们新建一个tsconfig.json(或者tsc init),这是我的内容:

{
  "compilerOptions": {
    // "incremental": true,                   /* 增量编译 提高编译速度*/
    "target": "ES2017",                       /* 编译目标ES版本*/
    "module": "commonjs",                     /* 编译目标模块系统*/
    // "lib": [],                             /* 编译过程中需要引入的库文件列表*/
    "declaration": true,                      /* 编译时创建声明文件 */
    "outDir": "dist",                         /* ts编译输出目录 */
    "baseUrl": "src",
    "paths": {
        "@/*": ["*"],
    },
    // "importHelpers": true,                 /* 从tslib导入辅助工具函数(如__importDefault)*/
    "strict": false,                           /* 严格模式开关 等价于noImplicitAny、strictNullChecks、strictFunctionTypes、strictBindCallApply等设置true */
    "noImplicitAny": false,
    "noUnusedLocals": false,                   /* 未使用局部变量报错*/
    "noUnusedParameters": false,               /* 未使用参数报错*/
    "noImplicitReturns": true,                /* 有代码路径没有返回值时报错*/
    "noFallthroughCasesInSwitch": true,       /* 不允许switch的case语句贯穿*/
    "moduleResolution": "node",               /* 模块解析策略 */
    "typeRoots": [                            /* 要包含的类型声明文件路径列表*/
      "./typings",
      "./node_modules/@types"
      ],
    "allowSyntheticDefaultImports": true,    /* 允许从没有设置默认导出的模块中默认导入,仅用于提示,不影响编译结果*/
    "esModuleInterop": true                  /* 允许编译生成文件时,在代码中注入工具类(__importDefault、__importStar)对ESM与commonjs混用情况做兼容处理*/

  },
  "include": [                                /* 需要编译的文件 */
    "src/**/*.ts",
    "typings/**/*.ts"
  ],
  "exclude": [                                /* 编译需要排除的文件 */
    "node_modules/**"
  ],
}
  

集成eslint代码规范

其实ts最早都是使用tslint,但2019开始ts官方决定投奔eslint,嗯,所以我们肯定也用eslint了。

1.安装依赖

首先安装eslint以及ts的parser、plugin:

npm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin -D

说白了,就是eslint需要配置ts的parser、以及ts的规则,这是我的.eslintrc.js文件内容:

module.exports = {
    'parser':'@typescript-eslint/parser',
    'extends': ['standard', 'plugin:@typescript-eslint/recommended'],
    'env': {'node': true},
    'rules':{
        '@typescript-eslint/ban-ts-ignore': 0
    }
}

extends里面很明显多了一个standard,这是因为@typescript-eslint/recommended的规则并不完善,所以我们还需要使用eslint的standard规则,安装以下依赖:

npm i eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard -D

除了eslint-config-standard,后面几个都是standard的依赖
rules是用来覆盖规则的,我这里加了一个ban-ts-ignore,因为我有的地方要写ts-ignore,不加他就报错了

都配置好后,我们再来package.json的scripts中追加两行命令:

"lint": "eslint --ext .js --ext .ts src/",
"lint-fix": "eslint --fix --ext .js --ext .ts src/",

lint用来检测代码格式问题,lint-fix用来自动修复代码格式

2.配置vscode

ts的标配,毫无疑问是vscode。
vscode中需要安装eslint插件(插件搜索安装即可),安装完成之后 首选项-> 设置 -> 扩展 -> eslint,我们直接点击 在settings.json 中编辑 ,打开编辑文件进行编辑,这是我的配置文件(备注中有追加说明):

{
    "workbench.colorTheme": "One Dark Pro",
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true    // 保存文件时,自动eslint修复格式
    },
    "eslint.enable": true,  // 开启eslint
    "eslint.options": {
        "extensions": [ // eslint检测的文件格式
            ".js",
            ".ts",
            ".tsx",
        ],
    },
    "eslint.validate": [    // eslint检测的语法
        "javascript",
        "javascriptreact",
        "typescript",
        "typescriptreact",
    ]
}

这里需要说明的是,eslint插件2.0.4开始,保存时自动修复文件是通过 editor.codeActionsOnSave 进行配置了,以前是 "eslint.autoFixOnSave": true 。
描述里还说只要在eslint中正确配置了ts,就不需要在eslint.validate中配置了,不过我都不管了,还是统统加上了。

源码调整

这部分就略繁琐了,需要把原代码全部修改成ts,让我们一步步来

1.修改文件后缀

把原来的js文件全部改成ts,我这里是直接写了段node代码来干这个事情:

const fs = require('fs')
const path = require('path')

function renameFile (dir) {
  fs.access(dir, function (err) {
    if (err) {
      console.log('目录不存在')
    }
    _rename(dir)
  })

  function _rename (dir) {
    fs.readdir(dir, function (err, paths) {
      if (err) {
        console.log(err)
      } else {
        paths.forEach(function (curPath) {
          console.log(`查找到${curPath}`)
          const _src = dir + '/' + curPath
          const _dist = dir + '/' + curPath.replace('.js', '.ts')
          fs.stat(_src, function (err, stat) {
            if (err) {
              console.log(err)
            } else {
              // 判断是文件还是目录
              if (stat.isFile()) {
                if (curPath.endsWith('.js')) {
                  fs.rename(_src, _dist, function (err) {
                    if (err) {
                      console.log(err)
                    } else {
                      console.log(`${_src} ==> ${_dist}`)
                    }
                  })
                }
              } else if (stat.isDirectory()) {
                // 当是目录是,递归复制
                _rename(_src)
              }
            }
          })
        })
      }
    })
  }
}

renameFile(path.join(__dirname, 'src'))

跑完之后把src目录下面的js文件全部改成ts文件

2.修改代码

主要是原来的require全部改成es的import,这里我是写了一个正则,搜索替换的:

const ([^ ]+) = require\(([^)]+)\)  // from
import $1 from $2   // to

你如果对自己代码有自信,也可以在上一步的node脚本中,读取文件内容,然后替换掉。

关于import这一块就比较有意思了,我们来看一段对比:

// 编译前:
import path from 'path'
import fsTool from '@/util/fs-tool'

// 编译后:
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const fs_tool_1 = __importDefault(require("@/util/fs-tool"));

显然,ts追加了一个 __importDefault函数,这就是ts的esModuleInterop编译选项的作用,对es和commonjs的模块做兼容处理:

  • ts编译的时候,给当前模块插入一个属性: __esModule: true
  • 导入的时候先判断该模块是否有__esModule
  • 如果为true,判定为es模块,直接导出
  • 如果为false,判定为commonjs模块,作为default导出:{ default: mod }

    参考文章里认为这里会有一个陷阱,所以需要打开allowSyntheticDefaultImports编译选项。的确,如果一个模块是用ts写的,或者自己就是追加了__esModule属性,但同时exports又没有default,最终 __importDefault导出来的会是一个空值。
    但我认为自己追加__esModule属性不太可能,用ts写的没有export default但又import default时,ts是会报错的,所以我认为这种情况可以忽略。

调试

1.chrome中调试

在package.json的scripts中追加以下命令:

"dev": "nodemon --watch src -e ts,tsx,js,json --exec node --inspect -r ts-node/register ./src/app.ts",

node调试的命令是 --inspect选项,nodemon用来监测到文件改动时自动重启,ts-node用来调试ts代码

以上,就能直接在chrome的开发者工具中调试了,如果有不清楚的可以自己去搜索node --inspect,这里就不做贴图说明了

vscode中调试

.vscode/launch.json填入以下内容:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Node: Nodemon",
            "processId": "${command:PickProcess}",
            "restart": true,
            "protocol": "inspector",
        }
    ]
}

打开debug面板,选择刚才设置的Node: Nodemon,点击调试并运行,即可开始在vscode中调试(需要先npm run dev把项目运行起来):

说明

在查阅过的资料中,京东社交电商部的这篇文章帮助最大:Node.js项目TypeScript改造指南,非常感谢!
本文也是在此基础上有部分更新以及补充。

原文地址:https://www.cnblogs.com/thyong/p/12182579.html

时间: 2024-10-12 18:03:40

nodejs项目升级为ts的相关文章

webstorm/...开发 NodeJS 项目

前提: 已安装好 webstorm/IDEA 2016.3 & 2017.1 (见 文 IDEA开发Java 相关 --- 1 IDEA安装 ...) 要用 IDEA 开发 NodeJS项目(web/JS)项目,首先需要: 1. 自行下载 Node.js 并安装,下载网址:https://nodejs.org/en/download/:或者 https://nodejs.org/en/: 测试: cmd-> node -v  或者 node, 未出现错误,如下,则表明已安装完好.   其次,

将arcEngine9.3和dev9.2.4开发的项目升级成arcObject10.2和dev15.1.3过程中遇到的问题和解决

好久没碰.net了,arcgis更是感觉都忘干净了,今天将arcEngine9.3和dev9.2.4开发的一个项目升级成arcObject10.2和dev15.1.3过程中遇到了一系问题,留个笔记,留个回忆: 一,双击打开项目: 这个时候发现,一直在upgrade和ok这两步循环,上面的英文描述原因已经说得很明白了,就是需要.NET framework4.0+以上的版本,而这个项目我看了一下.NET framework3.5版本是3.5 换成4.0以上就行,如下图: 然后再回到upgrade界面

MyBatis的项目升级

第二节 MyBatis的项目升级 2016年3月2日 星期三 09:13 1.namespace命名空间 针对于SQLID的方式: 持久化类的全路径,例如 com.shxt.model.User 针对于接口的方式: 取的是针对于数据库操作的定义接口的那个全路径: com.shxt.mapper[dao].UserMapper 2.日志文件的配置 使用的是log4j.properties 针对于日志文件有一个级别: TRACE DEBUG INFO WARNING ERROR 扩展作业:如果使用J

【Nodejs项目手记】Nodejs中使用图片验证码,captchapng模块可以解决Nodejs图片验证码

Nodejs项目,在做图片验证码的时候遇到了难题.Nodejs没有图片库,以后会有,但是现在没有. 网络上搜索一圈,有几个解决方案: 1.采用第三方验证码程序,有的时候,项目可能不允许: 2.使用Java或者PHP生成图片,Nodejs调用,中间采用Redies共享: 这两种方式都不太理想,好在终于找到了可以支持Nodejs图片验证码的一个库,虽然只支持数字,但是也还不错.原理是使用Base64的图片编码方式. 这个库的Gighub地址是:https://github.com/GeorgeCha

学习笔记-使用cmd命令行创建nodejs项目

使用cmd命令行创建nodejs项目 1)在DOS下cd 进入到你想要创建项目的路径. 2)mkdir sing (创建一个sing文件夹) 3)cd sing 4) npm init (初始化工程) 此时需要填写一些项目信息,你可以根据情况填写,当然也可以一路回车. 5)安装第三方包(后面程序会直接调用包的模块) 说明:由于http模块.fs模块都是内置的包,因此不需要额外添加. 这里安装cheerio包,和request包. 在dos中,cd进入sing文件夹,然后npm install c

如何编写package.json配置NodeJS项目的模块声明

在NodeJS项目中,用package.json文件来声明项目中使用的模块,这样在新的环境部署时,只要在package.json文件所在的目录执行 npm install 命令即可安装所需要的模块. package.json文件中可配置的项有:名称(name).应用描述(description).版本号(version).应用的配置项(config).作者(author).资源仓库地址(repository).授权方式(licenses).目录(directories).应用入口文件(main)

一个简单的nodejs项目(cat-names)分析

https://github.com/sindresorhus/cat-names 一个非常简单的nodejs项目,用来方便的获取猫猫的名字: 安装: npm install --save cat-names 用法: const catNames = require('cat-names'); //获取随机猫名 catNames.random(); // => 'Max' index.js源码 非常简单,不解释 'use strict'; var uniqueRandomArray = requ

Unity5.x 项目升级过程中常见问题解决方案总结

最近整理Unity4.x 项目升级Unity5.0 过程中出现的各种常见问题,与大家共享. 1:Unity4.x 项目中3D模型其材质丢失,成为"白模"?      解决方案:手工重新赋值材质贴图. 2:Unity4.x 项目中的NavMesh 升级报错?     "NavMesh asset format has changed. Please rebake the NavMesh data." ?     解决方案:按照字面含义,重新对静态物体进行烘焙即可. 3

如何在NodeJS项目中优雅的使用ES6

如何在NodeJS项目中优雅的使用ES6 NodeJs最近的版本都开始支持ES6(ES2015)的新特性了,设置已经支持了async/await这样的更高级的特性.只是在使用的时候需要在node后面加上参数:--harmony.但是,即使如此node也还是没有支持全部的ES6特性.所以这个时候就需要用到Babel了. 现在开始Babel 在开始使用Babel之前,假设 1. 你已经安装了nodejs,并且已经熟悉了Js. 2. 你也可以使用npm安装各种依赖包. 3. 而且你也对ES6(后来改为