Bỏ qua để đến nội dung

Dự án TypeScript

Trình tạo dự án TypeScript có thể được sử dụng để tạo một thư viện hoặc ứng dụng TypeScript hiện đại được cấu hình với các phương pháp hay nhất như ECMAScript Modules (ESM), project references của TypeScript, Vitest để chạy kiểm thử và Biome để lint và format.

Bạn có thể tạo một dự án TypeScript mới theo hai cách:

Terminal window
pnpm nx g @aws/nx-plugin:ts#project
Bạn cũng có thể thực hiện chạy thử để xem những tệp nào sẽ bị thay đổi
Terminal window
pnpm nx g @aws/nx-plugin:ts#project --dry-run
Tham sốKiểuMặc địnhMô tả
name Bắt buộcstring-Tên dự án TypeScript
directory stringpackagesThư mục cha nơi thư viện được đặt.
subDirectory string-Thư mục con nơi thư viện được đặt. Mặc định đây là tên thư viện.
preferInstallDependencies booleantrueCó nên ưu tiên cài đặt các dependencies sau khi generator chạy hay không. Đặt thành false để hoãn việc cài đặt khi chạy nhiều generator liên tiếp (việc cài đặt vẫn sẽ chạy nếu cần thiết để các generator tiếp theo có thể tính toán Nx project graph); cài đặt một lần vào cuối.

Trình tạo sẽ tạo cấu trúc dự án sau trong thư mục <directory>/<name>:

  • Thư mụcsrc Mã nguồn TypeScript
    • index.ts
  • package.json Tệp kê khai dự án xác định tên package và các phụ thuộc của dự án
  • project.json Cấu hình dự án và các target build
  • tsconfig.json Cấu hình TypeScript cơ bản cho dự án này (kế thừa từ tsconfig.base.json ở thư mục gốc workspace)
  • tsconfig.lib.json Cấu hình TypeScript cho thư viện của bạn (mã nguồn runtime hoặc được đóng gói)
  • tsconfig.spec.json Cấu hình TypeScript cho các bài kiểm thử của bạn
  • vitest.config.mts Cấu hình cho Vitest

Bạn cũng sẽ nhận thấy một số thay đổi đối với các tệp sau trong thư mục gốc workspace của bạn:

  • nx.json Cấu hình Nx được cập nhật để cấu hình plugin @nx/js/typescript cho dự án của bạn
  • tsconfig.base.json một alias TypeScript được thiết lập cho dự án của bạn để nó có thể được import bởi các dự án khác trong workspace của bạn
  • tsconfig.json một project reference TypeScript được thêm cho dự án của bạn

Thêm mã TypeScript của bạn vào thư mục src.

Vì dự án TypeScript của bạn là một ES Module, hãy đảm bảo viết các câu lệnh import với cú pháp ESM chính xác, tham chiếu rõ ràng phần mở rộng tệp:

index.ts
import { sayHello } from './hello.js';

Điểm vào cho dự án TypeScript của bạn là src/index.ts. Bạn có thể thêm các export ở đây cho bất kỳ thứ gì bạn muốn các dự án khác có thể import:

src/index.ts
export { sayHello } from './hello.js';
export * from './algorithms/index.js';

Import mã thư viện của bạn trong các dự án khác

Phần tiêu đề “Import mã thư viện của bạn trong các dự án khác”

TypeScript aliases cho dự án của bạn được cấu hình trong tsconfig.base.json của workspace, cho phép bạn tham chiếu dự án TypeScript của mình từ các dự án TypeScript khác:

packages/my-other-project/src/index.ts
import { sayHello } from '@my-scope/my-library';

Khi bạn thêm một câu lệnh import cho một dự án mới trong workspace của mình lần đầu tiên, bạn có thể sẽ thấy một lỗi trong IDE của mình tương tự như bên dưới:

Lỗi import
Terminal window
File '/path/to/my/workspace/packages/my-library/src/index.ts' is not under 'rootDir' '/path/to/my/workspace/packages/my-consumer'. 'rootDir' is expected to contain all source files.
File is ECMAScript module because '/path/to/my/workspace/package.json' has field "type" with value "module" ts(6059)
File '/path/to/my/workspace/packages/my-library/src/index.ts' is not listed within the file list of project '/path/to/my/workspace/packages/my-consumer/tsconfig.lib.json'. Projects must list all files or use an 'include' pattern.
File is ECMAScript module because '/path/to/my/workspace/package.json' has field "type" with value "module" ts(6307)

Điều này là do một project reference chưa được thiết lập, và dự án được import chưa được khai báo là một phụ thuộc workspace trong package.json của dự án bạn.

