Skonfiguruj projekt TypeScript z typowymi zależnościami, aby zbudować wiele zwykłych plików wyjściowych JavaScript


10

Obecnie piszę kilka skryptów dla Bot Land . Bot Land to gra strategiczna w czasie rzeczywistym, w której zamiast kontrolować jednostki za pomocą myszy i klawiatury, piszesz kod kontrolujący boty za pośrednictwem interfejsu API, a następnie boty walczą z botami innych. Jeśli znasz jednostki w SC2, możesz tworzyć boty podobne do mrugających prześladowców, czołgów oblężniczych, medyków i ultralisk. (To dość zabawna gra dla inżynierów oprogramowania, ale to nie wchodzi w zakres tego pytania).

bot land

Kontrola botów ma trzy poziomy rosnącej złożoności: domyślną sztuczną inteligencję, język programowania podobny do Scratch oraz ograniczony zestaw JavaScript o nazwie BotLandScript. Chociaż wbudowany edytor BotLandScript jest rozsądny, musisz przesłać cały kod jako jeden plik z globalnymi funkcjami najwyższego poziomu wszędzie. Oczywiście zaczyna to boleć po pewnym czasie, jeśli twój kod zaczyna się wydłużać, a różne boty mają te same funkcje.

środowisko programistyczne

Aby ułatwić pisanie kodu dla wielu botów, zmniejszyć ryzyko niezamierzonych błędów podczas kodowania w czystym JS i zwiększyć moje szanse na pokonanie innych graczy, skonfigurowałem powyższy projekt TypeScript, aby zapewnić wspólną bibliotekę oraz kod dla każdego z moich botów . Obecna struktura katalogów wygląda mniej więcej tak:

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

libjest wspólnym kodem dzielonym przez boty i zawiera definicje TypeScript dla (nie-TS) Bot Land API. Każdy bot otrzymuje następnie swój własny folder, z jednym plikiem zawierającym kod bota, a drugim - płytką zbiorczą tsconfig.json:

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

Po tsconfig.jsonzbudowaniu każdego z nich tworzony jest odpowiedni bot.jskod, który zawiera transpilowany kod z samego bota, a także cały kod common.js. Ta konfiguracja jest nieoptymalna z kilku powodów, między innymi: wymaga dużej ilości zduplikowanych płyt kotłowych, utrudnia dodawanie nowych botów, zawiera wiele niepotrzebnego kodu dla każdego bota i wymaga, aby każdy bot był budowany osobno.

Jednak na podstawie moich dotychczasowych badań nie wydaje się, że istnieje prosty sposób na robienie tego, co chcę. W szczególności użycie nowej tsc -bopcji i odniesień nie działa, ponieważ wymaga to modularyzacji kodu, a Bot Land wymaga jednego pliku ze wszystkimi funkcjami zdefiniowanymi na najwyższym poziomie.

Jaki jest najlepszy sposób na uzyskanie jak największej liczby poniższych możliwości?

  • Nie jest wymagana nowa płyta kotła, aby dodać nowego bota (np. Nie tsconfig.jsonna bota)
  • Użyj importdla typowych funkcji, aby uniknąć generowania nieużywanego kodu, ale potem ...
  • Nadal wyprowadzasz wszystkie funkcje jako jeden plik w specyficznym formacie Bot Land
  • Jeden krok kompilacji, w którym powstaje wiele plików wyjściowych, po jednym dla każdego bota
  • Bonus: zintegrowanie procesu kompilacji z VS Code. Obecnie istnieje odpowiednio plansza tasks.jsondo budowy każdego podprojektu.

Domyślam się, że odpowiedź prawdopodobnie wiąże się z czymś takim jak Grunt tsc, ale nie wiem wystarczająco dużo na ten temat.


Czy konieczne jest, aby wszystkie boty miały osobne foldery? A może wystarczy, że każdy bot znajduje się na poziomie głównym w jednym pliku? (np. <root>/MissileKite.ts)
— 1300

1
Czy wszystkie transpilowane pliki botów muszą mieć nazwy bot.js?
— a1300,

