Định cấu hình dự án TypeScript với các phụ thuộc chung để xây dựng nhiều tệp đầu ra JavaScript đơn giản


10

Tôi hiện đang viết một số kịch bản cho Bot Land . Bot Land là một trò chơi chiến lược thời gian thực, thay vì điều khiển các đơn vị của bạn bằng chuột và bàn phím, bạn viết mã để điều khiển các bot của mình thông qua API và sau đó các bot của bạn sẽ chiến đấu với các bot của người khác. Nếu bạn đã quen thuộc với các đơn vị trong SC2, bạn có thể tạo các bot tương tự như kẻ theo dõi chớp mắt, xe tăng bao vây, huy chương và ultralisks. (Đây là một trò chơi khá thú vị dành cho các kỹ sư phần mềm, nhưng điều đó nằm ngoài phạm vi của câu hỏi này.)

bot đất

Điều khiển Bot có ba mức độ phức tạp tăng dần: AI mặc định, ngôn ngữ lập trình giống như Scratch và một bộ JavaScript giảm gọi là BotLandScript. Mặc dù trình chỉnh sửa tích hợp cho BotLandScript là hợp lý, bạn phải tải lên tất cả mã của mình dưới dạng một tệp duy nhất với các hàm cấp cao nhất toàn cầu ở mọi nơi. Đương nhiên, điều này sẽ bắt đầu trở nên đau đớn sau một thời gian nếu mã của bạn bắt đầu dài và các bot khác nhau có chung các chức năng.

môi trường lập trình

Để tạo điều kiện viết mã cho nhiều bot, giảm cơ hội xảy ra lỗi vô ý khi mã hóa trong mã trần và tăng cơ hội đánh bại những người chơi khác, tôi đã thiết lập dự án TypeScript ở trên để cung cấp thư viện chung cũng như mã cho mỗi bot của tôi . Cấu trúc thư mục hiện tại trông giống như sau:

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

liblà mã phổ biến được chia sẻ giữa các bot và cung cấp các định nghĩa TypeScript cho API Bot Land (không phải TS). Mỗi bot sau đó nhận được thư mục riêng của mình, với một tệp chứa mã bot và tệp còn lại là bản soạn sẵn tsconfig.json:

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

Khi mỗi cái tsconfig.jsonđược xây dựng, nó tạo ra một mã tương ứng bot.jschứa mã được mã hóa từ chính bot cũng như tất cả mã trong đó common.js. Thiết lập này không tối ưu vì một số lý do, trong số những lý do khác: nó đòi hỏi rất nhiều bản sao chép trùng lặp, khiến cho việc thêm bot mới trở nên khó khăn, bao gồm rất nhiều mã không cần thiết cho mỗi bot và yêu cầu mỗi bot phải được xây dựng riêng.

Tuy nhiên, dựa trên nghiên cứu của tôi cho đến nay , dường như không có cách nào dễ dàng để làm những gì tôi muốn. Cụ thể, sử dụng tsc -btùy chọn mới và tham chiếu không hoạt động, vì điều đó đòi hỏi mã phải được mô đun hóa và Bot Land yêu cầu một tệp duy nhất với tất cả các chức năng được xác định ở cấp cao nhất.

Cách tốt nhất để đạt được càng nhiều điều sau đây càng tốt?

  • Không yêu cầu nồi hơi mới để thêm bot mới (ví dụ: không có tsconfig.jsonmỗi bot)
  • Sử dụng importcho các chức năng phổ biến để tránh xuất mã không sử dụng, nhưng sau đó ...
  • Vẫn xuất tất cả các chức năng dưới dạng một tệp duy nhất ở định dạng cụ thể của Bot Land
  • Một bước xây dựng duy nhất tạo ra nhiều tệp đầu ra, một cho mỗi bot
  • Phần thưởng: tích hợp quá trình xây dựng với Mã VS. Hiện tại có một bản tóm tắt tương ứng tasks.jsonđể xây dựng từng tiểu dự án.

Tôi mơ hồ phỏng đoán câu trả lời có lẽ liên quan đến một cái gì đó giống như Grunt tsc, nhưng tôi không biết đủ về điều đó để chắc chắn.


Có cần thiết rằng tất cả các bot có thư mục riêng biệt? Hoặc là đủ để mỗi bot ở cấp độ gốc trong một tệp? (ví dụ <root>/MissileKite.ts)
a1300

1
Có phải tất cả các tập tin bot được mã hóa phải được đặt tên bot.js?
a1300

