likes
comments
collection
share

TypeScript增量编译

作者站长头像
站长
· 阅读数 1759

我们在使用Node.js开发服务端时通常会使用TypeScript来开发大型项目,但是使用ts-node进行全量编译时经常遇到编译速度慢的问题,通常是修改一行代码编译两分钟。这时我们需要使用增量编译来优化编译速度,及其他的文件在项目启动时进行全量编译,开发时修改了哪个TS文件就编译成对应的JS文件。

2024/10/05更新:现在可以直接使用tsx工具对项目进行增量编译,在build时直接使用tsc打包即可

在dev启动前先运行一个ts-node来进行其他文件的修改(这段可以去掉),后使用tsx启动并监听项目

  "dev": "ts-node ./scripts/dev &&cross-env ENV=development tsx watch --include \"./src/**/*\" --clear-screen=false ./src/index.ts",

开发环境

1.修改tscon.json文件

{
  "compilerOptions": {
    "watch": true
  }
}

在ts配置中开启watch监听rootDir路径下的全部ts文件(文章末尾会有我的tsconfig.json)

2.编写程序

编写dev.js作为项目开发启动文件,封装Node.js自带方法来移动文件夹来复制如public文件夹、.env文件,启动tsc增量编译,监听tsc运行结果首次运行成功后开始使用shell来运行编译好的dist文件夹

整个demo我会在文章底部放gitee链接。

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

const clearDir = require('./modules/clearDir');//删除整个文件夹
const copyDir = require('./modules/copyDir');//复制文件夹
const countFile = require('./modules/countFile');//计算文件夹内文件的个数


clearDir('dist'); //清空dist
fs.mkdirSync('dist') //创建dist
copyDir('public', 'dist/public'); //复制public
fs.writeFileSync('dist/.env.development', fs.readFileSync('.env.development').toString()) //复制环境变量文件

// 开始执行tsc
const shell = require('shelljs');
const tsCount = countFile(path.join(__dirname, '../src')) //获取ts文件个数实时对比JS
const _tsc = shell.exec('tsc', {
    async: true
});
// 实时对比TS和JS的个数
new Promise((resolve, reject) => {
    _tsc.stdout.on('data', function (data) {
        let src = path.join(__dirname, '../dist/src');
        if (fs.existsSync(src)) {
            let timer = setInterval(() => {
                let jsCount = countFile('./dist/src')
                if (jsCount == tsCount) {
                    clearInterval(timer)
                    resolve()
                }
            }, 50);
        }
    });
}).then(() => {
    shell.exec('cross-env ENV=development nodemon --watch ./dist ./dist/src/index.js', {
        async: true
    });
})

我在这里面进行了dist文件夹的清空和public文件夹的复制,以及环境变量文件的迁移

整体思路:

初始化所需的静态文件夹,开始tsc的运行,同时监听源代码中的ts文件数量和dist中的js文件数量是否一直,一直则说明tsc首次编译结束。在src文件夹全部打包后开始使用nodemon运行dist文件夹,这样就只需要运行对应的js就可以了,大大加快了热更新速度。

很多同学在使用ts开发时使用到了ts路径别名,使用了module-alias插件来解决,但是dist下package.json 需要额外修改,具体在node.js中使用路径别名可以参考这篇文章TypeScript中使用类型别名

打包

const fs = require('fs');
const shell = require('shelljs');
const path = require('path');

const clearDir = require('./modules/clearDir')
const copyDir = require('./modules/copyDir');
const countFile = require('./modules/countFile');

clearDir('dist'); //清空dist
fs.mkdirSync('dist')
const _tsc = shell.exec('tsc', {
    async: true
});
copyDir('public', 'dist/public'); //复制public
fs.writeFileSync('dist/package.json', fs.readFileSync('package.json').toString())
fs.writeFileSync('dist/yarn.lock', fs.readFileSync('yarn.lock').toString())
fs.writeFileSync('dist/.env.production', fs.readFileSync('.env.production').toString())

const tsCount = countFile(path.join(__dirname, '../src')) //获取ts文件个数实时对比JS

new Promise((resolve, reject) => {
    _tsc.stdout.on('data', function (data) {
        let src = path.join(__dirname, '../dist/src');
        if (fs.existsSync(src)) {
            let timer = setInterval(() => {
                let jsCount = countFile('./dist/src');
                if (jsCount == tsCount) {
                    clearInterval(timer)
                    resolve()
                }
            }, 50);
        }
    });
}).then(() => {
    console.log(`打包完成,SRC下共 ${tsCount} 个文件`);
    shell.exit(1)
})

原理和开发类似,只不过移动的文件夹不同,并且在tsc结束后可以直接退出

Demo地址

一个Koa+TypeScript的模板,ORM使用Sequelize,TS添加了增量编译以及类型别名,Koa也基本调试好,自动引入Router以及配置了静态文件

基本上可以Koa+TS下载即用,运行命令在Readme.md中

git clone https://gitee.com/awebcoder/koa-ts.git

tsconfig.json

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "target": "ES2015",
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./",
    "moduleResolution": "node",
    //变量和函数参数未使用警告
    // "noUnusedLocals": true,
    // "noUnusedParameters": true,
    "removeComments": true, //取消注释
    "strict": true,
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"]
    },
    "skipLibCheck": true,
    "esModuleInterop": true,
    "noImplicitAny": true, // 不允许隐式的 any 类型
    "watch": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "**/*.d.ts"]
}
评论
请登录