Konfigurasikan proyek TypeScript dengan dependensi umum untuk membangun beberapa file output JavaScript biasa

10

Saat ini saya sedang menulis beberapa skrip untuk Bot Land . Bot Land adalah gim strategi real-time di mana alih-alih mengendalikan unit Anda dengan mouse dan keyboard, Anda menulis kode untuk mengontrol bot Anda melalui API, dan kemudian bot Anda bertarung melawan bot orang lain. Jika Anda terbiasa dengan unit di SC2, Anda dapat membuat bot yang mirip dengan penguntit kedip, tangki pengepungan, petugas medis, dan ultralis. (Ini adalah permainan yang cukup menyenangkan untuk insinyur perangkat lunak, tapi itu di luar cakupan pertanyaan ini.)

tanah bot

Kontrol bot memiliki tiga tingkat peningkatan kompleksitas: AI default, bahasa pemrograman seperti Scratch , dan serangkaian JavaScript yang dikurangi yang disebut BotLandScript. Meskipun editor bawaan untuk BotLandScript masuk akal, Anda harus mengunggah semua kode Anda sebagai satu file tunggal dengan fungsi tingkat global di mana-mana. Secara alami, ini mulai menyakitkan setelah beberapa saat jika kode Anda mulai menjadi panjang dan berbagai bot berbagi fungsi yang sama.

lingkungan pemrograman

Untuk memfasilitasi penulisan kode untuk banyak bot, kurangi peluang untuk kesalahan yang tidak disengaja saat pengkodean di bare JS, dan tingkatkan peluang saya untuk mengalahkan pemain lain, saya menyiapkan proyek TypeScript di atas untuk menyediakan perpustakaan umum serta kode untuk setiap bot saya . Struktur direktori saat ini terlihat kira-kira seperti berikut ini:

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

libadalah kode umum yang dibagikan di antara bot, dan memberikan definisi TypeScript untuk API Bot Tanah (non-TS). Setiap bot kemudian mendapatkan foldernya sendiri, dengan satu file yang berisi kode bot dan satunya lagi adalah boilerplate tsconfig.json:

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

Ketika masing tsconfig.json- masing dibangun, itu menciptakan yang sesuai bot.jsyang berisi kode yang diubah dari bot itu sendiri serta semua kode di dalamnya common.js. Pengaturan ini tidak optimal karena beberapa alasan, antara lain: memerlukan banyak duplikat boilerplate, membuatnya sulit untuk menambahkan bot baru, termasuk banyak kode yang tidak perlu untuk setiap bot, dan mengharuskan setiap bot dibangun secara terpisah.

Namun, berdasarkan penelitian saya sejauh ini , sepertinya tidak ada cara mudah untuk melakukan apa yang saya inginkan. Secara khusus, menggunakan tsc -bopsi baru dan referensi tidak berfungsi, karena itu memerlukan kode untuk dimodulasi dan Bot Land memerlukan satu file dengan semua fungsi yang didefinisikan di tingkat atas.

Apa cara terbaik untuk mencapai sebanyak mungkin hal berikut ini?

  • Tidak diperlukan boilerplate baru untuk menambahkan bot baru (mis. Tidak ada tsconfig.jsonper bot)
  • Gunakan importuntuk fungsi-fungsi umum untuk menghindari mengeluarkan kode yang tidak digunakan, tetapi kemudian ...
  • Masih menampilkan semua fungsi sebagai satu file tunggal dalam format spesifik Bot Land
  • Langkah build tunggal yang menghasilkan banyak file output, satu untuk setiap bot
  • Bonus: mengintegrasikan proses pembuatan dengan VS Code. Ada boilerplate saat ini sesuai tasks.jsonuntuk membangun setiap sub-proyek.

Samar-samar aku menduga jawabannya mungkin melibatkan sesuatu seperti Grunt tsc, tapi aku tidak cukup tahu tentang itu.

