Bundler เป็นเครื่องมือสร้างที่รวมโมดูล JavaScript หลาย ๆ โมดูลเข้าเป็นไฟล์เดียวหรือหลายไฟล์เพื่อใช้ในเบราว์เซอร์หรือแอปพลิเคชันมือถือ ตัวรวมโมดูลสมัยใหม่ (Webpack, Metro, Vite) ไม่เพียงแต่รวมไฟล์เท่านั้น แต่ยังทำการทรานสไพล์ การย่อขนาด และการปรับแต่งทรัพยากรอีกด้วย ตามข้อมูลจาก Webpack Concepts (2026) การกำหนดค่าตัวรวมโมดูลที่เหมาะสมช่วยลดขนาดบิลด์ลง 40–60% โดยไม่สูญเสียฟังก์ชันการทำงาน
ประเด็นสำคัญ
Bundler (ตัวรวมโมดูล) เป็นเครื่องมือบรรทัดคำสั่งที่รับจุดเริ่มต้น (entry point) — ไฟล์หลักของแอปพลิเคชัน — และ遍历 dependencies ทั้งหมดของมันแบบเรียกซ้ำ สร้างกราฟโมดูล ผลลัพธ์ที่ได้ ตัวรวมโมดูลจะสร้างไฟล์หนึ่งไฟล์หรือมากกว่าที่สามารถรวมในหน้า HTML หรือรันในแอปพลิเคชันมือถือ
เบราว์เซอร์ไม่รองรับระบบโมดูล JavaScript ในระดับแพลตฟอร์มเป็นเวลานาน Bundler แก้ปัญหานี้โดยเปลี่ยน import และ require นับร้อยเป็นไฟล์เดียว ทุกวันนี้ แม้จะมีการรองรับโมดูล ES ดั้งเดิมในเบราว์เซอร์ ตัวรวมโมดูลก็ยังทำงานเพิ่มเติม: การทรานสไพล์ JSX และ TypeScript, การย่อขนาดโค้ด, การแบ่งโค้ดสำหรับการโหลดแบบขี้เกียจ และ การแทนที่โมดูลร้อน (HMR) เพื่อเร่งการพัฒนา
ในการพัฒนามือถือ React Native ใช้ Metro เป็นตัวรวมโมดูลเริ่มต้น ในขณะที่ Flutter ใช้ระบบสร้างของตัวเองที่ใช้ Dart การเลือกตัวรวมโมดูลส่งผลโดยตรงต่อความเร็วในการพัฒนา ขนาดแอปพลิเคชัน และประสิทธิภาพรันไทม์
การรวมโมดูล ผ่านหลายขั้นตอน: การแยกวิเคราะห์ไฟล์นำเข้า การสร้างกราฟ dependencies การแปลงโมดูล และการสร้างไฟล์ส่งออก ในแต่ละขั้นตอน ตัวรวมโมดูลจะใช้ loaders เพื่อแปลงซอร์สโค้ดและ plugins เพื่อปรับแต่ง
ตัวรวมโมดูลเริ่มต้นจากจุดเริ่มต้น อ่านไฟล์ และสร้าง AST (Abstract Syntax Tree) จาก AST จะแยกคำสั่ง import และ require ทั้งหมดออกมา สำหรับแต่ละ import ที่พบ ตัวรวมโมดูลจะทำซ้ำกระบวนการแบบเรียกซ้ำจนกว่า dependencies ทั้งหมดจะถูกรวบรวมในกราฟเดียว
// การใช้งานตัวรวมโมดูลอย่างง่าย
const fs = require('fs');
const path = require('path');
function buildGraph(entry) {
const content = fs.readFileSync(entry, 'utf-8');
const imports = content.match(/require\(['"](.+?)['"]\)/g);
const modulePath = path.resolve(path.dirname(entry), imports[0]);
return { entry, content, deps: [buildGraph(modulePath)] };
}
หลังจากสร้างกราฟ ตัวรวมโมดูลจะใช้ loaders — การแปลงที่เปลี่ยนไฟล์เป็น JavaScript: TypeScript → JS, SCSS → CSS, JSX → ฟังก์ชัน JSX จากนั้น plugins จะทำการแปลงเพิ่มเติม: การย่อขนาด การแทรกรูปภาพ การสร้าง service worker
ตัวรวมโมดูล แบ่งออกเป็นสามยุค: คลาสสิก เฉพาะทาง และยุคใหม่ที่ใช้โมดูล ES แต่ละประเภทมีสถาปัตยกรรมและขอบเขตการใช้งานของตัวเอง
Webpack เป็นตัวรวมโมดูลที่แพร่หลายที่สุดพร้อมระบบนิเวศขนาดใหญ่ ข้อได้เปรียบหลักคือความยืดหยุ่น: loaders และ plugins นับพันครอบคลุมเกือบทุกสถานการณ์การสร้าง Parcel นำเสนอแนวทาง zero-config ตรวจจับการแปลงที่จำเป็นโดยอัตโนมัติตามนามสกุลไฟล์ ตัวรวมโมดูลทั้งสองรองรับการแบ่งโค้ดและ HMR
Metro ถูกสร้างขึ้นเฉพาะสำหรับ React Native และทำงานกับ JavaScript และ TypeScript เท่านั้น สถาปัตยกรรมของมันถูกปรับแต่งสำหรับการพัฒนามือถือ: รองรับ inline requires, การโหลดโมดูลแบบอะซิงโครนัส และการรวมกับเอนจิน Hermes Rollup มุ่งเน้นที่ไลบรารีและแพ็กเกจ npm สร้างผลลัพธ์โมดูล ES ที่สะอาดโดยไม่มี wrapper ที่ไม่จำเป็น
การเลือกตัวรวมโมดูลขึ้นอยู่กับแพลตฟอร์มและข้อกำหนดของโปรเจกต์ Webpack ใช้งานได้หลากหลายแต่ต้องการการกำหนดค่าโดยละเอียด Metro เป็นตัวเลือกเดียวสำหรับ React Native Vite มอบประสบการณ์การพัฒนาที่เร็วที่สุดด้วยโมดูล ES ดั้งเดิม
| คุณลักษณะ | Webpack | Metro | Vite |
|---|---|---|---|
| แพลตฟอร์ม | เว็บ, สากล | React Native | เว็บ, สากล |
| ความเร็วบิลด์ dev | ปานกลาง | สูง | สูงมาก |
| การแบ่งโค้ด | ใช่ | ใช่ | ใช่ |
| HMR | ใช่ | Fast Refresh | HMR ทันที |
| ระบบนิเวศ plugins | ใหญ่ | จำกัด | กำลังเติบโต |
| การกำหนดค่า | ซับซ้อน | ง่าย | ง่าย |
| รองรับ TypeScript | ผ่าน loaders | ในตัว | ในตัว |
Vite ใช้ esbuild สำหรับการรวม dependencies ล่วงหน้าและ Rollup สำหรับบิลด์โปรดักชัน ทำให้ความเร็วเพิ่มขึ้น 5–10 เท่าเมื่อเทียบกับ Webpack ในโหมดพัฒนา Metro ไม่รองรับเป้าหมายเว็บแต่ให้การรวมที่ราบรื่นกับบริดจ์ React Native และ Turbo Modules
การกำหนดค่า ของตัวรวมโมดูลกำหนดวิธีประมวลผลไฟล์ประเภทต่าง ๆ ตำแหน่งที่จะสร้างบิลด์ และการปรับแต่งใดที่จะใช้ ไฟล์กำหนดค่าทั่วไปประกอบด้วยจุดเริ่มต้น กฎสำหรับโมดูล plugins และการตั้งค่าผลลัพธ์
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true,
},
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: { loader: 'babel-loader', options: { presets: ['@babel/preset-react'] } },
},
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
],
},
plugins: [new HtmlWebpackPlugin({ template: './public/index.html' })],
devServer: { port: 3000, hot: true },
};
Metro ใช้ไฟล์แยก metro.config.js และ babel.config.js สำหรับการกำหนดค่า ต่างจาก Webpack การกำหนดค่าของ Metro ง่ายกว่ามากเนื่องจากตัวรวมโมดูลเชี่ยวชาญสำหรับ React Native และไม่ต้องการกำหนดค่า loaders สำหรับสไตล์หรือรูปภาพ
แม้แต่นักพัฒนาที่มีประสบการณ์ก็พบข้อผิดพลาดในการรวมโมดูล Duplicate module เป็นหนึ่งในปัญหาที่พบบ่อยที่สุด เมื่อ dependency เดียวกันปรากฏใน bundle หลายครั้งเนื่องจากเวอร์ชันไม่เข้ากันใน package.json Module not found เกิดขึ้นเมื่อพาธนำเข้าไม่ถูกต้องหรือไม่ได้ติดตั้งแพ็กเกจ
Metro ถูกจำกัดด้วยขนาด bundle สำหรับอุปกรณ์มือถือ เมื่อเกินขีดจำกัด 2–5 MB จะเกิดข้อผิดพลาด Unable to resolve module เนื่องจากหน่วยความจำไม่เพียงพอบนอุปกรณ์ วิธีแก้ไข — ใช้ inline requires และ RAM bundles สำหรับการโหลดโมดูลแบบขี้เกียจ Metro ยังไวต่อ symlink ดังนั้น monorepo ต้องการการกำหนดค่า watchFolders เพิ่มเติม
สำหรับ Webpack ปัญหาทั่วไปคือ Module parse failed ซึ่งเกิดขึ้นเมื่อไฟล์มีรูปแบบที่ไม่คาดคิดหรือไม่มี loader ที่จำเป็น การตรวจสอบนามสกุลไฟล์และเพิ่มกฎที่เหมาะสมใน module.rules แก้ปัญหาได้ การใช้ source-map-explorer ช่วยค้นหาโมดูลที่ซ้ำกันและ dependencies ที่ซ้ำซ้อนใน bundle สุดท้าย
บิลด์ที่ช้าเป็นหนึ่งในปัญหาหลักเมื่อทำงานกับตัวรวมโมดูล เพื่อเพิ่มความเร็ว ให้ใช้ การแคชแบบถาวร (persistent caching) ซึ่งบันทึกผลการแปลงโมดูลระหว่างการรัน Webpack 5 รองรับการแคชไฟล์ผ่าน cache: { type: 'filesystem' }, Vite ใช้ esbuild สำหรับการรวมล่วงหน้า และ Metro ใช้การแคชโมดูลในหน่วยความจำ นอกจากนี้ ระบุ exclude สำหรับ node_modules ใน loaders เพื่อหลีกเลี่ยงการประมวลผลแพ็กเกจที่พร้อมแล้วซ้ำ
การแบ่งโค้ด (Code splitting) แบ่ง bundle เป็นชิ้นส่วนที่โหลดตามความต้องการ ตัวรวมโมดูลต่าง ๆ นำกลยุทธ์นี้ไปใช้แตกต่างกัน Webpack รองรับการนำเข้าแบบไดนามิก import() สร้างชิ้นส่วนแยกสำหรับแต่ละโมดูล Metro ใช้ inline requires สำหรับการโหลดแบบรอ Vite แบ่ง vendor chunks และการนำเข้าแบบไดนามิกโดยอัตโนมัติโดยไม่ต้องกำหนดค่าเพิ่มเติม การเลือกกลยุทธ์ขึ้นอยู่กับข้อกำหนดของโปรเจกต์: สำหรับแอปพลิเคชันมือถือ bundle เริ่มต้นที่เล็กกว่าพร้อมการโหลดแบบขี้เกียจเป็นที่นิยม
สำหรับ code splitting ที่ทำงานถูกต้องใน React Native ต้องมีการกำหนดค่าเพิ่มเติม: Metro ต้องถูกกำหนดค่าสำหรับชิ้นส่วนอะซิงโครนัสผ่าน inlineRequires ใน Webpack และ Vite การแบ่งโค้ดทำงานทันทีเมื่อใช้ syntax แบบไดนามิก import() ซึ่งสร้างจุดแบ่งโดยอัตโนมัติ เพื่อประสิทธิภาพสูงสุด รวมการแบ่งโค้ดกับคำแนะนำการโหลดล่วงหน้าผ่าน <link rel="preload"> สำหรับชิ้นส่วนที่สำคัญ
คำถามที่พบบ่อย
สำหรับโปรเจกต์ง่าย ๆ ที่ไม่มี JSX, TypeScript หรือโมดูล CSS คุณสามารถใช้ โมดูล ES ดั้งเดิมในเบราว์เซอร์ อย่างไรก็ตาม สำหรับบิลด์โปรดักชัน ตัวรวมโมดูลให้การย่อขนาด tree shaking และการแบ่งโค้ด ซึ่งสำคัญต่อประสิทธิภาพ หากไม่มีตัวรวมโมดูล การรักษาสถาปัตยกรรมโมดูลาร์ในโปรเจกต์ใหญ่เป็นเรื่องยาก
สำหรับ React Native — Metro (ตัวเลือกเดียวที่รองรับ) สำหรับแอปพลิเคชันเว็บ — Vite สำหรับโปรเจกต์ใหม่ (เนื่องจากความเร็ว) หรือ Webpack สำหรับโปรเจกต์ที่มีอยู่แล้วพร้อมระบบนิเวศที่สมบูรณ์ สำหรับไลบรารีและแพ็กเกจ npm — Rollup เพราะสร้างผลลัพธ์โมดูล ES ที่สะอาด
ตัวรวมโมดูล กำหนดขนาด bundle JS สุดท้ายโดยตรง Webpack พร้อม tree shaking สามารถลดขนาดได้ 30–50% Metro สำหรับ React Native รองรับ Hermes bytecode ซึ่งลดขนาด 20–30% เมื่อเทียบกับ JavaScript ปกติ การแบ่งโค้ดช่วยให้โหลดโมดูลตามความต้องการ ลด bundle เริ่มต้น
สำหรับเว็บ ตัวรวมโมดูล สร้างโค้ดที่เข้ากันได้กับเบราว์เซอร์ต่าง ๆ และรองรับ CSS รูปภาพ และฟอนต์ สำหรับแพลตฟอร์มมือถือ Metro สร้างโค้ดสำหรับเอนจิน JavaScript (Hermes หรือ JSC) ไม่ประมวลผล CSS หรือ HTML และปรับแต่งบิลด์สำหรับทรัพยากรที่จำกัดของอุปกรณ์
ได้ โปรเจกต์บางโปรเจกต์ใช้ Webpack สำหรับส่วนเว็บและ Metro สำหรับ React Native — ตัวอย่างเช่น ใน monorepo ที่มีโค้ดเบสร่วมกัน อย่างไรก็ตาม สิ่งนี้ทำให้การกำหนดค่า CI/CD ซับซ้อนและต้องการการซิงค์เวอร์ชัน dependencies ขอแนะนำให้ใช้ตัวรวมโมดูลเดียวสำหรับทุกเป้าหมายหากเป็นไปได้
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม