การขยาย Tailwind ในโมโนรีโพ
ใช้ tailwind.config.js เดียวร่วมกันในหลายแพ็กเกจของโมโนรีโพ ใช้พรีเซ็ตสำหรับโทเค็นร่วม และจัดการส่วนขยายเฉพาะพื้นที่ทำงาน
การขยาย Tailwind ในโมโนรีโพ เป็นบทเรียน Tailwind CSS Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Tailwind CSS Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Tailwind CSS Academy มีบทเรียนทั้งหมด 4 บทเรียน
พื้นฐานโมโนรีโพสำหรับ Tailwind
โมโนรีโพ คือรีโพซิทอรีเดียวที่เก็บหลายแพ็กเกจหรือแอปพลิเคชัน และจัดการด้วยเครื่องมืออย่าง Turborepo, Nx หรือเวิร์กสเปซของ pnpm เมื่อมีหลายแอปใช้ Tailwind ภายในโมโนรีโพ การใช้การกำหนดค่าร่วมกันจึงมีความสำคัญ หากไม่ใช้ร่วมกัน แต่ละแอปจะทำซ้ำโทเค็นสี แบบอักษร และการกำหนดค่าปลั๊กอิน ทำให้ค่อย ๆ แตกต่างกันจนส่วนติดต่อผู้ใช้ของแต่ละผลิตภัณฑ์ไม่สอดคล้องกัน
monorepo/
├── apps/
│ ├── web/ # Next.js marketing site
│ └── dashboard/ # React admin app
├── packages/
│ ├── ui/ # Shared component library
│ └── tailwind-config/ # ← Shared Tailwind config
├── package.json # Workspace root
└── turbo.jsonการสร้างแพ็กเกจการกำหนดค่าร่วม
แยกการกำหนดค่า Tailwind ออกเป็นแพ็กเกจเฉพาะ ซึ่งโดยทั่วไปตั้งชื่อว่า @repo/tailwind-config หรือ @acme/tailwind-config แพ็กเกจนี้ส่งออกออบเจ็กต์การกำหนดค่าพื้นฐานที่แต่ละแอปซึ่งนำไปใช้จะนำเข้าและขยายต่อ แพ็กเกจร่วมจะอยู่ใน packages/tailwind-config/ พร้อมไฟล์ package.json ของตนเองที่ระบุว่าเป็นการพึ่งพาภายใน
// packages/tailwind-config/package.json
{
"name": "@acme/tailwind-config",
"version": "0.0.1",
"private": true,
"main": "./tailwind.config.js",
"devDependencies": {
"tailwindcss": "^3.4.0"
}
}
// packages/tailwind-config/tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
colors: {
brand: { 500: '#3b82f6', 900: '#1e3a8a' },
},
},
},
plugins: [],
};การใช้การกำหนดค่าร่วม
แต่ละแอปนำเข้าการกำหนดค่าร่วมโดยใช้ require แล้วกระจายหรือผสานเข้ากับการแทนที่เฉพาะแอป การกำหนดค่า tailwind.config.js ของแอปจะเพิ่มเส้นทาง content ของตนเอง เนื่องจากเส้นทางเนื้อหาจะเฉพาะกับแต่ละแอปเสมอ รวมถึงการขยายใด ๆ ที่มีเฉพาะในแอปนั้น การกำหนดค่าร่วมจะจัดการโทเค็นธีมและปลั๊กอินที่ใช้ร่วมกันทั้งหมด
// apps/web/tailwind.config.js
const sharedConfig = require('@acme/tailwind-config');
/** @type {import('tailwindcss').Config} */
module.exports = {
// Merge shared config
...sharedConfig,
// App-specific content paths (NEVER shared — paths differ per app)
content: [
'./src/**/*.{js,ts,jsx,tsx}',
'./public/**/*.html',
],
theme: {
...sharedConfig.theme,
extend: {
...sharedConfig.theme.extend,
// App-specific extensions
backgroundImage: {
'hero-gradient': 'linear-gradient(to bottom, #eff6ff, #ffffff)',
},
},
},
};การใช้พรีเซ็ตของ Tailwind
ระบบ preset ของ Tailwind เป็นกลไกที่รองรับอย่างเป็นทางการสำหรับการใช้การกำหนดค่าร่วมกัน พรีเซ็ตคือออบเจ็กต์ที่ส่งผ่านอาร์เรย์ presets ในการกำหนดค่าของแอปที่นำไปใช้ ต่างจากการกระจายออบเจ็กต์การกำหนดค่า Tailwind จะผสานพรีเซ็ตอย่างชาญฉลาด โดยการขยายธีมจะถูกผสานแบบลึก ปลั๊กอินจะถูกรวมต่อกัน และอาร์เรย์เนื้อหาจะถูกรวมโดยไม่ต้องกระจายด้วยตนเอง
// packages/tailwind-config/tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
theme: {
extend: {
colors: { brand: { 500: '#3b82f6' } },
},
},
plugins: [require('@tailwindcss/forms')],
};
// apps/dashboard/tailwind.config.js
module.exports = {
presets: [require('@acme/tailwind-config')], // ← official preset
content: ['./src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
// Deep-merged with preset's theme.extend automatically
spacing: { 18: '4.5rem' },
},
},
};เส้นทางเนื้อหาของแพ็กเกจส่วนติดต่อผู้ใช้ร่วม
ข้อผิดพลาดสำคัญในโมโนรีโพคือ หากคุณมีไลบรารีคอมโพเนนต์ packages/ui ที่ส่งออกคอมโพเนนต์ซึ่งใช้คลาส Tailwind แอปที่นำแพ็กเกจนี้ไปใช้ต้องรวมไฟล์ของแพ็กเกจนั้นไว้ในอาร์เรย์ content ด้วย มิฉะนั้นกลไก JIT จะไม่สแกนคอมโพเนนต์ร่วม และคลาสที่ใช้ในนั้นจะถูกลบออกจากบิลด์สำหรับใช้งานจริง
// apps/web/tailwind.config.js
module.exports = {
presets: [require('@acme/tailwind-config')],
content: [
// App's own files
'./src/**/*.{js,ts,jsx,tsx}',
// ⬇ CRITICAL: include shared UI package files
'../../packages/ui/src/**/*.{js,ts,jsx,tsx}',
],
};การตั้งค่าการพึ่งพาของเวิร์กสเปซ
ในโมโนรีโพของเวิร์กสเปซ pnpm หรือ npm ให้เพิ่มแพ็กเกจการกำหนดค่าร่วมเป็นการพึ่งพาสำหรับการพัฒนาโดยใช้โพรโทคอลเวิร์กสเปซ วิธีนี้จะสร้างลิงก์เชิงสัญลักษณ์ไปยังแพ็กเกจภายในเครื่องโดยไม่ต้องเผยแพร่ไปยัง npm ไฟล์ package.json ของแอปที่นำไปใช้จะแสดงรายการ @acme/tailwind-config: workspace:* และเครื่องมือบิลด์จะค้นหาแพ็กเกจภายในเครื่องให้โดยอัตโนมัติ
// apps/web/package.json
{
"name": "web",
"devDependencies": {
"@acme/tailwind-config": "workspace:*",
"tailwindcss": "^3.4.0"
}
}
// Install all workspace packages from the monorepo root:
pnpm install
# or
npm install --workspacesการแคชบิลด์ Tailwind ด้วย Turborepo
ในโมโนรีโพของ Turborepo ให้กำหนดค่า pipeline ใน turbo.json เพื่อแคชเอาต์พุตจากบิลด์ Tailwind เนื่องจากการกำหนดค่าร่วมเป็นการพึ่งพาของบิลด์แต่ละแอป การเปลี่ยนแปลงใน packages/tailwind-config จึงทำให้แคชบิลด์ของแอปที่นำไปใช้ทั้งหมดไม่ถูกต้องได้อย่างถูกต้อง วิธีนี้ป้องกันไม่ให้ CSS ที่ค้างอยู่ในแคชถูกนำไปใช้งานเมื่อระบบการออกแบบมีการอัปเดต
// turbo.json
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "dist/**", "!.next/cache/**"]
},
"type-check": {
"dependsOn": ["^build"]
}
}
}
# Build only what has changed since last run:
npx turbo build
# Turbo caches CSS output and invalidates when tailwind-config changesการจัดการความแตกต่างของเส้นทางเนื้อหา
เส้นทางเนื้อหาเป็นการกำหนดค่าเพียงอย่างเดียวที่ไม่สามารถใช้ร่วมกันได้ เพราะต้องกำหนดเฉพาะภายในแต่ละแอป โครงสร้างไดเรกทอรีของแต่ละแอปแตกต่างกัน อย่าเผลอนำเส้นทางเนื้อหาไปไว้ในการกำหนดค่าร่วม เพราะอาจทำให้พลาดไฟล์หรือสแกนกว้างเกินไป การกำหนดค่าร่วมควรส่งออกเฉพาะธีม ปลั๊กอิน และพรีเซ็ตเท่านั้น ส่วนเนื้อหาต้องกำหนดภายในไฟล์การกำหนดค่าของแต่ละแอปที่นำไปใช้เสมอ
// packages/tailwind-config/tailwind.config.js
// ⚠ DO NOT include content paths here
module.exports = {
// content: [] ← Leave this OUT of the shared config
theme: {
extend: { colors: { brand: { 500: '#3b82f6' } } },
},
plugins: [],
};
// Each app defines its own content:
// apps/web: './src/**/*.{js,ts,jsx,tsx}'
// apps/dashboard: './pages/**/*.tsx', './components/**/*.tsx'การกำหนดเวอร์ชันของการกำหนดค่าร่วม
แม้แพ็กเกจการกำหนดค่าร่วมจะเป็นแพ็กเกจส่วนตัวและไม่เคยเผยแพร่ไปยัง npm ก็ควรจัดการเวอร์ชันอย่างมีวินัย ให้เพิ่มเวอร์ชันใน package.json ทุกครั้งที่มีการเปลี่ยนแปลงที่ทำให้เข้ากันไม่ได้ เช่น การลบสี การเปลี่ยนชื่อโทเค็น หรือการลบปลั๊กอิน ผู้ใช้พรีเซ็ตจะสามารถล็อกไว้ที่เวอร์ชันหนึ่งและอัปเกรดอย่างตั้งใจ แทนที่จะปล่อยให้การเปลี่ยนแปลงที่ทำให้เข้ากันไม่ได้เผยแพร่ไปยังทุกแอปพร้อมกันโดยไม่รู้ตัว
// packages/tailwind-config/package.json
{
"name": "@acme/tailwind-config",
"version": "1.3.0", // ← bump on breaking changes
"private": true,
"main": "./tailwind.config.js"
}
// apps/dashboard/package.json — pin to a specific version
{
"devDependencies": {
"@acme/tailwind-config": "workspace:^1.2.0" // pin minor version
}
}การทดสอบการเปลี่ยนแปลงการกำหนดค่าร่วม
ก่อนรวมการเปลี่ยนแปลงเข้ากับการตั้งค่า Tailwind ที่ใช้ร่วมกัน ให้เรียกใช้การทดสอบการถดถอยทางภาพกับแอปทั้งหมดที่นำไปใช้ การเปลี่ยนสีแบรนด์หรือการลบค่าระยะห่างจะส่งผลต่อทุกแอปพร้อมกัน ให้สร้างแอปทั้งหมดใน CI (turbo build) และเปรียบเทียบภาพหน้าจอของหน้าสำคัญ ถือว่าการเปลี่ยนแปลงการตั้งค่าเป็นการเปลี่ยนแปลงที่อาจทำให้แอปอื่นเสียหายข้ามแอป และสื่อสารการเปลี่ยนแปลงเหล่านี้ไว้ในบันทึกการเปลี่ยนแปลง
# Run all affected builds when tailwind-config changes
npx turbo build --filter='...[origin/main]'
# Turborepo detects which apps depend on the changed package
# and builds only those apps
# Run visual regression on changed apps:
npx playwright test --project=web
npx playwright test --project=dashboardการผสานการทำงานของ Storybook ในโมโนเรโป
หากใช้ Storybook ในแพ็กเกจ UI ที่ใช้ร่วมกันเพื่อจัดทำเอกสารส่วนประกอบ ให้ตั้งค่า Storybook ให้ใช้ค่าตั้งต้น Tailwind เดียวกัน เพิ่มส่วนเสริม Tailwind ของ Storybook (@storybook/addon-styling-webpack หรือส่วนเสริมที่เทียบเท่าสำหรับเฟรมเวิร์กนั้น) และชี้ไปยังการตั้งค่าที่ใช้ร่วมกัน วิธีนี้ทำให้ส่วนประกอบแสดงผลใน Storybook ด้วยโทเค็นเดียวกับที่ใช้ในแอป
// packages/ui/.storybook/main.js
module.exports = {
addons: ['@storybook/addon-styling-webpack'],
framework: '@storybook/react-webpack5',
};
// packages/ui/.storybook/preview.js
import '../src/styles/globals.css'; // imports Tailwind
// packages/ui/tailwind.config.js
module.exports = {
presets: [require('@acme/tailwind-config')],
content: ['./src/**/*.{js,ts,jsx,tsx}'],
};ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจแนวคิด Tailwind CSS Mastery จากบทเรียนนี้
ทบทวนบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้เกี่ยวกับ การสร้างแพ็กเกจการตั้งค่า Tailwind ที่ใช้ร่วมกัน โดยใช้ระบบค่าตั้งต้นอย่างเป็นทางการเพื่อผสานการตั้งค่าเชิงลึกอย่างชาญฉลาด การรวมไฟล์แพ็กเกจ UI ที่ใช้ร่วมกันไว้ในเส้นทางเนื้อหา เพื่อป้องกันการลบคลาสที่ใช้งานอยู่ และ การถือว่าการเปลี่ยนแปลงการตั้งค่าเป็นการเปลี่ยนแปลงที่อาจทำให้แอปอื่นเสียหายข้ามแอป พร้อมการกำหนดเวอร์ชันและการทดสอบการถดถอยทางภาพ บทถัดไป เราจะวางระบบการออกแบบ Tailwind อย่างสมบูรณ์สำหรับโครงการสรุปยอด
เรียนรู้ HTML ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “การขยาย Tailwind ในโมโนรีโพ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การขยาย Tailwind ในโมโนรีโพ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Tailwind CSS Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Tailwind CSS Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การขยาย Tailwind ในโมโนรีโพ”
ใช้ tailwind.config.js เดียวร่วมกันในหลายแพ็กเกจของโมโนรีโพ ใช้พรีเซ็ตสำหรับโทเค็นร่วม และจัดการส่วนขยายเฉพาะพื้นที่ทำงาน คุณปฏิบัติ Tailwind CSS Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Tailwind CSS Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Tailwind CSS Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การขยาย Tailwind ในโมโนรีโพ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Tailwind CSS Academy นี้ได้ไหม
ได้ บทเรียน Tailwind CSS Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การจัดระเบียบไฟล์และโฟลเดอร์
- การอยู่ร่วมกับ CSS เดิม
- CSS Modules และ Tailwind
- การขยาย Tailwind ในโมโนรีโพ