Preferowane byłoby rootowanie w jednym pliku; znajdują się w osobnych folderach ze względu na osobne tsconfig.json. Przeszczepione pliki botów mogą mieć dowolną nazwę, najlepiej wersję oryginalnego pliku .js. Mam to ustawione w ten sposób teraz w repozytorium wyjściowym do build/MissileKite.js.
— Andrew Mao,

1
@ andrew-mao Możesz rzucić okiem na mój szablon dla projektów GAS, który spełnia większość twoich wymagań (ale ukierunkowanie na inne środowisko) Jeśli ci to odpowiada, być może będę w stanie dostosować go dla ciebie w przyszłym tygodniu. github.com/PopGoesTheWza/ts-gas-project-starter
— PopGoesTheWza

Czy tsconfig-gas.jsonwarto tam spojrzeć?
— Andrew Mao,

Odpowiedzi:


2

Oto moja próba odpowiedzi na twoje wymagania.

Ważne pliki:

  • src/tsconfig-botland.jsonprzechowuje ustawienia dla dowolnego skryptu bot.land (w tym niestandardowych deklaracji, do których przeprowadziłem się types/bot-land/index.d.ts). Możesz zmienić strictustawienia, których użyłem.
  • src/tsconfig.jsonzawiera odniesienia do wszystkich twoich botów. Jest to plik do edycji za każdym razem, gdy chcesz dodać kolejny skrypt bota

Skrypt bota to co najmniej dwa pliki: minimalistyczny tsconfig.jsoni jeden lub więcej .tsplików skryptowych.

Na przykład src/AggroMiner/tsconfig.json:

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

W większości przypadków, aby uruchomić nowy skrypt bota, powinieneś:

  1. skopiuj dowolny folder bota (tj src/AggroMiner ) do nowego folderu podsrc
  2. edytuj src/<newBotFolder>/tsconfig.json aby edytować outFilez nazwą twojego bota
  3. edytować src/tsconfig.json i dodaj odniesienie dosrc/<newBotFolder>

Ustawiono następujące npm/ yarnskrypt:

  • build zbudować wszystkie boty
  • build-cleanktóre usuwają buildfolder przed uruchomieniembuild
  • formaturuchomić Prettier na wszystkich .tsplikach poniżejsrc
  • lint aby uruchomić sprawdzanie tslint na wszystkich skryptach bota

Teraz wyczerpują się twoje wymagania:

  • Nie jest wymagana nowa płyta kotła, aby dodać nowego bota (np. Brak tsconfig.json na bota)

Aby to osiągnąć, należy utworzyć skrypt, który wyliczy folder / skrypty bota ... i skonfiguruje odpowiedni dla każdego bota tsconfig.jsoni uruchomtsc . O ile nie jest to absolutnie konieczne, minimalna konfiguracja (opis powyżej) może być wystarczająca.

  • Użyj importu do typowych funkcji, aby uniknąć generowania nieużywanego kodu, ale potem ...

Po pierwsze, pamiętaj, że jeśli zaczniesz używać dowolnego modułu export/ importinstrukcji, będziesz potrzebować dodatkowej strony trzeciej do spakowania / uzgadniania drzewa w celu uzyskania pojedynczego pliku wyjściowego. Z tego, co mogłem zebrać w Bot.land, twoje skrypty działają na serwerze. O ile deadcode nie wpływa na wydajność twojego bota, tak naprawdę nie zawracałbym sobie głowy.

  • Nadal wyprowadzasz wszystkie funkcje jako jeden plik w specyficznym formacie Bot Land

Gotowy.

  • Jeden krok kompilacji, w którym powstaje wiele plików wyjściowych, po jednym dla każdego bota

Gotowy.

  • Bonus: zintegrowanie procesu kompilacji z VS Code. Istnieją obecnie odpowiednio `` kotłowe zadania ''. Json do budowy każdego podprojektu.

Te npmskrypty powinien pojawić się na liście zadań VSC (przynajmniej robią w kopalni) co powoduje, że tasks.jsonzbędne.


