Skip to content

4.1 · vtrc-web Deep Dive

vtrc-web คือเว็บแอปฝั่งพนักงานของสภากาชาดไทย — ดูสลิปเงินเดือน, ยื่นคำขอลา, เบิกสวัสดิการรักษาพยาบาล, ดูข่าวสารและนโยบาย, จัดการกองทุนสงเคราะห์, สมัครงาน และอื่น ๆ เป็น React 16.14 + Apollo Client v2 (react-apollo@3.1.5) + AntD v3.26 + Webpack 4.42 ที่ ejected จาก CRA (vtrc-web/package.json:75,76,20,106) รันที่ https://vtrc.redcross.or.th/ (prod) และ https://uat-vtrc.redcross.or.th/ (UAT) — ทั้งคู่ใช้ bundle ตัวเดียวกัน ที่เลือก GraphQL endpoint ตอน runtime ผ่าน checkLinkURL() (vtrc-web/src/config/apollo.js:17-34)

คู่สมรสคือ vtrc-rc-backoffice (ฝั่ง HR — Volume 4.2) ใช้ pattern คล้ายกันแต่คนละเวอร์ชัน library (AntD v3 vs v4, Webpack vs CRA, class + withApollo vs Recoil) ห้ามสับสน


เป้าหมายของ Volume นี้

ให้ผู้อ่านเข้าใจโครงสร้างของ vtrc-web/src/, รู้จุดที่ต้องระวัง, และสามารถแก้ไขหรือเพิ่มฟีเจอร์ได้โดยไม่ทำลาย pattern ที่มีอยู่ เอกสารนี้เป็นแผนที่ ไม่ใช่ตัวแทนของโค้ด — ควรเปิดไฟล์จริงใน repo ควบคู่กับการอ่าน


Tech stack (verify กับ vtrc-web/package.json 2026-07-13)

LayerTechเวอร์ชันCitation
UI runtimeReact16.14vtrc-web/package.json:75
React DOMreact-dom16.14vtrc-web/package.json:81
GraphQL clientreact-apollo (Apollo Client v2 HOC)3.1.5vtrc-web/package.json:76
apollo-client coreapollo-client2.6.3vtrc-web/package.json:22
Component libantd3.26.20vtrc-web/package.json:20
Routingreact-router-dom5.3.3vtrc-web/package.json:92
Date librarymoment2.29.4vtrc-web/package.json:64
Build toolwebpack (CRA ejected)4.42.0vtrc-web/package.json:106
Dev serverwebpack-dev-server3.11.0vtrc-web/package.json:107
Bundler minifyterser-webpack-plugin2.3.8vtrc-web/package.json:101
HTTP (REST)axios0.21.4vtrc-web/package.json:29
State (lightweight)styled-components, lodash, uuidvtrc-web/package.json:62,100,105
File uploadapollo-upload-client11.0.0vtrc-web/package.json:28
Drag and dropreact-dnd, react-dnd-html5-backend11.1.3vtrc-web/package.json:79,80
PDF viewerreact-pdf, pdfjs-dist, react-pdf-to-imagevtrc-web/package.json:90,68,91
Container (Docker)node + nginx14.20 / 1.24.0vtrc-web/Dockerfile:1,11

ห้าม upgrade React เป็น 17/18, Apollo เป็น v3, หรือ AntD ข้าม major โดยไม่ได้รับมอบหมาย — breaking change เพราะ HOC withApollo deprecated ใน Apollo v3, AntD v3 ใช้ LocaleProvider + Form.create ที่หายไปใน v4, React 17 เปลี่ยน event delegation


Branch info

  • Default/canonical branchmaster (default repo branch ที่ GitHub รู้จัก) ไม่มี pattern prod/uat แยกเหมือนหลาย repo ใน workspace
  • Working directory — 1,055 ไฟล์ทั้ง repo (รวม build/ และ node_modules) เนื้อที่จริงใน src/ ประมาณ 18,000 บรรทัดรวม
  • CI/CDbitbucket-pipelines.yml trigger branch feature/cicd, develop, uat, prod ทำ pipeline เดียวกัน (build-front-end-productionbuild-dockerpush-image-to-registry)
  • No .env ใน workspace — env-specific ทำงานที่ runtime ผ่าน window.location.href ทั้งหมด bundle ตัวเดียวใช้กับทุก env

ตัวเลขที่ควรจำ

