TypeScript增量编译
我们在使用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结束后可以直接退出
一个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"]
}