N

Nokfa Docs

Current: framework-next.js

ไม่มีชื่อบทความ

การสร้าง Shared Packages (auth-lib, pdf-writer, ui-kit)

TL;DR

  • โฟลเดอร์ packages/* ใช้เก็บโค้ดที่แชร์ข้ามแอป เช่น auth-lib, pdf-writer, ui-kit
  • ทุกแพ็กเกจควรมี index.ts, tsconfig.json, package.json พร้อมตั้งชื่อ prefix @nokfa/
  • ใช้ private: true เพื่อไม่ให้ publish ออก npm โดยไม่ตั้งใจ
  • Import ข้ามแอปด้วย alias เช่น @nokfa/ui-kit, @nokfa/auth-lib
  • ตั้ง convention เดียวกันทุกแพ็กเกจเพื่อให้จัดการง่ายและ scale ได้ในอนาคต

1. โครงสร้างโดยรวม

packages/
├── auth-lib/
│   ├── src/
│   │   ├── index.ts
│   │   └── firebase-auth.ts
│   ├── package.json
│   └── tsconfig.json
├── pdf-writer/
│   ├── src/
│   │   ├── index.ts
│   │   └── generate-pdf.ts
│   ├── package.json
│   └── tsconfig.json
└── ui-kit/
    ├── src/
    │   ├── index.ts
    │   ├── Button.tsx
    │   └── Card.tsx
    ├── package.json
    └── tsconfig.json

2. ตั้งค่า package.json

📄 ตัวอย่าง packages/pdf-writer/package.json

{
  "name": "@nokfa/pdf-writer",
  "version": "0.1.0",
  "main": "src/index.ts",
  "private": true
}
  • ✅ ตั้งชื่อ prefix เป็น @nokfa/ เพื่อความเป็นระบบ
  • private: true เพื่อป้องกัน publish ขึ้น npm โดยไม่ได้ตั้งใจ
  • ❗ ถ้าจะ publish ขึ้น private registry ในอนาคต ค่อยเอา private: true ออก

3. ตั้งค่า tsconfig.json (เฉพาะแพ็กเกจ)

📄 ตัวอย่าง packages/pdf-writer/tsconfig.json

{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src",
    "composite": true
  },
  "include": ["src"]
}

📄 แนะนำให้เพิ่มใน root tsconfig.base.json

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@nokfa/*": ["packages/*/src"]
    }
  }
}

4. โครงสร้างไฟล์ index.ts

auth-lib/src/index.ts

export * from './firebase-auth';

pdf-writer/src/index.ts

export * from './generate-pdf';

ui-kit/src/index.ts

export { Button } from './Button';
export { Card } from './Card';

✅ แนวทางนี้ทำให้ consumer import ง่าย เช่น

import { Button } from '@nokfa/ui-kit';
import { signInWithGoogle } from '@nokfa/auth-lib';

5. ตัวอย่าง stub แต่ละแพ็กเกจ

📦 auth-lib

📄 firebase-auth.ts

import { signInWithPopup, GoogleAuthProvider } from 'firebase/auth';

export const signInWithGoogle = async (auth: any) => {
  const provider = new GoogleAuthProvider();
  return await signInWithPopup(auth, provider);
};

📦 pdf-writer

📄 generate-pdf.ts

import { PDFDocument } from 'pdf-lib';

export const generateSimplePdf = async (text: string): Promise<Uint8Array> => {
  const pdfDoc = await PDFDocument.create();
  const page = pdfDoc.addPage([500, 400]);
  page.drawText(text, { x: 50, y: 350 });
  return await pdfDoc.save();
};

📦 ui-kit

📄 Button.tsx

'use client';
import React from 'react';

export const Button = ({ children, ...props }) => (
  <button className="bg-blue-600 text-white px-4 py-2 rounded" {...props}>
    {children}
  </button>
);

📄 Card.tsx

'use client';
import React from 'react';

export const Card = ({ title, children }) => (
  <div className="border p-4 rounded shadow">
    <h3 className="font-bold text-lg mb-2">{title}</h3>
    <div>{children}</div>
  </div>
);

6. ตารางเปรียบเทียบ Shared Package แบบต่าง ๆ

ชื่อแพ็กเกจ ประเภท ใช้ใน จุดเด่น
auth-lib logic (non-UI) web, dashboard แยก auth logic ออกจาก UI
pdf-writer utility / binary dashboard ประมวลผล PDF ฝั่ง client หรือ server
ui-kit UI Component (React) web, dashboard ปรับดีไซน์กลาง เปลี่ยนที่เดียวได้ทุกที่

7. กลยุทธ์การใช้ shared packages ภายใน Nokfa

  • ไม่ใช้ npm publish สำหรับตอนนี้ → ทำงานภายใน workspace เท่านั้น
  • ✅ ใช้ alias @nokfa/* ผ่าน paths ใน tsconfig
  • ✅ ใช้ pnpm filter ทำ dev เฉพาะแพ็กเกจได้ เช่น:
$ pnpm --filter ui-kit dev
  • ✅ สร้าง CI ตรวจแต่ละแพ็กเกจแยกกันได้ง่ายในอนาคต
  • ✅ โค้ดทุกแพ็กเกจอยู่ใน workspace → sync กันหมดใน Monorepo

8. สรุปข้อดี‑ข้อเสียของการทำ Shared Packages

ด้าน ข้อดี ข้อเสีย
Maintenance โค้ดเป็นระบบ แก้ที่เดียว ใช้ได้หลายที่ ต้องวางโครงสร้างชัดเจน ไม่งั้นจะรกและ import สลับไปมา
Dev Experience import ด้วย alias สะดวก, ไม่ต้อง copy/paste โค้ด ต้องคอยดูแลให้เวอร์ชัน match ทุกแพ็กเกจใน workspace
Performance ใช้ TurboRepo cache ข้าม build ได้ดี บางแพ็กเกจต้อง build ทุกครั้งหากมี dependency ลึก
Team Scaling แยกความรับผิดชอบทีมได้ตามแพ็กเกจ ต้องมี convention เดียวกัน, ไม่งั้นการแชร์จะกลายเป็นภาระ