Deadcode to dobry kompromis dla wszystkiego, co tutaj stworzyłeś; czy możesz mi jednak powiedzieć, dlaczego użyłeś types/bot-landdefinicji i dlaczego wybrałeś strictustawienia?
— Andrew Mao

Typy / bot-land / index.d.ts to naprawdę twój oryginalny plik .d.ts z biblioteki lib, którego nazwa została zmieniona i umieszczony inaczej. Î załóżmy, że w pewien sposób opisuje ogólny kontekst wykonywania bot.land dla wszystkich skryptów, dlatego upewniam się, że jest on zawsze dostępny w każdym skrypcie bota. Ustawienia „ścisłe” są tutaj tylko dlatego, że leniwie skopiowałem moje ulubione ustawienia (to samo dla ładniejszych ustawień). Powinny być one dostosowane do preferencji użytkownika (Ciebie).
— PopGoesTheWza

Zastanawiam się tylko, czy istnieje jakiś zwyczajny powód, aby to włożyć, typesczy też był to tylko określony sposób organizacji, który wybrałeś.
— Andrew Mao,

Jedynym powodem jest założenie, że był to kontekst bot.land. Pomyśl o tym jak o tym, że @ typy / typy węzłów są już dostępne w twoich skryptach
— nodejs

1
Folder A / types jest jednym z konwencjonalnych miejsc, w których umieszcza się deklaracje typów zewnętrznych (tj. Kontekst wykonania specyficzny, taki jak silnik botland lub nietypowe moduły / pakiety JavaScript, które nie są tutaj używane)
— PopGoesTheWza

3

Możesz użyć referencji projektu. Wykonaj następujące kroki, aby uzyskać takie same wyniki, jak w przypadku oryginalnych plików, ze wszystkimi funkcjami na najwyższym poziomie w jednym pliku. Jednak nie mogłem znaleźć rozwiązania, aby zaimportować tylko potrzebne funkcje do botów. To znaczy bez korzystania z importu i eksportu.

W tsconfig.json w katalogu głównym

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

Następnie w folderze lib dodaj plik 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"
  ]
}

Musimy wprowadzić kilka zmian w data.ts, move.ts i utils.ts, aby ts nie przeszkadzał nam w błędach kompilacji.

data.ts

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

(...)

move.ts


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

utils.ts

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

Następnie dodajemy base.json w katalogu głównym (tsconfig.json botów go przedłuży).

base.json

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

i tsconfig.json bots (dostosuj zgodnie z botami)

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

Otóż ​​to. Teraz po prostu biegnij

tsc -b

Pomyślałem o czymś takim, ale to nie działa, ponieważ plik, który dostaje się do twojego oddziału, ma na górze mnóstwo takich rzeczy, a gra potrzebuje jednego pliku ze wszystkimi funkcjami. Musiałbym więc ręcznie połączyć wszystkie skompilowane dane wyjściowe, aby utworzyć plik, który przesłałem, zamiast po prostu skopiować plik. `` użyj ścisłego ''; eksportuje .__ esModule = true; var data_1 = wymagany („../ lib / data”); var ruch_1 = wymagany („../ lib / ruch”); var utils_1 = wymagany („../ lib / utils”); `
— Andrew Mao,

Ale działa, ponieważ lib jest również wyprowadzany (budowany) w folderze kompilacji (dzięki referencjom).
— jperl

Byłem w trakcie edytowania mojego komentarza - patrz wyżej. Lub spójrz na to, build/MissileKite.jsco jest generowane podczas budowania oryginalnego repo.
— Andrew Mao,

@AndrewMao przepraszam, dopiero teraz rozumiem, co miałeś na myśli mówiąc „ponieważ wymaga to zmodularyzowania kodu, a Bot Land wymaga jednego pliku ze wszystkimi funkcjami zdefiniowanymi na najwyższym poziomie”. Myślałem o użyciu „prepend: true”, ale to wymaga użycia outFile, a ts nie pozwoli nam skompilować plików w lib, ponieważ niektóre są zależne od innych.
— jperl

@AndrewMao Dodałem obsługę Webpack. Zredagowałem post i opublikowałem zmiany w repozytorium. Daj mi znać, jeśli będzie lepiej.
— jperl
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.