Andrew Mao
sumber
Apakah perlu agar semua bot memiliki folder terpisah? Atau apakah cukup bahwa setiap bot berada di tingkat root dalam satu file? (mis. <root>/MissileKite.ts)
a1300
1
Apakah semua file bot yang dipindahkan harus dinamai bot.js?
A1300
Root dalam satu file akan lebih disukai; mereka berada di folder terpisah karena terpisah tsconfig.json. File bot yang di-transpile dapat dinamai apa saja, lebih disukai versi .js dari file asli. Saya sudah mengaturnya sekarang di repo keluaran ke build/MissileKite.js.
Andrew Mao
1
@ andrew-mao Anda dapat melihat templat saya untuk proyek GAS yang membahas sebagian besar kebutuhan Anda (tetapi menargetkan lingkungan yang berbeda) Jika cocok untuk Anda, saya mungkin dapat menyesuaikannya untuk Anda sekitar minggu depan. github.com/PopGoesTheWza/ts-gas-project-starter
PopGoesTheWza
Apakah tsconfig-gas.jsonhal yang relevan untuk dilihat di sana?
Andrew Mao

Jawaban:

2

Ini adalah upaya saya untuk menjawab kebutuhan Anda.

File penting:

  • src/tsconfig-botland.jsonmenyimpan pengaturan untuk skrip bot.land (termasuk deklarasi khusus yang saya pindahkan ke types/bot-land/index.d.ts). Anda dapat mengubah strictpengaturan yang saya gunakan.
  • src/tsconfig.jsonmemegang referensi ke semua bot Anda. Ini adalah file yang akan diedit setiap kali Anda ingin menambahkan skrip bot lain

Skrip bot setidaknya terdiri dari dua file: file skrip minimalis tsconfig.jsondan satu atau lebih .ts.

Sebagai contoh src/AggroMiner/tsconfig.json:

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

Dalam kebanyakan kasus, untuk memulai skrip bot baru Anda harus:

  1. salin folder bot apa saja (yaitu src/AggroMiner) ke folder baru di bawahsrc
  2. edit src/<newBotFolder>/tsconfig.jsonuntuk mengedit outFiledengan nama bot Anda
  3. edit src/tsconfig.jsondan tambahkan referensi kesrc/<newBotFolder>

Script npm/ berikut yarnini telah ditetapkan:

  • build untuk membangun semua bot
  • build-cleanyang menghapus buildfolder sebelum menjalankanbuild
  • formatuntuk menjalankan Prettier pada semua .tsfile di bawahsrc
  • lint untuk menjalankan pemeriksaan tslint pada semua skrip bot

Sekarang menjalankan persyaratan Anda:

  • Tidak diperlukan boilerplate baru untuk menambahkan bot baru (mis. Tidak ada tsconfig.json per bot)

Untuk mencapai ini diperlukan pembuatan beberapa skrip yang akan menyebutkan folder / skrip bot Anda ... dan mengatur per bot yang relevan tsconfig.jsondan menjalankannya tsc. Kecuali sangat diperlukan, pengaturan minimal (yang dijelaskan di atas) mungkin cukup.

  • Gunakan impor untuk fungsi-fungsi umum untuk menghindari mengeluarkan kode yang tidak digunakan, tetapi kemudian ...

Pertama, perlu diketahui bahwa jika Anda mulai menggunakan modul export/ importpernyataan apa pun , Anda akan membutuhkan pihak ke-3 tambahan untuk mengepak / treeshake untuk mencapai satu output file. Dari apa yang saya dapat kumpulkan dari Bot.land, skrip Anda berjalan di server. Kecuali jika deadcode berdampak pada kinerja bot Anda, saya tidak akan terlalu repot.

  • Masih menampilkan semua fungsi sebagai satu file tunggal dalam format spesifik Bot Land

Selesai

  • Langkah build tunggal yang menghasilkan banyak file output, satu untuk setiap bot

Selesai

  • Bonus: mengintegrasikan proses pembuatan dengan VS Code. Saat ini ada tugas-tugas boilerplate yang sesuai. Pekerjaan untuk membangun setiap sub-proyek.

The npmScript akan muncul dalam daftar tugas VSC (setidaknya mereka lakukan di tambang) sehingga membuat tasks.jsonyang tidak perlu.