Workspace của bạn được cấu hình với các trình tạo đồng bộ quản lý cả hai cho bạn, vì vậy bạn không cần phải cấu hình chúng thủ công. Chỉ cần chạy lệnh sau và Nx sẽ thêm cấu hình cần thiết:

Terminal window
pnpm nx sync
Terminal window
NX The workspace is out of sync
[@nx/js:typescript-sync]: Some TypeScript configuration files are missing project references to the projects they depend on, contain stale project references, or have duplicate project references.
[@aws/nx-plugin:ts#sync]: Local project dependencies are out of sync. The following workspace dependencies will be declared:
packages/my-other-project/package.json:
- @my-scope/my-library: workspace:*
Syncing the workspace...
The workspace was synced successfully!

Trình tạo đồng bộ TypeScript của Nx thêm project reference, và trình tạo ts#sync của plugin khai báo dự án được import trong package.json của dự án bạn (workspace:* nếu trình quản lý package hỗ trợ giao thức workspace, * trên npm và yarn classic), để trình quản lý package liên kết dự án cục bộ khi cài đặt. Sau đó, lỗi trong IDE của bạn sẽ biến mất và bạn đã sẵn sàng sử dụng thư viện của mình.

Nếu bạn thêm các mục compilerOptions.paths tùy chỉnh trong tsconfig.json của một dự án, TypeScript sẽ ngừng kế thừa các alias workspace được định nghĩa trong tsconfig.base.json. Trình tạo ẩn ts#sync chạy trước target compile (được cấu hình trong nx.json) để sao chép bất kỳ alias cơ bản nào còn thiếu vào các tệp tsconfig.json, tsconfig.lib.jsontsconfig.app.json đã khai báo paths. Để từ chối, hãy xóa @aws/nx-plugin:ts#sync khỏi targetDefaults.compile.syncGenerators trong nx.json.

Mỗi dự án TypeScript khai báo các phụ thuộc runtime của bên thứ ba trong package.json riêng của nó. Các công cụ build và test dùng chung giữa các dự án được định nghĩa trong package.json gốc.

Để thêm một phụ thuộc runtime vào một dự án, hãy cài đặt nó vào dự án đó:

Terminal window
pnpm add some-npm-package --filter my-library

Bạn cũng có thể chạy lệnh add/install thuần túy của trình quản lý package từ trong thư mục của dự án.

Để thêm một công cụ dev dùng chung, hãy cài đặt nó ở thư mục gốc workspace:

Terminal window
pnpm add -Dw some-dev-tool

Đối với các trình quản lý package hỗ trợ catalogs (pnpm, yarnbun), các trình tạo ghi lại mỗi phiên bản trong catalog và tham chiếu nó bằng giao thức catalog: (ví dụ "zod": "catalog:"), vì vậy catalog là nguồn duy nhất của sự thật cho các phiên bản bất kể dự án nào khai báo phụ thuộc. Điều này giúp bạn tuân theo single version policy, tránh xung đột kiểu và nhiều bản sao của các package trong các bundle triển khai.

Khi bạn tự thêm một phụ thuộc mới, hãy giữ nó trong catalog:

Workspace thiết lập catalogMode: strict, vì vậy pnpm add ghi lại phiên bản trong catalog và tham chiếu nó tự động — không cần bước bổ sung.

Terminal window
pnpm add some-npm-package --filter my-library

Catalogs được bật theo mặc định. Để tắt chúng, hãy tạo workspace của bạn với --catalog false:

Terminal window
pnpm create @aws/nx-workspace my-project --catalog false

Hoặc đặt nó trong aws-nx-plugin.config.mts bất kỳ lúc nào:

aws-nx-plugin.config.mts
export default {
packageManager: {
catalogs: false,
},
} satisfies AwsNxPluginConfig;

Với catalogs bị vô hiệu hóa, các trình tạo ghi các phiên bản phụ thuộc trực tiếp vào package.json của mỗi dự án, và việc giữ các phiên bản căn chỉnh giữa các dự án là trách nhiệm của bạn.

Khai báo tất cả các phụ thuộc ở thư mục gốc

Phần tiêu đề “Khai báo tất cả các phụ thuộc ở thư mục gốc”

Nếu bạn thích khai báo mọi phụ thuộc chỉ trong package.json gốc (không có khai báo phụ thuộc cho từng dự án), hãy tắt quy tắc lint trong biome.json của workspace:

biome.json
{
"linter": {
"rules": {
"correctness": {
"noUndeclaredDependencies": "off"
}
}
}
}

Các dự án phân giải các package được cài đặt ở thư mục gốc tại thời điểm build, vì vậy mọi thứ vẫn build được — bạn từ bỏ các tệp kê khai cho từng dự án như một bản ghi chính xác về các phụ thuộc của mỗi dự án (điều này quan trọng nếu sau này bạn xuất bản một dự án hoặc tách repo).

Khi bạn sử dụng dự án TypeScript của mình làm mã runtime (ví dụ như handler cho một hàm AWS Lambda), bạn nên sử dụng một công cụ như Rolldown để đóng gói dự án của mình, vì điều này có thể tree-shake để đảm bảo rằng chỉ các phụ thuộc mà dự án của bạn thực sự tham chiếu mới được bao gồm.

Bạn có thể đạt được điều này bằng cách thêm một target như sau vào tệp project.json của bạn:

{
...
"targets": {
...
"bundle": {
"cache": true,
"executor": "nx:run-commands",
"outputs": ["{workspaceRoot}/dist/packages/my-library/bundle"],
"options": {
"command": "rolldown -c rolldown.config.ts"
}
},
},
}

Và thêm tệp rolldown.config.ts như sau:

rolldown.config.ts
import { defineConfig } from 'rolldown';
export default defineConfig([
{
input: 'src/index.ts',
output: {
file: '../../dist/packages/my-library/bundle/index.js',
format: 'cjs',
codeSplitting: false,
},
},
]);

Dự án TypeScript của bạn được cấu hình với một target build (được định nghĩa trong project.json), bạn có thể chạy nó qua:

Terminal window
pnpm nx build <project-name>

Trong đó <project-name> là tên đầy đủ của dự án của bạn.

Target build sẽ biên dịch, lint và kiểm thử dự án của bạn.

Kết quả build có thể được tìm thấy trong thư mục dist gốc trong workspace của bạn, bên trong một thư mục cho package và target của bạn, ví dụ dist/packages/<my-library>/tsc

Để build tất cả các dự án trong workspace của bạn, hãy chạy:

Terminal window
pnpm nx run-many --target build

Hoặc sử dụng lệnh viết tắt:

Terminal window
pnpm build

Vitest được cấu hình để kiểm thử dự án của bạn.

Các bài kiểm thử nên được viết trong các tệp .spec.ts hoặc .test.ts, đặt cùng vị trí trong thư mục src của dự án bạn.

Ví dụ:

  • Thư mụcsrc
    • hello.ts Mã nguồn thư viện
    • hello.spec.ts Kiểm thử cho hello.ts

Vitest cung cấp cú pháp giống Jest để định nghĩa các bài kiểm thử, với các tiện ích như describe, it, testexpect.

hello.spec.ts
import { sayHello } from './hello.js';
describe('sayHello', () => {
it('should greet the caller', () => {
expect(sayHello('Darth Vader')).toBe('Hello, Darth Vader!');
});
});

Để biết thêm chi tiết về cách viết kiểm thử và các tính năng như mocking phụ thuộc, hãy tham khảo tài liệu Vitest

Các bài kiểm thử sẽ chạy như một phần của target build cho dự án của bạn, nhưng bạn cũng có thể chạy chúng riêng biệt bằng cách chạy target test:

Terminal window
pnpm nx test <project-name>

Bạn có thể chạy một bài kiểm thử riêng lẻ hoặc một bộ kiểm thử bằng cách sử dụng cờ -t của Vitest. Truyền nó sau dấu phân cách -- để Nx chuyển tiếp nó cho Vitest thay vì sử dụng nó như tùy chọn --target của chính nó:

Terminal window
pnpm nx test <project-name> -- -t 'sayHello'

Các dự án TypeScript sử dụng Biome để lint và format. Biome được cấu hình trong tệp biome.json ở thư mục gốc workspace — các thay đổi đối với tệp này áp dụng cho tất cả các dự án TypeScript trong workspace của bạn và đảm bảo tính nhất quán.

Để gọi linter để kiểm tra dự án của bạn, bạn có thể chạy target lint.

Terminal window
pnpm nx lint <project-name>

Phần lớn các vấn đề linting hoặc formatting có thể được sửa tự động bằng cách chạy với tham số --configuration=fix.

Terminal window
pnpm nx lint <project-name> --configuration=fix

Tương tự, nếu bạn muốn sửa tất cả các vấn đề lint trong tất cả các package trong workspace của mình, bạn có thể chạy:

Terminal window
pnpm nx run-many --target lint --all --configuration=fix

Để tránh các vấn đề linting làm chậm bạn trong quá trình phát triển (đặc biệt nếu bạn có các vấn đề không thể tự động sửa trong dự án của mình), bạn có thể chạy build với cấu hình skip-lint:

Terminal window
pnpm nx run-many --target build --configuration=skip-lint

Điều này bỏ qua hoàn toàn target lint trong quá trình build.