web-dev-qa-db-fra.com

Configurer un projet TypeScript avec des dépendances communes pour créer plusieurs fichiers de sortie JavaScript simples

J'écris actuellement certains scripts pour Bot Land . Bot Land est un jeu de stratégie en temps réel où au lieu de contrôler vos unités avec une souris et un clavier, vous écrivez du code pour contrôler vos bots via une API, puis vos bots vont combattre les bots des autres. Si vous connaissez les unités de SC2, vous pouvez créer des robots similaires aux harceleurs clignotants, aux chars de siège, aux médecins et aux ultralisks. (C'est un jeu assez amusant pour les ingénieurs logiciels, mais cela sort du cadre de cette question.)

bot land

Le contrôle des bots a trois niveaux de complexité croissante: une IA par défaut, un langage de programmation de type Scratch , et un ensemble réduit de JavaScript appelé BotLandScript. Bien que l'éditeur intégré pour BotLandScript soit raisonnable, vous devez télécharger tout votre code en tant que un seul fichier avec des fonctions globales de premier niveau partout. Naturellement, cela commence à devenir douloureux après un certain temps si votre code commence à devenir long et que des robots différents partagent les mêmes fonctions.

programming environment

Pour faciliter l'écriture de code pour plusieurs robots, réduire le risque d'erreurs involontaires lors du codage en JS nu et augmenter mes chances de battre les autres joueurs, j'ai configuré ci-dessus projet TypeScript pour fournir également une bibliothèque commune comme code pour chacun de mes robots. La structure de répertoire actuelle ressemble approximativement à la suivante:

lib/ 
  bot.land.d.ts
  common.ts
BlinkStalker/
  BlinkStalker.ts
  tsconfig.json
Artillery/
  Artillery.ts
  tsconfig.json
SmartMelee/
  SmartMelee.ts
  tsconfig.json

lib est le code commun qui est partagé entre les bots et fournit des définitions TypeScript pour l'API Bot Land (non TS). Chaque bot obtient alors son propre dossier, avec un fichier contenant le code du bot et l'autre un passe-partout tsconfig.json:

{
  "compilerOptions": {
    "target": "es3",
    "module": "none",
    "sourceMap": false,
    "outFile": "bot.js"
  },
  "files": [
    "MissileKite.ts"
  ],
  "include": [
    "../lib/**/*"
  ]
}

Lorsque chaque tsconfig.json est construit, il crée un bot.js qui contient du code transpilé du bot lui-même ainsi que tout le code dans common.js. Cette configuration est sous-optimale pour plusieurs raisons, entre autres: elle nécessite beaucoup de passe-partout en double, rend difficile l'ajout de nouveaux bots, inclut beaucoup de code inutile pour chaque bot et nécessite que chaque bot soit construit séparément.

Cependant, d'après mes recherches jusqu'à présent , il ne semble pas qu'il existe un moyen facile de faire ce que je veux. En particulier, en utilisant le nouveau tsc -b L'option et les références ne fonctionnent pas, car cela nécessite que le code soit modulaire et Bot Land nécessite un fichier unique avec toutes les fonctions définies au niveau supérieur.

Quelle est la meilleure façon d'obtenir le plus grand nombre possible des éléments suivants?

  • Aucun nouveau passe-partout requis pour ajouter un nouveau bot (par exemple, pas de tsconfig.json par bot)
  • Utilisez import pour les fonctions courantes afin d'éviter de sortir du code inutilisé, mais alors ...
  • Toujours afficher toutes les fonctions dans un seul fichier au format spécifique de Bot Land
  • Une seule étape de génération qui produit plusieurs fichiers de sortie, un pour chaque bot
  • Bonus: intégration du processus de construction avec VS Code. Il existe actuellement un passe-partout correspondant tasks.json pour la construction de chaque sous-projet.

Je suppose vaguement que la réponse implique probablement quelque chose comme Grunt en plus de tsc, mais je n'en sais pas assez pour en être sûr.

10
Andrew Mao

Voici mon tentative pour répondre à vos besoins.

