配置具有公共依赖项的 TypeScript 项目以构建多个纯 JavaScript 输出文件
Configure a TypeScript project with common dependencies to build multiple plain JavaScript output files
我正在写 some scripts for Bot Land。 Bot Land 是一款实时战略游戏,您无需使用鼠标和键盘控制您的单位,而是编写代码通过 API 控制您的机器人,然后您的机器人与其他机器人战斗。如果您熟悉 SC2 中的单位,您可以创建类似于闪烁追猎者、攻城坦克、医疗兵和雷兽的机器人。 (对于软件工程师来说,这是一个非常有趣的游戏,但这不在本题的讨论范围内。)
Bot 控制具有三个级别,其复杂性不断增加:默认 AI、类似于 Scratch 的编程语言和称为 BotLandScript 的精简集 JavaScript。尽管 BotLandScript 的内置编辑器是合理的,但您必须将所有代码作为 一个文件 上传,并在任何地方使用全局顶级函数。当然,如果您的代码开始变长并且不同的机器人共享相同的功能,这会在一段时间后开始变得痛苦。
为了方便为多个机器人编写代码,减少在纯 JS 编码时出现意外错误的机会,并增加我击败其他玩家的机会,我设置了 above TypeScript project 以提供一个公共库作为我每个机器人的代码。当前目录结构大致如下所示:
lib/
bot.land.d.ts
common.ts
BlinkStalker/
BlinkStalker.ts
tsconfig.json
Artillery/
Artillery.ts
tsconfig.json
SmartMelee/
SmartMelee.ts
tsconfig.json
lib
是机器人之间共享的通用代码,并为(非 TS)Bot Land API 提供 TypeScript 定义。然后每个机器人都有自己的文件夹,一个文件包含机器人代码,另一个文件是样板 tsconfig.json
:
{
"compilerOptions": {
"target": "es3",
"module": "none",
"sourceMap": false,
"outFile": "bot.js"
},
"files": [
"MissileKite.ts"
],
"include": [
"../lib/**/*"
]
}
当构建每个 tsconfig.json
时,它会创建一个相应的 bot.js
,其中包含来自机器人本身的转译代码以及 all common.js
。由于以下几个原因,此设置不是最佳选择:它需要大量重复的样板,难以添加新机器人,为每个机器人包含大量不必要的代码,并且需要单独构建每个机器人。
但是,基于 ,似乎没有一种简单的方法可以完成我想做的事情。特别是,使用新的 tsc -b
选项和引用不起作用,因为这需要对代码进行模块化,而 Bot Land 需要一个包含在顶层定义的所有函数的文件。
尽可能多地实现以下目标的最佳方法是什么?
- 添加新机器人不需要新的样板文件(例如每个机器人不需要
tsconfig.json
)
- 对常用函数使用
import
以避免输出未使用的代码,但是...
- 仍以 Bot Land 的特定格式将所有功能输出为一个文件
- 生成多个输出文件的单个构建步骤,每个机器人一个
- 奖励:将构建过程与 VS Code 集成。当前有一个相应的样板
tasks.json
用于构建每个子项目。
我隐约猜测除了 tsc
之外,答案可能还涉及 Grunt 之类的东西,但我对此了解不多,无法确定。
您实际上可以使用项目引用。按照这些步骤获得与原始文件相同的结果,所有函数都在一个文件的顶层。但是,我找不到在机器人中只导入所需功能的解决方案。也就是说,不使用导入和导出。
在你的 tsconfig.json 根部
{
"files": [],
"references": [
{ "path": "./lib" }
{ "path": "./AggroMiner" }
{ "path": "./ArtilleryMicro" }
{ "path": "./MissileKite" }
{ "path": "./SmartMelee" }
{ "path": "./ZapKite" }
]
}
接下来,在你的 lib 文件夹中,像这样添加一个 tsconfig.json
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"composite": true,
"rootDir": ".",
"outFile": "../build/lib.js",
"target": "es3",
"removeComments": true,
"sourceMap": false,
},
"files": [
"data.ts",
"movement.ts",
"utils.ts"
]
}
我们需要在 data.ts、movement.ts 和 utils.ts 中进行一些调整,以便 ts 不会因编译错误而困扰我们。
data.ts
/// <reference path="./bot.land.d.ts"/>
(...)
movement.ts
/// <reference path="./data.ts"/>
/// <reference path="./utils.ts"/>
(...)
utils.ts
/// <reference path="./bot.land.d.ts"/>
(...)
接下来,我们在根添加base.json(机器人的tsconfig.json会扩展它)。
base.json
{
"compilerOptions": {
"declaration": true,
"composite": true,
"rootDir": ".",
"target": "es3",
"removeComments": true,
"sourceMap": false,
}
}
和机器人的 tsconfig.json(根据机器人进行调整)
{
"extends": "../base",
"compilerOptions": {
"outFile": "../build/AggroMiner.js",
},
"files": [
"AggroMiner.ts"
],
"references": [
{ "path": "../lib", "prepend": true } //note the prepend: true
]
}
就是这样。现在只是 运行
tsc -b
这里是我attempt回答你的要求。
值得注意的文件:
src/tsconfig-botland.json
保存任何 bot.land 脚本的设置(包括我移至 types/bot-land/index.d.ts
的自定义声明)。您可以更改我使用的 strict
设置。
src/tsconfig.json
包含对所有机器人的引用。这是您要添加另一个机器人脚本时要编辑的文件
一个机器人脚本至少包含两个文件:一个极简 tsconfig.json
和一个或多个 .ts
脚本文件。
例如src/AggroMiner/tsconfig.json
:
{
"extends": "../tsconfig-botland",
"compilerOptions": {
"outFile": "../../build/AggroMiner.js"
},
"files": ["index.ts"],
"include": ["**/*.ts", "../lib/**/*.ts"]
}
在大多数情况下,要启动新的机器人脚本,您应该:
- 将任何 bot 文件夹(即
src/AggroMiner
)复制到 src
下的新文件夹
- 编辑
src/<newBotFolder>/tsconfig.json
以使用您的机器人名称编辑 outFile
- 编辑
src/tsconfig.json
并添加对 src/<newBotFolder>
的引用
已设置以下 npm
/yarn
脚本:
build
构建所有机器人
build-clean
在 运行 之前清除 build
文件夹 build
format
到 运行 在 src
下的所有 .ts
文件上更漂亮
lint
到 运行 对所有机器人脚本进行 tslint 检查
现在运行确定您的要求:
- 添加新机器人不需要新的样板文件(例如每个机器人不需要 tsconfig.json)
要实现这一点,需要创建一些脚本来枚举您的机器人 folder/scripts... 并为每个机器人设置相关的 tsconfig.json
和 运行 tsc
。除非绝对必要,否则最小设置(如上所述)可能就足够了。
- 对常用函数使用 import 以避免输出未使用的代码,但是...
首先,请注意,如果您开始使用任何模块 export
/import
语句,您将需要额外的第 3 方来打包/treeshake 以实现单个文件输出。根据我收集到的 Bot.land,您的脚本 运行 在服务器上。除非 deadcode 对你的机器人性能有影响,否则我真的不会打扰。
- 仍以 Bot Land 的特定格式将所有功能输出为一个文件
完成。
- 生成多个输出文件的单个构建步骤,每个机器人一个
完成。
- 奖励:将构建过程与 VS Code 集成。当前有一个相应的样板 tasks.json 用于构建每个子项目。
npm
脚本应该出现在 vsc 的任务列表中(至少在我的任务列表中是这样),这样就不需要 tasks.json
。
我正在写 some scripts for Bot Land。 Bot Land 是一款实时战略游戏,您无需使用鼠标和键盘控制您的单位,而是编写代码通过 API 控制您的机器人,然后您的机器人与其他机器人战斗。如果您熟悉 SC2 中的单位,您可以创建类似于闪烁追猎者、攻城坦克、医疗兵和雷兽的机器人。 (对于软件工程师来说,这是一个非常有趣的游戏,但这不在本题的讨论范围内。)
Bot 控制具有三个级别,其复杂性不断增加:默认 AI、类似于 Scratch 的编程语言和称为 BotLandScript 的精简集 JavaScript。尽管 BotLandScript 的内置编辑器是合理的,但您必须将所有代码作为 一个文件 上传,并在任何地方使用全局顶级函数。当然,如果您的代码开始变长并且不同的机器人共享相同的功能,这会在一段时间后开始变得痛苦。
为了方便为多个机器人编写代码,减少在纯 JS 编码时出现意外错误的机会,并增加我击败其他玩家的机会,我设置了 above TypeScript project 以提供一个公共库作为我每个机器人的代码。当前目录结构大致如下所示:
lib/
bot.land.d.ts
common.ts
BlinkStalker/
BlinkStalker.ts
tsconfig.json
Artillery/
Artillery.ts
tsconfig.json
SmartMelee/
SmartMelee.ts
tsconfig.json
lib
是机器人之间共享的通用代码,并为(非 TS)Bot Land API 提供 TypeScript 定义。然后每个机器人都有自己的文件夹,一个文件包含机器人代码,另一个文件是样板 tsconfig.json
:
{
"compilerOptions": {
"target": "es3",
"module": "none",
"sourceMap": false,
"outFile": "bot.js"
},
"files": [
"MissileKite.ts"
],
"include": [
"../lib/**/*"
]
}
当构建每个 tsconfig.json
时,它会创建一个相应的 bot.js
,其中包含来自机器人本身的转译代码以及 all common.js
。由于以下几个原因,此设置不是最佳选择:它需要大量重复的样板,难以添加新机器人,为每个机器人包含大量不必要的代码,并且需要单独构建每个机器人。
但是,基于 tsc -b
选项和引用不起作用,因为这需要对代码进行模块化,而 Bot Land 需要一个包含在顶层定义的所有函数的文件。
尽可能多地实现以下目标的最佳方法是什么?
- 添加新机器人不需要新的样板文件(例如每个机器人不需要
tsconfig.json
) - 对常用函数使用
import
以避免输出未使用的代码,但是... - 仍以 Bot Land 的特定格式将所有功能输出为一个文件
- 生成多个输出文件的单个构建步骤,每个机器人一个
- 奖励:将构建过程与 VS Code 集成。当前有一个相应的样板
tasks.json
用于构建每个子项目。
我隐约猜测除了 tsc
之外,答案可能还涉及 Grunt 之类的东西,但我对此了解不多,无法确定。
您实际上可以使用项目引用。按照这些步骤获得与原始文件相同的结果,所有函数都在一个文件的顶层。但是,我找不到在机器人中只导入所需功能的解决方案。也就是说,不使用导入和导出。
在你的 tsconfig.json 根部
{
"files": [],
"references": [
{ "path": "./lib" }
{ "path": "./AggroMiner" }
{ "path": "./ArtilleryMicro" }
{ "path": "./MissileKite" }
{ "path": "./SmartMelee" }
{ "path": "./ZapKite" }
]
}
接下来,在你的 lib 文件夹中,像这样添加一个 tsconfig.json
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"composite": true,
"rootDir": ".",
"outFile": "../build/lib.js",
"target": "es3",
"removeComments": true,
"sourceMap": false,
},
"files": [
"data.ts",
"movement.ts",
"utils.ts"
]
}
我们需要在 data.ts、movement.ts 和 utils.ts 中进行一些调整,以便 ts 不会因编译错误而困扰我们。
data.ts
/// <reference path="./bot.land.d.ts"/>
(...)
movement.ts
/// <reference path="./data.ts"/>
/// <reference path="./utils.ts"/>
(...)
utils.ts
/// <reference path="./bot.land.d.ts"/>
(...)
接下来,我们在根添加base.json(机器人的tsconfig.json会扩展它)。
base.json
{
"compilerOptions": {
"declaration": true,
"composite": true,
"rootDir": ".",
"target": "es3",
"removeComments": true,
"sourceMap": false,
}
}
和机器人的 tsconfig.json(根据机器人进行调整)
{
"extends": "../base",
"compilerOptions": {
"outFile": "../build/AggroMiner.js",
},
"files": [
"AggroMiner.ts"
],
"references": [
{ "path": "../lib", "prepend": true } //note the prepend: true
]
}
就是这样。现在只是 运行
tsc -b
这里是我attempt回答你的要求。
值得注意的文件:
src/tsconfig-botland.json
保存任何 bot.land 脚本的设置(包括我移至types/bot-land/index.d.ts
的自定义声明)。您可以更改我使用的strict
设置。src/tsconfig.json
包含对所有机器人的引用。这是您要添加另一个机器人脚本时要编辑的文件
一个机器人脚本至少包含两个文件:一个极简 tsconfig.json
和一个或多个 .ts
脚本文件。
例如src/AggroMiner/tsconfig.json
:
{
"extends": "../tsconfig-botland",
"compilerOptions": {
"outFile": "../../build/AggroMiner.js"
},
"files": ["index.ts"],
"include": ["**/*.ts", "../lib/**/*.ts"]
}
在大多数情况下,要启动新的机器人脚本,您应该:
- 将任何 bot 文件夹(即
src/AggroMiner
)复制到src
下的新文件夹
- 编辑
src/<newBotFolder>/tsconfig.json
以使用您的机器人名称编辑outFile
- 编辑
src/tsconfig.json
并添加对src/<newBotFolder>
的引用
已设置以下 npm
/yarn
脚本:
build
构建所有机器人build-clean
在 运行 之前清除build
文件夹build
format
到 运行 在src
下的所有 lint
到 运行 对所有机器人脚本进行 tslint 检查
.ts
文件上更漂亮
现在运行确定您的要求:
- 添加新机器人不需要新的样板文件(例如每个机器人不需要 tsconfig.json)
要实现这一点,需要创建一些脚本来枚举您的机器人 folder/scripts... 并为每个机器人设置相关的 tsconfig.json
和 运行 tsc
。除非绝对必要,否则最小设置(如上所述)可能就足够了。
- 对常用函数使用 import 以避免输出未使用的代码,但是...
首先,请注意,如果您开始使用任何模块 export
/import
语句,您将需要额外的第 3 方来打包/treeshake 以实现单个文件输出。根据我收集到的 Bot.land,您的脚本 运行 在服务器上。除非 deadcode 对你的机器人性能有影响,否则我真的不会打扰。
- 仍以 Bot Land 的特定格式将所有功能输出为一个文件
完成。
- 生成多个输出文件的单个构建步骤,每个机器人一个
完成。
- 奖励:将构建过程与 VS Code 集成。当前有一个相应的样板 tasks.json 用于构建每个子项目。
npm
脚本应该出现在 vsc 的任务列表中(至少在我的任务列表中是这样),这样就不需要 tasks.json
。