Logo Zephyrnet

Chia sẻ mã hiệu quả với Lerna

Ngày:

Xin chào Codementor! Hôm nay tôi muốn cùng các bạn khám phá cách thiết lập monorepo với lerna. Chúng tôi sẽ xây dựng một monorepo với gói giao diện người dùng, gói phụ trợ và gói chung sẽ chia sẻ các loại và phương thức chung giữa hai loại. Tôi sẽ trình bày rõ ràng vấn đề mà chúng tôi gặp phải, một giải pháp kém đẹp mắt và giải pháp tối ưu hóa của chúng tôi bằng Lerna.

Vấn đề

Bởi vì tôi yêu Bản đánh máy (và bạn cũng nên như vậy!), Tôi không thể không xác định các giao diện đối tượng thực sự tuyệt vời để tôi luôn biết mình đang làm việc với cái gì.
Ảnh chụp màn hình 2022-12-16 lúc 04.38.32.png
Đây là người dùng tuyệt vời của tôi. Tôi cũng muốn thiết lập một hàm trả về tên đầy đủ của người dùng.
Ảnh chụp màn hình 2022-12-16 lúc 04.40.32.png
Vậy vấn đề là gì? Chà, giả sử tôi sử dụng mã này trong phần phụ trợ của mình để thiết lập API và xác định cách nhập chính xác. Đó là cách viết API đúng đắn! Nhưng điều gì sẽ xảy ra nếu tôi CŨNG muốn sử dụng giao diện và phương thức để đảm bảo tôi đang tìm nạp đúng loại và cho mục đích hiển thị trên giao diện người dùng? giờ thì sao?

Một giải pháp lộn xộn

Hãy lấy CopyPaste tốt của bạn ra và có một common thư mục ở cả giao diện người dùng và phụ trợ với cùng một mã. Nghe có vẻ hay, nhưng nếu Người dùng của tôi trở nên phức tạp hơn thì sao? Tôi muốn thêm danh sách sở thích, địa chỉ email, mật khẩu. Bây giờ, tôi cần nhớ cập nhật mã ở 2 nơi. Và nếu bây giờ tôi có một máy chủ báo cáo phục vụ cùng một mục đích thì sao?
Danh sách đi về.
Giải pháp là không thể thực hiện được. Chúng ta làm gì bây giờ?

Một giải pháp Lerna

Chúng tôi sử dụng Monorepo! Về cơ bản, đây là một kho lưu trữ duy nhất cho tất cả mã của bạn. Điều này cho phép các kho lưu trữ khác nhau chia sẻ mã chung, như thể đó là thư viện npm. Lerna thực hiện tất cả các liên kết tượng trưng và phép thuật đằng sau hậu trường. Hãy xem nó hoạt động như thế nào!

Thành lập

Mở một thư mục trống trong trình chỉnh sửa mã yêu thích của bạn. Sau đó chạy
npx lerna init
npm i

Ảnh chụp màn hình 2022-08-29 lúc 08.30.10.png

Điều này đã thiết lập một kho lưu trữ lerna với một packages thư mục và một lerna.json tập tin cấu hình. Bạn không cần phải làm phiền nó nếu bạn không cần thiết.

trong packages, tạo ba thư mục: common, frontend, backend
Hãy đi vào common bằng cách gõ vào thiết bị đầu cuối: cd packages/common
Sau đó, khởi tạo kho lưu trữ npm bằng cách sử dụng npm init -y.
Trong mới được tạo ra package.json, thay đổi tên của dự án thành một cái gì đó như thế này:
Ảnh chụp màn hình 2022-12-16 lúc 06.56.17.png
với định dạng “@{projectName}/{module}” như tôi đã làm. Đây là quy ước tiêu chuẩn và cách thực hành tốt nhất cho monorepos.

Tôi đã thêm một tập lệnh “dev-common” để biên dịch bản đánh máy và theo dõi các thay đổi

Lưu ý: “main” cần trỏ tới “dist/index.js”, như chúng ta sẽ thiết lập sau

Bây giờ, vẫn có điểm chung, hãy cài đặt các phần phụ thuộc: npm i typescript
Và hãy tạo 3 tệp: index.ts, types.ts, functions.ts

In types.ts, thêm vào:

interface User { firstName: string; lastName: string;
} export { User };

va cho functions.ts:

import { User } from "./types"; const getUserFullName = (user: User) => `${user.firstName} ${user.lastName}`; export { getUserFullName };

va cho index.ts:

export * from "./functions";
export * from "./types";

Cuối cùng, chúng ta cần một tsconfig.json tập tin:

{ "compilerOptions": { "target": "ES5", "module": "commonjs", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "moduleResolution": "node", "rootDir": "src", "outDir": "dist", "declaration": true, "declarationMap": true, "sourceMap": true }, "$schema": "https://json.schemastore.org/tsconfig", "display": "Recommended"
}

Lưu ý: đảm bảo Mục tiêu là ES5 để chúng tôi có thể biên dịch javascript cấp thấp, đồng thời các khóa khai báo và khai báo Bản đồ là đúng để nó tạo các tệp khai báo TypeScript cho chúng tôi.

Hãy quay trở lại thư mục gốc (cd ../..) và trong package.json của chúng tôi xác định một tập lệnh:

 "dev-common": "lerna run dev-common",

