Now.js Framework Documentation

Now.js Framework Documentation

Bundle ของโปรเจ็ค — แยกโค้ดเฉพาะโปรเจ็คออกจาก Now/

TH 06 Nov 2026 02:55

Bundle ของโปรเจ็ค — แยกโค้ดเฉพาะโปรเจ็คออกจาก Now/

ภาพรวม

โฟลเดอร์ Now/ (ซอร์ส Now/js, Now/css และบันเดิล Now/dist) กับ vite.config.js เหมือนกันทุกโปรเจ็ค
แก้ที่ต้นทาง (nowjs → adminframework) แล้วกระจายไปทุกโปรเจ็ค ห้ามมีไฟล์ของโปรเจ็คใดโปรเจ็คหนึ่งปนอยู่

โค้ดที่โปรเจ็คเดียวใช้และต้อง build เป็นบันเดิลของตัวเอง (เช่น designer, timeline) ให้อยู่ที่

js/components/<ชื่อ>/
├── build.json      ← บอก vite ว่าจะ build อย่างไร
├── entry.js        ← จุดเริ่มของบันเดิล (import ไฟล์อื่นและ CSS)
├── *.js · *.css    ← ซอร์สของบันเดิล
js/dist/            ← ผลการ build ของทุกบันเดิลในโปรเจ็คนี้

ไม่ต้องแก้ vite.config.js — เมื่อสั่ง BUILD_TARGET=<ชื่อ> แล้วไม่ใช่บันเดิลของ Now.js
vite จะอ่าน js/components/<ชื่อ>/build.json เองและ build ลง js/dist/

build.json

{
  "entry": "entry.js",
  "name": "now.timeline.min.js",
  "css": "now.timeline.min.css",
  "libName": "NowTimeline"
}
คีย์ ความหมาย
entry ไฟล์เริ่มต้น เทียบกับโฟลเดอร์ของบันเดิล (ไม่ใส่ = entry.js)
name ชื่อไฟล์ JS ใน js/dist/
css ชื่อไฟล์ CSS ใน js/dist/ (มีเมื่อ entry import CSS)
libName ชื่อ global ของ IIFE — export default ของ entry จะอยู่ที่ window[libName]

ชื่อโฟลเดอร์ต้องไม่ซ้ำกับบันเดิลของ Now.js (core, table, graph, serviceworker, queue,
eventcalendar, editor, formbuilder, syntaxhighlighter) เพราะชื่อเหล่านั้นถูกใช้ก่อนเสมอ

คำสั่ง build

เพิ่ม script ใน package.json ของโปรเจ็คนั้น (ไฟล์นี้ต่างกันได้ในแต่ละโปรเจ็ค)

"build:timeline": "cross-env BUILD_TARGET=timeline vite build"

แล้วต่อท้าย "build" ด้วย && npm run build:timeline ถ้าต้องการให้ build พร้อมกันทั้งหมด

บันเดิลของ Now.js ใช้ emptyOutDir ล้าง Now/dist ทุกครั้งที่ build core ส่วน js/dist ไม่ถูกล้าง
บันเดิลของโปรเจ็คจึงไม่หายตอน build core หรือตอนกระจาย Now/ ใหม่

การโหลดบันเดิล

index.php เป็นไฟล์กลางที่เหมือนกันทุกโปรเจ็ค จึงไม่โหลดบันเดิลของโปรเจ็ค —
ให้โมดูลที่ใช้โหลดเองจาก admin.js ของตัวเอง และส่ง ?v= ของ admin.js ต่อให้บันเดิล
(service worker เสิร์ฟไฟล์ .js ที่ไม่มี query แบบ cache-first ไฟล์ที่ build ใหม่จะไม่ถูกโหลด)

const docDesignerBundle = (() => {
  const src = document.currentScript?.src || '';
  const base = src.replace(/modules\/docdesigner\/admin\.js.*$/, '');
  if (!base) return Promise.resolve();
  const query = src.includes('?') ? src.slice(src.indexOf('?')) : '';

  const css = document.createElement('link');
  css.rel = 'stylesheet';
  css.href = `${base}js/dist/now.docdesigner.min.css${query}`;
  document.head.appendChild(css);

  return new Promise((resolve, reject) => {
    const js = document.createElement('script');
    js.src = `${base}js/dist/now.docdesigner.min.js${query}`;
    js.onload = () => resolve();
    js.onerror = () => reject(new Error('Failed to load js/dist/now.docdesigner.min.js'));
    document.head.appendChild(js);
  });
})();

async function initDocDesigner() {
  await docDesignerBundle; // หน้าอาจถูกวาดก่อนสคริปต์โหลดเสร็จ
  // ...
}

ตัวอย่างที่ใช้งานจริง

โปรเจ็ค บันเดิล ผลลัพธ์
project_manager js/components/timeline/ (entry import ซอร์สจาก modules/project/timeline/) js/dist/now.timeline.min.*
form js/components/docdesigner/ js/dist/now.docdesigner.min.*
gcms.in.th js/components/designer/ js/dist/gcms.designer.min.*
bluprint.in.th js/components/migration/ (ใช้ @e965/xlsx) js/dist/now.migration.min.js