ตัวเลขค่าCitation
GraphQL queries138 ตัว (export default keys)vtrc-web/src/graphql/queries.js (4,493 บรรทัด)
GraphQL mutations41 ตัวvtrc-web/src/graphql/mutations.js (1,447 บรรทัด)
Page folders48 โฟลเดอร์ (11 cluster)vtrc-web/src/pages/user/
Routes table1,410 บรรทัดvtrc-web/src/config/routes.js
Shell (SiderLayout)1,226 บรรทัดvtrc-web/src/components/user/SiderLayout/index.js
Leave Form (ใหญ่สุด)2,410 บรรทัดvtrc-web/src/pages/user/Leave/Form/index.js
Slip page1,528 บรรทัดvtrc-web/src/pages/user/Slip/index.js
Login page650 บรรทัดvtrc-web/src/pages/user/Login/index.js
ไฟล์ _bk* legacy/backup55 ไฟล์find in src/
dangerouslySetInnerHTML52 ไฟล์ทั่ว src/grep
AntD override (compiled CSS)21,190 บรรทัดvtrc-web/src/config/custom-antd.css
GA4 IDG-LKXD2EBDZ4vtrc-web/public/index.html:32
AES key hardcoded"6A45soD%9eB#"vtrc-web/src/utils/auth.js:38,41
Node (Docker)14.20 (EOL เม.ย. 2566)vtrc-web/Dockerfile:1

สไตล์โค้ด — 3 ข้อที่ต้องจำ

  1. class component + withApollo HOC เป็นหลัก — ไม่มี useQuery, ไม่มี <Query>/<Mutation> render props, ไม่มี function component ยกเว้น App/index.js (vtrc-web/src/containers/App/index.js:14)
  2. fetchPolicy: 'no-cache' เป็น default ทุก query/watchQuery — cache ของ Apollo แทบไม่ถูกใช้ (vtrc-web/src/config/apollo.js:171-182)
  3. endpoint เลือกตอน runtime ด้วย window.location.href.includes(...) ใน checkLinkURL() — ไม่ใช้ NODE_ENV หรือ REACT_APP_* (vtrc-web/src/config/apollo.js:17-34)

โครงสร้าง src/ ระดับบน

vtrc-web/
├── package.json                      — deps + 3 scripts (start/build/test)
├── Dockerfile                        — 2 stages: node:14.20 build → nginx:1.24.0 serve
├── bitbucket-pipelines.yml           — CI/CD
├── nginx-config/default.conf         — server block + SPA fallback
├── public/index.html                 — title + GA4 gtag inline
├── config/                           — CRA ejected (webpack/env/paths)
└── src/
    ├── index.js              93 บรรทัด  — entry + ApolloProvider + LocaleProvider th_TH
    ├── index_bk.js          124 บรรทัด  — legacy entry (ห้ามแตะ)
    ├── serviceWorker.js     135 บรรทัด  — CRA SW (เรียก unregister)
    ├── assets/                          — css, sass, fonts, images, pdf
    ├── components/
    │   ├── element/           3 ไฟล์     — reusable UI เล็ก ๆ
    │   └── user/             36 โฟลเดอร์ — domain components (รวม `from/` = typo ของ `Form`)
    ├── config/
    │   ├── apollo.js        184 บรรทัด   — Apollo Client + errorLink + authLink
    │   ├── routes.js      1,410 บรรทัด   — route table + render helpers
    │   ├── custom-antd.css 21,190 บรรทัด — AntD v3 override (compiled)
    │   ├── axios-bo.js       85 บรรทัด   — REST axios instance
    │   ├── refreshToken.js   35 บรรทัด   — token refresh promise wrapper
    │   └── datasets*.js   ~1,689 บรรทัด  — dropdown master data
    ├── containers/App/index.js  35 บรรทัด — root router + auth gate
    ├── graphql/
    │   ├── queries.js      4,493 บรรทัด  — 138 queries
    │   ├── mutations.js    1,447 บรรทัด  — 41 mutations
    │   └── index.js            2 บรรทัด  — re-export Queries + Mutations
    ├── pages/user/          48 โฟลเดอร์  — route screens (11 cluster)
    └── utils/                36 ไฟล์     — helpers (`auth.js`, `formatdate.js`, …)

ไฟล์ legacy/backup — ห้ามแตะ ห้ามใช้เป็นต้นแบบ

vtrc-web มีไฟล์ backup/snapshot 55 ไฟล์ กระจายทั่ว repo จากการ deploy หลาย env และการทดลอง refactor ที่ยังไม่ลบ

รูปแบบชื่อตัวอย่าง
_bk.jssrc/index_bk.js, src/config/routes_bk.js, src/pages/user/Login/index_bk.js
_bk<date>.jssrc/config/routes_bk11072568.js
_bk-prd.js/_bk-pro.js/_bkPpu.jsLeave/Form/index_bk-to-prd.js, detail_bk-prd.js
_pentest, _prd (สะกดผิด)queries_pentest.js, querries_prd.js
_gql.js/_axios.js/_table.jsContact/index_gql.js, index_axios.js, ChildEducationFee/index_table.js
ชื่อสะกดผิดcomponents/user/from/ (ควรเป็น Formห้ามแก้ชื่อ เพราะมี import อ้างถึงทั้งระบบ)