Root trong một tập tin sẽ thích hợp hơn; chúng nằm trong các thư mục riêng biệt vì riêng biệt tsconfig.json. Các tệp bot được dịch mã có thể được đặt tên bất cứ thứ gì, tốt nhất là phiên bản .js của tệp gốc. Tôi có nó được thiết lập theo cách này bây giờ trong repo xuất ra build/MissileKite.js.
Andrew Mao

1
@ andrew-mao Bạn có thể xem mẫu của tôi cho các dự án GAS giải quyết hầu hết các yêu cầu của bạn (nhưng nhắm mục tiêu vào một môi trường khác) Nếu phù hợp với bạn, tôi có thể điều chỉnh nó cho bạn vào tuần tới. github.com/PopGoesTheWza/ts-gas-project-starter
PopGoesTheWza

tsconfig-gas.jsonđiều liên quan để xem xét ở đó?
Andrew Mao

Câu trả lời:


2

Đây là nỗ lực của tôi để trả lời yêu cầu của bạn.

Các tập tin đáng chú ý:

  • src/tsconfig-botland.jsongiữ các cài đặt cho bất kỳ tập lệnh bot.land nào (bao gồm các khai báo tùy chỉnh mà tôi đã chuyển đến types/bot-land/index.d.ts). Bạn có thể thay đổi strictcài đặt tôi đã sử dụng.
  • src/tsconfig.jsongiữ tài liệu tham khảo cho tất cả các bot của bạn. Đây là tệp để chỉnh sửa bất cứ khi nào bạn muốn thêm tập lệnh bot khác

Một tập lệnh bot có ít nhất hai tệp: một tập tin tối giản tsconfig.jsonvà một hoặc nhiều .tstập lệnh.

Ví dụ src/AggroMiner/tsconfig.json:

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

Trong hầu hết các trường hợp, để bắt đầu một tập lệnh bot mới, bạn nên:

  1. sao chép bất kỳ thư mục bot (tức là src/AggroMiner) vào một thư mục mới bên dướisrc
  2. chỉnh sửa src/<newBotFolder>/tsconfig.jsonđể chỉnh sửa outFilevới tên bot của bạn
  3. chỉnh sửa src/tsconfig.jsonvà thêm một tham chiếu đếnsrc/<newBotFolder>

Tập lệnh npm/ yarntập lệnh sau đã được đặt:

  • build xây dựng tất cả các bot
  • build-cleanXóa buildthư mục trước khi chạybuild
  • formatđể chạy Prettier trên tất cả .tscác tệp trongsrc
  • lint để chạy kiểm tra tslint trên tất cả các tập lệnh bot

Bây giờ chạy xuống yêu cầu của bạn:

  • Không yêu cầu nồi hơi mới để thêm bot mới (ví dụ: không có tsconfig.json trên mỗi bot)

Để đạt được điều này sẽ yêu cầu tạo một số tập lệnh sẽ liệt kê thư mục / tập lệnh bot của bạn ... và thiết lập liên quan cho mỗi bot tsconfig.jsonvà chạy tsc. Trừ khi nó thực sự cần thiết, một thiết lập tối thiểu (mô tả ở trên) có thể là đủ.

  • Sử dụng nhập cho các chức năng phổ biến để tránh xuất mã không sử dụng, nhưng sau đó ...

Trước tiên, hãy lưu ý rằng nếu bạn bắt đầu sử dụng bất kỳ mô-đun export/ importcâu lệnh nào, bạn sẽ cần thêm bên thứ 3 để đóng gói / treeshake để đạt được một đầu ra tệp duy nhất. Từ những gì tôi có thể thu thập được của Bot.land, các tập lệnh của bạn đang chạy trên máy chủ. Trừ khi deadcode có ảnh hưởng đến hiệu suất bot của bạn, tôi sẽ không thực sự bận tâm.

  • Vẫn xuất tất cả các chức năng dưới dạng một tệp duy nhất ở định dạng cụ thể của Bot Land

Làm xong.

  • Một bước xây dựng duy nhất tạo ra nhiều tệp đầu ra, một cho mỗi bot

Làm xong.

  • Phần thưởng: tích hợp quá trình xây dựng với Mã VS. Hiện tại có một task.json nồi hơi tương ứng để xây dựng từng dự án con.

Các npmtập lệnh sẽ xuất hiện trong danh sách nhiệm vụ của vsc (ít nhất là chúng làm trong phần của tôi), do đó làm cho tasks.jsonkhông cần thiết.


Deadcode là một sự thỏa hiệp tốt đẹp cho mọi thứ khác bạn đã thực hiện ở đây; bạn có thể cho tôi biết mặc dù tại sao bạn sử dụng types/bot-landcho các định nghĩa và tại sao bạn chọn strictcài đặt không?
Andrew Mao