và hãy chạy nó: npm run dev-common

Ảnh chụp màn hình 2022-12-16 lúc 07.01.02.png

Hy vọng rằng chúng ta có được điều này. Lưu ý rằng nó xây dựng một dist thư mục trong gói chung

Tuyệt vời! Chúng tôi đã thiết lập một số điều chung. Bây giờ chúng ta đi vào thư mục phụ trợ:
cd ../backend
npm init -y
và thay đổi tên dự án là tốt.
Ảnh chụp màn hình 2022-08-29 lúc 08.48.56.png

Hãy tạo một máy chủ nhanh:

npm i express @types/express typescript
npm i --save-dev nodemon ts-node

Sao chép và dán tsconfig.json từ common trong backend là tốt.
Tạo một tệp index.ts:

import { User } from "@seanh/common";
import express from "express"; const users: User[] = [ { firstName: "Sean", lastName: "Hurwitz" }, { firstName: "Batman", lastName: "Michaels" },
]; const app = express(); app.use(express.json()); app.get("/", (req, res) => { res.send("Hello!");
}); app.get("/users", (req, res) => { res.json(users);
}); app.listen(2050, () => { console.log(`server up on http://localhost:${2050}`);
});

Lưu ý cách chúng tôi nhập giao diện Người dùng từ @seanh/common. Nhưng làm sao nó biết được? Bởi vì trong package.json, Đây là những gì bạn làm:

{ "name": "@seanh/backend", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev-backend": "tsc -w & nodemon dist/index.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "@seanh/common": "1.0.0", "@types/express": "^4.17.13", "express": "^4.18.1", "typescript": "^4.8.2" }, "devDependencies": { "nodemon": "^2.0.19", "ts-node": "^10.9.1" }
}

Tôi đã thêm thủ công dòng đầu tiên vào phần phụ thuộc ở đó. Đảm bảo phiên bản khớp chính xác với phiên bản trong package.json của common thư mục. (Ngoài ra, tôi đã thêm một tập lệnh đơn giản để khởi động máy chủ).
Bây giờ, hãy đi vào phần gốc của dự án trong terminal. bạn có thể sử dụng một trong hai cd ../.. hoặc mở một thiết bị đầu cuối mới. Sau đó chạy:
npx lerna bootstrap
Điều này nhắc lerna tạo liên kết tượng trưng, ​​liên kết tượng trưng của các gói khác nhau trong kho lưu trữ, theo sự phụ thuộc của chúng với nhau. Bởi vì thư mục chung là phần phụ thuộc của thư mục phụ trợ, lerna sẽ liên kết nó với phụ trợ và cung cấp cho nó hành vi của một gói như thể nó được tải xuống từ npm!

trên gói gốc.json, bạn có thể thêm tập lệnh:
"dev-backend": "lerna run dev-backend"
Điều này sẽ chạy tập lệnh dev-backend trong bất kỳ gói nào có nó (trong trường hợp này, nó chỉ là phần phụ trợ)

Chạy cái này hy vọng sẽ khởi động máy chủ và sẽ đến localhost sẽ trả lại bạn:
Ảnh chụp màn hình 2022-08-29 lúc 09.33.42.png
Như vậy các bạn có thể thấy, thư mục phụ trợ đã sử dụng thành công mã thư mục chung của chúng ta!
Hãy thêm giao diện người dùng ngay bây giờ. đi đến frontend thư mục:
cd packages/frontend
Tôi sẽ chỉ tạo một ứng dụng React để dễ sử dụng, nhưng bạn thực sự có thể làm bất cứ điều gì:

npx create-react-app --template typescript .

(ghi: bạn có thể gặp lỗi vì lerna đã thêm package.json vào thư mục frontend rồi. Chỉ cần xóa tệp ngay bây giờ và chạy lại ứng dụng tạo-phản ứng)

Dọn dẹp App.tsx và thêm mã này:

import { getUserFullName, User } from "@seanh/common";
import { useEffect, useState } from "react"; function App() { const [users, setUsers] = useState<User[]>([]); useEffect(() => { fetch("http://localhost:2050/users") .then((r) => r.json()) .then((r) => setUsers(r)); }, []); return ( <div> <h1>Users</h1> <ul> {users.map((user) => ( <li key={user.firstName}>{getUserFullName(user)}</li> ))} </ul> </div> );
} export default App; 

nhớ thêm "@seanh/common": "1.0.0", trong các phụ thuộc của frontend package.json.

Quay trở lại thư mục gốc (cd ../..) và chạy npx lerna bootstrap một lần nữa
Tôi đã thêm tập lệnh này vào thư mục gốc package.json:
"dev-frontend": "lerna run start"

Bây giờ bạn có thể chạy npm run dev-frontend và hy vọng ứng dụng sẽ hoạt động!

Ảnh chụp màn hình 2022-12-16 lúc 07.08.54.png

thì đấy. Giao diện người dùng đang sử dụng các loại và phương thức từ thư viện chung!

Kết luận

Bài viết ngắn này giới thiệu các monorepos và cách thiết lập chúng để tái sử dụng mã. Hãy cho tôi biết suy nghĩ của bạn trong phần bình luận bên dưới!

tại chỗ_img

Tin tức mới nhất

tại chỗ_img