Fichiers notables:

  • src/tsconfig-botland.json contient les paramètres de tout script bot.land (y compris vos déclarations personnalisées que j'ai déplacées vers types/bot-land/index.d.ts). Vous pouvez modifier les paramètres strict que j'ai utilisés.
  • src/tsconfig.json contient des références à tous vos robots. Il s'agit du fichier à modifier chaque fois que vous souhaitez ajouter un autre script de bot

Un script bot est composé d'au moins deux fichiers: un tsconfig.json et un ou plusieurs .ts fichiers de script.

Par exemple src/AggroMiner/tsconfig.json:

{
    "extends": "../tsconfig-botland",
    "compilerOptions": {
        "outFile": "../../build/AggroMiner.js"
    },
    "files": ["index.ts"],
    "include": ["**/*.ts", "../lib/**/*.ts"]
}

Dans la plupart des cas, pour démarrer un nouveau script de bot, vous devez:

  1. copier n'importe quel dossier de bot (c'est-à-dire src/AggroMiner) dans un nouveau dossier sous src
  2. modifiez le src/<newBotFolder>/tsconfig.json pour modifier le outFile avec le nom de votre bot
  3. éditer src/tsconfig.json et ajoutez une référence à src/<newBotFolder>

Le script npm/yarn suivant a été défini:

  • build pour construire tous les bots
  • build-clean qui efface le dossier build avant d'exécuter un build
  • format pour exécuter Prettier sur tous les .ts fichiers sous src
  • lint pour exécuter une vérification tslint sur tous les scripts de bot

Exécuter maintenant vos exigences:

  • Aucun nouveau passe-partout requis pour ajouter un nouveau bot (par exemple, aucun tsconfig.json par bot)

Pour y parvenir, il faudrait créer un script qui énumérerait votre dossier/scripts de bots ... et configurer le per bot tsconfig.json et exécutez tsc. À moins que cela ne soit strictement nécessaire, une configuration minimale (décrite ci-dessus) peut être suffisante.

  • Utilisez l'importation pour les fonctions courantes pour éviter de sortir du code inutilisé, mais alors ...

Tout d'abord, sachez que si vous commencez à utiliser n'importe quel module export/import, vous aurez besoin de tiers supplémentaires pour emballer/arborescence afin d'obtenir une sortie de fichier unique. D'après ce que j'ai pu recueillir sur Bot.land, vos scripts s'exécutent sur le serveur. À moins que le code mort n'ait un impact sur les performances de votre bot, je ne me dérangerais pas vraiment.

  • Toujours afficher toutes les fonctions dans un seul fichier au format spécifique de Bot Land

Terminé.

  • Une seule étape de génération qui produit plusieurs fichiers de sortie, un pour chaque bot

Terminé.

  • Bonus: intégration du processus de construction avec VS Code. Il existe actuellement un fichier de tâches correspondant pour la construction de chaque sous-projet.

Les scripts npm devraient apparaître dans la liste des tâches de vsc (du moins ils le font dans la mienne), ce qui rend le tasks.json inutile.

2
PopGoesTheWza

Vous pouvez réellement utiliser des références de projet. Suivez ces étapes pour obtenir les mêmes résultats que vous obteniez pour vos fichiers d'origine, avec toutes les fonctions au niveau supérieur dans un seul fichier. Cependant, je n'ai pas trouvé de solution pour importer uniquement les fonctions nécessaires dans les bots. Autrement dit, sans utiliser les importations et les exportations.

Dans votre tsconfig.json à la racine

{
    "files": [],
    "references": [
        { "path": "./lib" }
        { "path": "./AggroMiner" }
        { "path": "./ArtilleryMicro" }
        { "path": "./MissileKite" }
        { "path": "./SmartMelee" }
        { "path": "./ZapKite" }
    ]
}

Ensuite, dans votre dossier lib, ajoutez un tsconfig.json comme ça

{
  "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"
  ]
}

Nous devons faire quelques ajustements dans data.ts, movement.ts et utils.ts afin que ts ne nous dérange pas avec des erreurs de compilation.

data.ts

/// <reference path="./bot.land.d.ts"/>

(...)

mouvement.ts


/// <reference path="./data.ts"/>
/// <reference path="./utils.ts"/>
(...)

utils.ts

/// <reference path="./bot.land.d.ts"/>
(...)

Ensuite, nous ajoutons base.json à la racine (le tsconfig.json des bots va l'étendre).

base.json

{
  "compilerOptions": {
    "declaration": true,
    "composite": true,
    "rootDir": ".",
    "target": "es3",
    "removeComments": true,
    "sourceMap": false,
  }
}

et tsconfig.json des bots (adapter en fonction des bots)

{
  "extends": "../base",
  "compilerOptions": {
    "outFile": "../build/AggroMiner.js",
  },
  "files": [
    "AggroMiner.ts"
  ],
  "references": [
      { "path": "../lib", "prepend": true } //note the prepend: true
  ]
}

C'est tout. Maintenant, lancez

tsc -b
3
jperl