Các loại / bot-đất / index.d.ts thực sự là .d.ts ban đầu của bạn từ lib, được đổi tên và đặt khác nhau. Giả sử nó mô tả bối cảnh thực thi bot.land chung cho tất cả các tập lệnh và do đó tôi đảm bảo rằng nó luôn có sẵn trong mọi tập lệnh bot. Các cài đặt 'nghiêm ngặt' chỉ có ở đây vì tôi lười biếng sao chép các cài đặt ưa thích của mình (tương tự cho các cài đặt đẹp hơn). Những người nên được điều chỉnh theo sở thích của người dùng (bạn).
PopGoesTheWza

Tôi chỉ tự hỏi liệu có một lý do thông thường để đưa nó vào typeshoặc nếu đó chỉ là một cách cụ thể để tổ chức mà bạn đã chọn.
Andrew Mao

Lý do duy nhất là giả sử đó là bối cảnh bot.land. Hãy nghĩ về nó giống như việc có các kiểu chữ @ / nút đã có sẵn trong các tập lệnh nodejs của bạn
PopGoesTheWza

1
Thư mục A / type là một trong những nơi thông thường nơi người ta đặt các khai báo kiểu bên ngoài (Tức là bối cảnh thực thi cụ thể như công cụ botland hoặc các mô-đun / gói JavaScript chưa được sử dụng ở đây)
PopGoesTheWza

3

Bạn thực sự có thể sử dụng tài liệu tham khảo dự án. Thực hiện theo các bước sau để có được kết quả giống như bạn nhận được cho các tệp gốc của mình, với tất cả các chức năng ở cấp cao nhất trong một tệp. Tuy nhiên, tôi không thể tìm thấy giải pháp chỉ nhập các chức năng cần thiết trong bot. Đó là, không sử dụng nhập khẩu và xuất khẩu.

Trong tsconfig.json của bạn ở thư mục gốc

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

Tiếp theo, trong thư mục lib của bạn, hãy thêm tsconfig.json như vậy

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

Chúng ta cần thực hiện một vài điều chỉnh trong data.ts, Movement.ts và utils.ts để ts không làm phiền chúng tôi với các lỗi biên dịch.

dữ liệu

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

(...)

phong trào.ts


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

đồ dùng

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

Tiếp theo, chúng tôi thêm base.json ở thư mục gốc (tsconfig.json của các bot sẽ mở rộng nó).

cơ sở

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

và tsconfig.json của bot (thích ứng với bot)

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

Đó là nó. Bây giờ chỉ cần chạy

tsc -b

Vì vậy, tôi đã nghĩ về một cái gì đó như thế này, nhưng lý do nó không hoạt động là vì tệp được xuất ra trên nhánh của bạn có một loạt các thứ như thế này ở trên cùng và trò chơi cần một tệp có tất cả các chức năng trong đó. Vì vậy, sau đó tôi phải tự lắp ráp tất cả các đầu ra được biên dịch lại với nhau để tạo tệp mà tôi tải lên, thay vì chỉ sao chép dán tệp. `" sử dụng nghiêm ngặt "; xuất khẩu .__ esModule = true; var data_1 = Yêu cầu ("../ lib / data"); var Movement_1 = Yêu cầu ("../ lib / phong trào"); var utils_1 = Yêu cầu ("../ lib / utils"); `
Andrew Mao

Nhưng nó hoạt động vì lib cũng là đầu ra (được xây dựng) trong thư mục xây dựng (nhờ các tài liệu tham khảo).
jperl

Tôi đang trong quá trình chỉnh sửa nhận xét của mình - xem ở trên. Hoặc hãy xem cái build/MissileKite.jsđược xuất ra khi bạn xây dựng repo ban đầu.
Andrew Mao

@AndrewMao xin lỗi, chỉ bây giờ tôi mới hiểu ý của bạn là gì "bởi vì điều đó đòi hỏi mã phải được mô đun hóa và Bot Land yêu cầu một tệp duy nhất với tất cả các chức năng được xác định ở cấp cao nhất.". Tôi đã nghĩ về việc sử dụng "preend: true" nhưng điều đó đòi hỏi phải sử dụng outFile và ts sẽ không cho phép chúng tôi biên dịch các tệp trong lib vì một số phụ thuộc vào người khác.
jperl

@AndrewMao Tôi đã thêm hỗ trợ Webpack. Tôi chỉnh sửa bài đăng và đẩy những thay đổi trên repo. Hãy cho tôi biết nếu nó tốt hơn.
jperl
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.