โครงสร้างโฟลเดอร์ตามฟีเจอร์
จัดระเบียบโค้ดตามโดเมนของฟีเจอร์แทนประเภท วางเทสต์ สไตล์ และคอมโพเนนต์ที่เกี่ยวข้องไว้ใกล้กัน และบังคับขอบเขตด้วย eslint-plugin-boundaries
โครงสร้างโฟลเดอร์ตามฟีเจอร์ เป็นบทเรียน Frontend Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Frontend Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน
สองแนวทางในการจัดระเบียบโค้ด
คุณสามารถจัดกลุ่มโค้ด ตามประเภท (components/, hooks/, services/, types/) หรือ ตามฟีเจอร์ (auth/, checkout/, dashboard/ — แต่ละโฟลเดอร์มี components, hooks และอื่น ๆ ของตัวเอง) สำหรับแอปขนาดกลางถึงใหญ่ การจัดตามฟีเจอร์เหมาะกว่า
การจัดตามประเภท — กับดักค่าเริ่มต้น
โครงสร้างแบบบทเรียน React คลาสสิกจะจัดทุกอย่างตามประเภท ซึ่งขยายระบบได้ไม่ดี: การเปลี่ยนแปลงแต่ละไฟล์กระทบหลายโฟลเดอร์ที่ไม่เกี่ยวข้องกัน และการค้นหาโค้ด checkout ทั้งหมดหมายถึงการใช้ grep ไปทั่วทั้งโครงสร้าง
// Type-based (avoid for large apps):
src/
components/
Button.tsx
LoginForm.tsx
CartItem.tsx
hooks/
useAuth.ts
useCart.ts
services/
auth.ts
cart.ts
types/
User.ts
CartItem.tsโครงสร้างแบบจัดตามฟีเจอร์
จัดทุกอย่างที่เกี่ยวข้องกับฟีเจอร์หนึ่งไว้ในโฟลเดอร์เดียว ค้นหาได้ง่าย ลบได้ง่าย และทำความเข้าใจได้ง่าย
src/
features/
auth/
LoginForm.tsx
SignupForm.tsx
useAuth.ts
auth.service.ts
auth.types.ts
auth.test.tsx
cart/
CartItem.tsx
CartSummary.tsx
useCart.ts
cart.service.ts
cart.types.ts
shared/
components/
Button.tsx
hooks/
useDebounce.tsการวางโค้ดที่เกี่ยวข้องไว้ด้วยกันภายในฟีเจอร์
โฟลเดอร์ฟีเจอร์ประกอบด้วย components, hooks, services, types และ tests — โค้ดทั้งหมดที่จำเป็นสำหรับโดเมนนั้น นักพัฒนาคนใหม่ต้องการทำความเข้าใจ auth ใช่ไหม ให้เปิด auth/ ต้องการลบ auth ใช่ไหม ก็ลบทั้งโฟลเดอร์
โค้ดที่ใช้ร่วมกันกับโค้ดเฉพาะฟีเจอร์
โค้ดที่ใช้โดยฟีเจอร์ตั้งแต่ 2 ฟีเจอร์ขึ้นไปให้ย้ายไปไว้ใน shared/ (หรือ lib/) โค้ดที่ใช้โดยฟีเจอร์เดียวให้คงไว้ภายในฟีเจอร์นั้น อย่ารีบดึงโค้ดออกเพียงเพราะคิดว่า “อาจนำกลับมาใช้ใหม่ภายหลัง” ให้รอจนมีการใช้งานครั้งที่สองก่อน
กฎเกี่ยวกับขอบเขตของฟีเจอร์
ฟีเจอร์ไม่ควรนำเข้าจากกันโดยตรง หากฟีเจอร์สองรายการต้องใช้โค้ดร่วมกัน ให้ย้ายส่วนที่ใช้ร่วมกันไปไว้ใน shared/ หากต้องประสานงานกัน ให้ใช้เหตุการณ์หรือที่เก็บสถานะร่วมกันในระดับแอป
บังคับใช้ขอบเขตด้วย ESLint
ใช้ eslint-plugin-boundaries หรือ eslint-plugin-import เพื่อบังคับใช้กฎว่า ฟีเจอร์สามารถนำเข้าจาก shared ได้ แต่ไม่สามารถนำเข้าจากฟีเจอร์อื่น
// .eslintrc.json
{
"plugins": ["boundaries"],
"settings": {
"boundaries/elements": [
{ "type": "feature", "pattern": "src/features/*" },
{ "type": "shared", "pattern": "src/shared/*" }
]
},
"rules": {
"boundaries/element-types": ["error", {
"default": "disallow",
"rules": [
{ "from": "feature", "allow": ["shared"] },
{ "from": "shared", "allow": ["shared"] }
]
}]
}
}API สาธารณะสำหรับแต่ละฟีเจอร์
แต่ละฟีเจอร์ส่งออก API สาธารณะผ่าน features/auth/index.ts โค้ดส่วนอื่นนำเข้าจาก '@/features/auth' แทนการใช้เส้นทางย่อยภายใน ช่วยให้คุณปรับโครงสร้างภายในใหม่ได้โดยไม่ทำให้โค้ดที่นำไปใช้เกิดปัญหา
// features/auth/index.ts
export { LoginForm } from './LoginForm';
export { useAuth } from './useAuth';
export type { User, AuthState } from './auth.types';
// Consumers:
import { LoginForm, useAuth } from '@/features/auth';
// NOT: import { LoginForm } from '@/features/auth/LoginForm';การซ้อนฟีเจอร์ย่อย
ฟีเจอร์ขนาดใหญ่สามารถมีโฟลเดอร์ย่อยได้ เช่น dashboard/widgets/ และ dashboard/charts/ หลีกเลี่ยงการซ้อนลึกเกิน 2–3 ระดับ เพราะจะค้นหาได้ยาก
เส้นทางอยู่ที่ใด
หน้าและเส้นทางสามารถอยู่ในโฟลเดอร์ระดับบนสุดอย่าง pages/ หรือ routes/ ได้ โฟลเดอร์เหล่านี้ควรมีโค้ดน้อย โดยดึง components และ hooks จากฟีเจอร์มาประกอบเข้าด้วยกัน
src/
pages/
Dashboard.page.tsx // composes Dashboard widgets from features/dashboard/
Cart.page.tsx // composes from features/cart/
features/
shared/การย้ายโครงสร้างแอปที่มีอยู่
เริ่มจากฟีเจอร์ใหม่เท่านั้น — ใส่โค้ดใหม่ไว้ใน features/ อย่าปรับโครงสร้างทุกอย่างพร้อมกัน เมื่อคุณแก้ไขไฟล์เก่า ให้ค่อย ๆ ย้ายไฟล์เหล่านั้นไป กฎขอบเขตของ ESLint จะป้องกันไม่ให้โครงสร้างใหม่ถดถอย
เมื่อการจัดตามประเภทยังคงเหมาะสม
สำหรับแอปขนาดเล็กมาก (มี components น้อยกว่า 30 รายการ) หรือไลบรารี การจัดตามประเภทถือว่าใช้ได้ ให้เปลี่ยนไปใช้การจัดตามฟีเจอร์ทันทีที่มีโดเมนธุรกิจที่แยกจากกันชัดเจน เช่น auth, checkout, billing และ settings
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ประโยชน์หลักด้านการจัดระเบียบของการจัดกลุ่มโค้ดตามฟีเจอร์แทนการจัดตามประเภทไฟล์คืออะไร
สรุป: โครงสร้างแบบจัดตามฟีเจอร์
features/ มีโค้ดเฉพาะโดเมน ส่วน shared/ มีเครื่องมือที่ใช้ข้ามฟีเจอร์ แต่ละฟีเจอร์ส่งออก index.ts สาธารณะ ฟีเจอร์ไม่ได้นำเข้าจากกันเอง — นำเข้าได้เฉพาะจาก shared ใช้ eslint-plugin-boundaries เพื่อบังคับใช้กฎนี้ หน้าและเส้นทางทำหน้าที่ประกอบฟีเจอร์เข้าด้วยกัน ย้ายโครงสร้างทีละน้อย การจัดตามประเภทเหมาะสำหรับแอปขนาดเล็ก
คำถามที่พบบ่อย
บทเรียน “โครงสร้างโฟลเดอร์ตามฟีเจอร์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “โครงสร้างโฟลเดอร์ตามฟีเจอร์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Frontend Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Frontend Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “โครงสร้างโฟลเดอร์ตามฟีเจอร์”
จัดระเบียบโค้ดตามโดเมนของฟีเจอร์แทนประเภท วางเทสต์ สไตล์ และคอมโพเนนต์ที่เกี่ยวข้องไว้ใกล้กัน และบังคับขอบเขตด้วย eslint-plugin-boundaries คุณปฏิบัติ Frontend Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Frontend Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Frontend Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “โครงสร้างโฟลเดอร์ตามฟีเจอร์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Frontend Academy นี้ได้ไหม
ได้ บทเรียน Frontend Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การออกแบบแบบอะตอมิก: อะตอม โมเลกุล ออร์แกนิซึม
- การตั้งค่าโมโนรีโพด้วย Turborepo
- ไมโครฟรอนต์เอนด์: Module Federation
- โครงสร้างโฟลเดอร์ตามฟีเจอร์