กฎเหล็ก — (1) อย่าแก้ไฟล์ที่ลงท้ายด้วย suffix backup (2) อย่า copy โค้ดจากไฟล์เหล่านี้เป็นต้นแบบ (query อาจ deprecated) (3) อย่าลบทิ้งเองโดยไม่ตรวจ git history ก่อน


สารบัญ

บทหัวข้อคำถามที่ตอบ
4.1.1Bootstrap + Webpack build + Apollo Clientแอปเริ่มที่ไหน สร้าง bundle อย่างไร ส่ง request อย่างไร เลือก endpoint อย่างไร
4.1.2Routing + auth gate + Component patterns + GraphQL catalogroute ทำงานอย่างไร component ใช้ pattern อะไร มี query/mutation อะไรบ้าง
4.1.3State + styling + locale (พ.ศ.) + security + scorecardstate อยู่ที่ไหน ใช้ CSS แบบไหน จัดการ พ.ศ. อย่างไร จุดเสี่ยงด้านความปลอดภัย สรุปสุขภาพ repo

บทเต็มของ v1 (docs-v1-archive/volume-06-vtrc-web/) มี 10 บท + index (~3,325 บรรทัด) — v2 ย่อเป็น 3 บทหนา เนื้อหาเดียวกันแต่กลั่นกรองและ verify กับโค้ดปัจจุบัน (2026-07-13) ทุก claim


สิ่งที่ไม่ cover ใน Volume นี้

  • GraphQL schema ฝั่ง vtrc-api — cover ใน Volume 3 โดยเฉพาะ @auth(accessRole, accessMenu) directive
  • HRMI MSSQL schema ฝั่ง cu-central-api — cover ใน Volume 8 (Data Model, ยังไม่เขียน)
  • business rule ของแต่ละฟีเจอร์ — cover ใน Volume 1 (Business, ยังไม่เขียน)
  • vtrc-rc-backofficeVolume 4.2 แยกต่างหาก (ใช้ AntD v4 + Recoil + MUI v5)
  • Modern microservices (2way/benefit/pms/…) — Volume 5+ เป็นกลุ่ม NestJS แยกจาก Legacy Core

การเปลี่ยนแปลงจาก v1

เนื้อหาพอร์ตจาก docs-v1-archive/volume-06-vtrc-web/ และ verify ใหม่ทุก claim — สิ่งที่เปลี่ยน

  1. Meeting cluster ถูก comment out ทั้งหมดvtrc-web/src/config/routes.js:1170-1300 มี meeting cluster ~130 บรรทัดที่ถูก comment ไว้ แสดงว่า vtrc-web ไม่ได้ใช้ meeting cluster แล้ว (ย้ายไป meeting-backoffice/2way-meeting-backoffice) v1 บอกว่า meeting มี ~15 route ซึ่งตอนนี้เป็น 0 route ใน routes array (แม้ component ยัง import อยู่ที่ routes.js:73-95)
  2. _bk* ไฟล์ 55 ไฟล์ (v1 บอก "มากกว่า 50") — verify ด้วย find src -name '*_bk*'
  3. dangerouslySetInnerHTML 52 ไฟล์ (v1 บอก "20+") — มากกว่าที่ v1 รายงานอย่างมาก
  4. formatdate.js จริง ๆ 441 บรรทัด (v1 บอก 442), message.js/messages.js จริง ๆ 29 บรรทัด (v1 บอก 30), markDown.js 15 บรรทัด (v1 บอก 16), checkError.js 71 บรรทัด (v1 บอก 72)

สิ่งที่ยังเหมือนเดิมจาก v1 — AES key hardcoded, apiKey prod base64, console override, checkLinkURL() substring match, fetchPolicy: 'no-cache', moment.locale('th'), Webpack 4 CRA ejected, Docker 2 stages, GA4 ID


วิธีอ่านเล่มนี้

  • เวลาน้อย — อ่าน 4.1.1 (map + bootstrap + Apollo) + 4.1.3 (security + scorecard) ก็พอเข้าใจภาพรวม
  • จะแก้ฟีเจอร์ — อ่าน 4.1.2 ก่อนหา route entry ของฟีเจอร์ แล้วดู query/mutation ใน catalog
  • จะทำ security review — อ่าน 4.1.3 ก่อน แล้ว cross-check กับ Volume 9 (Security)
  • จะ debug "หน้าขาว" — อ่านส่วน "ตอน debug หน้าขาว" ใน 4.1.1 ก่อน เพราะ console ถูกปิดไว้ที่ vtrc-web/src/containers/App/index.js:15

ขอแนะนำให้เปิดไฟล์จริงใน repo ควบคู่กับการอ่าน — คู่มือนี้เป็นแผนที่ ไม่ใช่ตัวแทนของโค้ด