PopGoesTheWza
sumber
Deadcode adalah kompromi yang bagus untuk semua yang Anda buat di sini; dapatkah Anda memberi tahu saya mengapa Anda menggunakan types/bot-landdefinisi dan mengapa Anda memilih strictpengaturan?
Andrew Mao
Jenis / bot-land / index.d.ts benar-benar adalah .d.ts asli Anda dari lib, diganti namanya dan ditempatkan secara berbeda. Î menganggapnya semacam menggambarkan konteks eksekusi bot.land umum untuk semua skrip dan karenanya saya memastikan selalu tersedia di setiap skrip bot. Pengaturan 'ketat' hanya ada di sini karena saya dengan malas menyalin pengaturan yang saya sukai (sama untuk pengaturan yang lebih cantik). Itu harus disesuaikan dengan preferensi pengguna (Anda).
PopGoesTheWza
Saya hanya ingin tahu apakah ada alasan adat untuk memasukkannya ke dalam typesatau jika itu hanya cara khusus untuk mengatur yang Anda pilih.
Andrew Mao
Satu-satunya alasan adalah menganggap itu konteks bot.land. Anggap saja seperti memiliki @ types / node typing sudah tersedia di skrip nodejs Anda
PopGoesTheWza
1
Folder A / types adalah salah satu tempat konvensional di mana seseorang meletakkan deklarasi tipe eksternal (Yaitu konteks eksekusi spesifik seperti mesin botland atau modul / paket JavaScript yang tidak
diketik
3

Anda sebenarnya bisa menggunakan referensi proyek. Ikuti langkah-langkah ini untuk mendapatkan hasil yang sama dengan yang Anda dapatkan untuk file asli Anda, dengan semua fungsi di tingkat atas dalam satu file. Namun, saya tidak dapat menemukan solusi untuk mengimpor hanya fungsi yang diperlukan dalam bot. Artinya, tanpa menggunakan impor dan ekspor.

Di tsconfig.json Anda di root

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

Selanjutnya, di folder lib Anda, tambahkan tsconfig.json seperti itu

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

Kita perlu membuat beberapa penyesuaian dalam data.ts, movement.ts dan utils.ts sehingga ts tidak mengganggu kita dengan kesalahan kompilasi.

data.ts

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

(...)

gerakan


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

utils.ts

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

Selanjutnya, kita tambahkan base.json di root (tsconfig.json dari bot akan memperpanjangnya).

base.json

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

dan tsconfig.json dari bot (sesuaikan dengan bot)

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

Itu dia. Sekarang jalankan

tsc -b
jperl
sumber
Jadi saya memikirkan sesuatu seperti ini, tetapi alasan itu tidak berhasil adalah karena file yang mendapatkan output di cabang Anda memiliki banyak hal seperti ini di bagian atas, dan permainan membutuhkan satu file dengan semua fungsi di dalamnya. Jadi saya kemudian harus secara manual membuat semua output yang dikompilasi secara bersamaan untuk membuat file yang saya unggah, bukan hanya menyalin paste file. `" gunakan ketat "; ekspor .__ esModule = true; var data_1 = membutuhkan ("../ lib / data"); var movement_1 = membutuhkan ("../ lib / gerakan"); var utils_1 = membutuhkan ("../ lib / utils"); `
Andrew Mao
Tetapi ini berfungsi karena lib juga merupakan output (built) di folder build (terima kasih atas referensi).
jperl
Saya sedang dalam proses mengedit komentar saya - lihat di atas. Atau lihat build/MissileKite.jsyang dihasilkan saat Anda membangun repo asli.
Andrew Mao
@AndrewMao maaf, hanya sekarang saya mengerti apa yang Anda maksud dengan "karena itu membutuhkan kode untuk dimodulasi dan Bot Land memerlukan satu file dengan semua fungsi yang didefinisikan di tingkat atas.". Saya berpikir tentang menggunakan "prepend: true" tetapi itu membutuhkan penggunaan outFile dan ts tidak akan membiarkan kita mengkompilasi file dalam lib karena beberapa tergantung pada yang lain.
jperl
@AndrewMao Saya telah menambahkan dukungan Webpack. Saya mengedit posting dan mendorong perubahan pada repo. Beri tahu saya jika ini lebih baik.
jperl