🎞️ Videos → Why use JavaScript when CSS is possible?
Description
With the current state of CSS, it is now possible to move React Context to CSS for faster and smaller web. Let's explore the technique and its application together! Siriwat Kunaporn's YouTube channel https://www.youtube.com/@devMasterSomeday
Chapters
- เริ่มต้นด้วยแบบสำรวจ Styling Component และเกริ่นนำ Talk 0:00
- สปอยล์เนื้อหา Talk: เน้น CSS และ Reusable UI 0:30
- แนะนำตัวผู้บรรยายและบริษัท MUI 0:51
- หัวข้อ Talk: ใช้ JavaScript Styling ทำไมในเมื่อมี CSS? 1:48
- เป้าหมายของ Reusable UI: End User, Business, Developer 2:01
- Reusable UI/UI Library ควรครอบคลุมอะไรบ้าง? 4:00
- เฉลยวิธีที่ดีที่สุดในการสร้าง Reusable Component 6:32
- ทำไมไม่ใช่ Tailwind และ CSS in JS? 7:08
- รวมพลัง CSS Modules และ Inline Style 8:03
- CSS Modules คืออะไรและทำไมถึงเหมาะกับ Reusable Component 8:46
- ปัญหาการ Scale ของ CSS ทั่วไปและ Tailwind 10:37
- วิธีการ Scale CSS ด้วย JavaScript และ Tree Shaking 11:41
- ตัวอย่างปัญหา CSS แบบเดิมกับ Variants, สี, และขนาดของปุ่ม 13:18
- แนวคิด: ย้าย Style เข้า JavaScript เพื่อ Tree Shaking 15:37
- วิธีการ Implement: CSS Modules + Inline Style 17:45
- เปรียบเทียบขนาด Bundle Size กับ TailwindCSS พร้อม Dark Mode 20:36
- สรุปข้อดีของวิธี CSS Modules + Inline Style 22:04
- ปิดท้าย: POC และอนาคตของ Library 25:47
Transcript
คำบรรยายต่อไปนี้อาจไม่ถูกต้องทั้งหมด หากคุณพบข้อผิดพลาดใดๆ คุณสามารถช่วยแก้ไขข้อผิดพลาดได้บน GitHub
เริ่มต้นด้วยแบบสำรวจ Styling Component และเกริ่นนำ Talk0:00
โอเคครับ ใครสะดวก ใครว่างแล้ว มี survey สั้นๆ ให้ทำนะครับ คำถามเดียวเท่านั้น เดี๋ยวเราจะมาดูผล survey ตอนช่วงต้นของ talk ด้วยนะครับ ก็เป็นคำถามเกี่ยวกับเรา style component ยังไงนะครับตอนนี้
ในนี้มีใครไม่ใช่ frontend มั้ย อ๋อ มีไม่ใช่ frontend แต่ว่าชอบ CSS เหรอครับ โอเคนะครับ
สปอยล์เนื้อหา Talk: เน้น CSS และ Reusable UI0:30
สปอยล์นิดนึงแล้วกันนะ talk นี้ มันจะมีเรื่อง CSS ครึ่งๆ ละกันนะครับ ไม่ใช่ JavaScript อย่างเดียว ถือว่าเป็น talk ที่หลุดออกมานิดนึงนะครับ วันนี้เราฟัง JavaScript มากันเยอะแล้ว น่าจะปวดหัวกันมากขึ้นนะครับ
แนะนำตัวผู้บรรยายและบริษัท MUI0:51
โอเค เดี๋ยวระหว่างที่ทุกคนทำตัว survey นะ
มีคำถามเดียวนะครับ ใครที่ตอนนี้เพิ่งมานะครับ อยากให้สแกนแล้วก็ช่วยตอบคำถามหน่อยว่า ตอนนี้เรา style component ของเราด้วยวิธีอะไรกันบ้างนะครับ เดี๋ยวระหว่างที่ทุกคนสแกน เดี๋ยวจะแนะนำตัวแล้วก็ intro เร็วๆ นะครับเกี่ยวกับ talk นี้ โอเคครับ ก็สวัสดีทุกคนนะครับ
ผมชื่อจุ้นนะครับ ตอนนี้งานหลักๆ ก็จะเกี่ยวข้องกับทำ user interface บนเว็บนะครับ technology หลักๆ ที่ผมใช้เป็นประจำตอนนี้ ก็จะเป็นเรื่อง CSS กับตัว React นะครับ ผมทำงานอยู่ที่บริษัทชื่อ MUI นะครับ ก็เป็นบริษัทที่ทำ product เกี่ยวกับ React UI library นะครับ ก็จะมีทั้งพวก open source ด้วย แล้วก็มีทั้ง paid license ด้วยนะครับ
หัวข้อ Talk: ใช้ JavaScript Styling ทำไมในเมื่อมี CSS?1:48
โอเคนะครับ สำหรับ talk ในวันนี้ หัวข้อมันจะ clickbait นิดๆ นะครับ ว่าทำไมเราถึงใช้ JavaScript ในเมื่อเรามี CSS มัน possible นะครับ
เป้าหมายของ Reusable UI: End User, Business, Developer2:01
โอเค โดยที่เราจะคุยกันถึงเรื่องของการสร้าง reusable UI นะครับ
แล้วก็เราจะ focus ไปที่เรื่อง styling เลยนะ ก็จะเป็นเรื่องเกี่ยวกับ CSS นะครับ เราจะไม่ได้คุยกันถึงเรื่องพวก accessibility เรื่อง behavior ของ component อะไรพวกนี้ไม่มีนะครับ จะเป็นเรื่อง styling ล้วนๆ นะครับ โอเค คิดว่าทุกคนน่าจะตอบ survey กันไปแล้วนะครับ เดี๋ยวเราลองมาดูกันว่าในห้องนี้เนี่ย ทุกคนใช้อะไรกันอยู่นะครับ
ผิดคาดนิดนึงนะครับ แต่ว่ามีอันนึงที่ไม่ผิดคาดนะ ทุกคนน่าจะเห็นนะครับ อันนี้ 79 responses โอเคนะครับ
ถือว่าน่าจะครอบคลุมทั้งห้องนะ อันดับแรกก็คงไม่ค่อยพ้น Tailwind ใช่มั้ยครับ ทุกคนน่าจะใช้ Tailwind กันอยู่ อันดับที่ 2 ยังเป็น CSS in JS นะครับ แล้วก็อันดับที่ 3 เป็น inline style อันนี้จริงเหรอ จริงใช่มั้ย
โอเค ไม่เป็นไรครับ ผมคิดว่าอาจจะยังมีใช้กันอยู่นะครับ
เราแคปอันนี้กันไว้นะครับ เก็บไว้ในใจว่าตอนนี้อันดับ 1 ของเราเป็น Tailwind แล้วก็ CSS in JS นะครับ แล้วก็ inline style นะครับ เดี๋ยวเรากลับไปที่สไลด์ของเรา
โอเค ครับ แล้วก็วันนี้เนี่ย ที่ให้ทุกคนทำ survey นะครับ เพราะว่าเดี๋ยววันนี้ผมจะมาแชร์วิธีที่ผมคิดว่า มันเป็นวิธีที่ดีที่สุดแล้วกัน ในการสร้าง reusable component นะครับ โดยที่หนึ่งในวิธีนั้น method ที่ผมให้ทุกคนทำ survey ก็จะอยู่ในนี้นะครับ โอเค ทีนี้ก่อนอื่นที่เราจะไปดูนะครับ
Reusable UI/UI Library ควรครอบคลุมอะไรบ้าง?4:00
คำตอบว่ามันคืออะไรนะ วันนี้ที่ผมจะมาเล่าให้ฟัง เราจะต้องมาพูดในมุมของ reusable component ก่อนนะครับ ว่ามันครอบคลุมอะไรบ้างนะครับ เพราะว่าถ้าเราไม่ตีกรอบให้มันเนี่ย เวลาเราเอาแต่ละวิธีมา discuss หรือคุยกันนะครับ บางทีเราจะหลุดว่า สรุปแล้วคือมันจะต้องตอบโจทย์อะไรนะครับ เพราะฉะนั้น เราจะมาพูดถึงเรื่องนี้กันก่อน ก็เลยแบ่งเป็น 3 มุมนะครับ สำหรับตัว reusable UI หรือบางคนอาจจะเรียกว่าเป็น UI library ก็ได้นะครับ มุมแรกก็คือเป็นมุมที่ผมคิดว่าสำคัญที่สุดนะครับ แต่ส่วนใหญ่เราจะโฟกัสมุมเนี้ยทีหลังนะครับ
ก็คือเรื่องของ end user นะ คือ end user เนี่ยเขาไม่ได้สนใจหรอกว่า UI ที่เราทำมัน reusable อะไรหรือเปล่านะครับ สิ่งที่เขาสนใจก็คือมีแค่เรื่อง UI เนี่ยมันจะต้องเหมือนน่าดึงดูดในการใช้งานใช่ไหมครับ แล้วก็มีขนาดที่ bundle size เล็ก จะได้โหลดเร็วที่สุดนะ เปลืองเน็ตน้อย แล้วก็ทำงานได้เร็วนะครับ เปลืองแบตน้อยนะครับ ไม่เปลืองแบต ในมุมที่ 2 คือฝั่งที่เป็น business นะครับ ฝั่ง business เนี่ย เขาไม่ได้เขียนโค้ดเองหรอกใช่ไหม เขาสร้าง product เขาต้องการ ship product ให้ได้เร็วที่สุดนะครับ เพราะฉะนั้นเนี่ย ถ้าเป็น reusable UI เนี่ย เขาก็ต้องการให้มันนำมาแล้วสามารถ implement
สร้างเป็นเว็บไซต์ได้เลย เอามารวมนู่นนี่นั่นแล้วก็ออกมาเป็น digital product ได้นะครับ แล้วก็ที่สำคัญ สิ่งที่เขาสนใจคืออะไรครับ คือมันจะต้อง scale ได้นะครับ เวลาโปรเจคใหญ่ๆ มัน span ออกไปหลายๆ โปรเจคใช่ไหมครับ มันก็ตัว UI เนี่ยมันก็ควรที่จะเอามาใช้งานแล้วก็ทำงานได้เร็วอยู่
อันสุดท้ายคือพวกเรานี่แหละนะครับ ที่เป็น developer นะครับ เราสนใจอะไรใน reusable UI นะครับ คือมันควรที่จะ work ในทุกๆ framework ใช่ไหมครับ เราเรียกว่า UI ไม่ควรจะเป็นข้อจำกัดให้เราเลือก framework นะครับ เราควรที่จะสามารถที่จะเลือก framework แล้วค่อยมาหา UI ใช้งานได้นะครับ แล้วก็มันควรใช้งานง่าย custom ง่าย มี DX ที่ดี มี auto completion type safety อะไรพวกนี้นะครับ ที่เราสนใจนะครับ อันนี้คือ scope กว้างๆ ที่ผมคิดว่า เหมือนจะเป็น ideal เลยสำหรับ reusable UI หรือ UI library นะ ถ้ามี UI library ไหนที่มันสามารถตอบโจทย์ ครอบคลุมตรงนี้ได้ทั้งหมดเนี่ย ก็น่าใช้งานมากนะครับ
เฉลยวิธีที่ดีที่สุดในการสร้าง Reusable Component6:32
เดี๋ยวเราจะมาดูกันว่าวิธีที่ผมจะนำเสนอวันนี้ มันสามารถที่จะครอบคลุมทั้งหมดได้หรือเปล่านะครับ slide นี้ก็จะเป็น list ของ option ที่ให้ทุกคนเลือกเมื่อกี้แหละนะครับ
ไล่จาก pure CSS ข้างบนสุดเลย ลงมาถึง inline style ข้างล่างนะครับ คิดๆ ไว้ในใจให้พยายามลองเดาดูว่า
วันนี้ผมจะมา present option ไหน ลองนึกไว้ในใจนะครับ แล้วเดี๋ยวผมจะตัด choice ให้ว่าคืออะไร inline style เดี๋ยวเรามาดูกันครับ
ทำไมไม่ใช่ Tailwind และ CSS in JS?7:08
อย่างแรก ไม่ใช่ Tailwind แน่นอนนะครับ เพราะว่ามันคนใช้เยอะละนะครับ
จริงๆ Tailwind อันนี้เรากำลังพูดถึงการสร้าง reusable UI นะ หรือ UI library คือผมมองว่ามันยังมีข้อจำกัดบางอย่างสำหรับ Tailwind ที่ไม่คิดว่าเป็น the best ละกัน ณ ตอนนี้นะครับ
อันที่ 2 ที่ผมจะตัดทิ้งก็คือ อันดับที่ 2 ที่ทุกคนเลือกมานะครับ คือ CSS in JS ถามว่าทำไม ส่วนตัวผม ผมทำ library ที่ MUI เนี่ย library มันชื่อว่า Material UI นะครับ มันก็เป็น CSS in JS นะครับ ข้างหลังเนี่ย ทำมาหลายปีละ แล้วผมก็รู้สึกว่า มันไม่น่าจะเป็น the best option นะครับ แต่มัน work ในโลกของ React แต่ว่าพอเรามี concept เมื่อกี้ที่มันจะต้อง support ได้ ในทุก scope นะครับ ผมก็เลยตัดทิ้ง
รวมพลัง CSS Modules และ Inline Style8:03
ตอนนี้เราก็เลยเหลือ ฝั่งที่เป็น CSS กับตรงกลาง แล้วก็ inline style นะครับ แน่นอนข้างบนเนี่ยผมตัดทิ้งเพราะอะไรครับ เพราะว่าถ้าข้างบนมัน work เนี่ย เราคงไม่ต้องมีเครื่องมือข้างล่างใช่ไหม เพราะฉะนั้นเราตัด pure CSS ทิ้งนะครับ เราจะเหลือแค่ CSS Modules กับ inline style
โอเคนะครับ คำตอบของ method นี้คือ มันคือ 2 อันนี้รวมกันครับ นะ
ถ้าเกิดว่าผมบอกเป็น inline นี่คือวิ่งออกไปข้างนอกเลยใช่มั้ย ไม่ใช่มันคือ 2 อันนี้รวมกันนะครับ เดี๋ยวจะมาเล่าให้ฟังว่าทำไมนะครับ
CSS Modules คืออะไรและทำไมถึงเหมาะกับ Reusable Component8:46
คิดว่าเป็นวิธีใหม่ๆ ด้วยมั้ง ยังไม่ค่อยเห็นใครทำกันเท่าไหร่นะครับ
อย่างแรกเดี๋ยวมาพูดถึง CSS Modules ให้ฟังก่อนละกันนะครับ สำหรับใครที่อาจจะยังไม่เคยใช้นะครับ หรือไม่รู้ว่ามันคืออะไร CSS Modules เนี่ยจริงๆ คอนเซ็ปต์ของมันง่ายมากเลยนะครับ คือเราเขียนทุกอย่างในไฟล์ CSS เหมือนเดิม โดยที่เราตั้งชื่อเป็น .module.css อย่างงั้นนะครับ ข้างในเนี่ยเราเขียนคลาสธรรมดาเลย อยากจะเขียนตั้งชื่ออะไรก็ใส่เข้าไปนะครับ สไตล์ก็ใส่เข้าไป เสร็จแล้วในฝั่งของ JavaScript เนี่ย เวลาเราสร้าง component นะครับ เราจะ import ตัวสไตล์มาจากไฟล์ CSS Modules อันนั้นนะครับ
แล้วเราจะสามารถดึงสไตล์เนี่ย
เวลา import มามันจะเป็นเหมือน object นะครับ แล้วคลาสเนี่ยก็จะเป็นชื่อเดียวกับตัว class name ที่เราใส่ไว้ในไฟล์ CSS นะครับ แล้วก็ดึงมาใช้ตามปกติเลยครับ สุดท้ายเนี่ยเวลาที่เรา compile หรือ build ออกมาเนี่ย ฝั่งที่เป็น HTML เนี่ยคือผลลัพธ์ที่เราจะได้นะครับ ก็สังเกตว่าคลาสมันจะถูก hash ด้วย random string
อะไรพวกเนี้ยครับ มันจะถูก hash เอาเป็นว่าทำให้มัน unique นะครับ เพราะฉะนั้นวิธีเนี้ยเหมาะมากๆ สำหรับการสร้าง component เนี่ยเอามาสร้างเป็น component ใช่มั้ยครับ เพราะว่าคนที่เป็นคนสร้างเนี่ย เขาไม่ต้องกังวลว่าเค้าจะตั้งชื่อคลาสอะไร ซึ่งก็เป็นปัญหาคลาสสิกของ CSS ใช่มั้ยครับ สำหรับคนที่เอา component นี้ไปใช้งาน เค้าก็ไม่ต้องกลัวว่าเวลาเค้าเอาไปใช้แล้ว มันจะไปกระทบอะไรกับ component อื่นๆ หรือเปล่านะครับ เพราะฉะนั้นวิธีนี้เวิร์กมาก ฝั่งขวาเนี่ยมันอาจจะไม่ได้ใช่แบบนี้เท่าไหร่นะครับ หมายถึงว่าสไตล์ตรงเนี้ยไม่ต้องโฟกัส เอาเป็นว่าให้เห็นว่ามันจะถูก hash นะครับ
ปัญหาการ Scale ของ CSS ทั่วไปและ Tailwind10:37
คลาสจะถูก hash ทีนี้ที่ผมลอง research แล้วผมรู้สึกว่ามันเวิร์กนะครับ
เพราะอะไรครับ CSS Modules เนี่ยมันแทบจะ built-in support ทุก framework ถ้าเราลองไปไล่ดูนะครับ Next.js, Nuxt, SolidJS built-in support ตัว CSS Modules เลย ถ้าลองเข้าไป search เราจะเจอนะครับ แล้วเราสามารถที่จะสมมุติเริ่มโปรเจค พิมพ์ CSS Modules แล้วก็ตั้งชื่อไฟล์ .module.css import ใช้งานได้เลยนะครับ framework พวกนี้ทำทุกอย่างให้หมดแล้วเรื่องของ compile นะครับ ส่วนที่เป็น Astro, Svelte, Angular เนี่ย เค้าไม่ได้ support โดยตรง แต่ว่าคอนเซ็ปต์ในการสร้างสไตล์ของเค้า เหมือนกับ CSS Modules เลย คือสร้างสไตล์แล้วมันก็จะ scope ไปที่ component นะครับ เพราะฉะนั้นเนี่ย แค่เราเลือก method นี้
ในการสไตล์ component เนี่ย มันเหมือนกับว่าเรามาครึ่งทางแล้วนะครับ เพราะมันเวิร์กกับทุก framework เลย เพราะฉะนั้นเอามาสู้กับ Tailwind ได้อยู่
วิธีการ Scale CSS ด้วย JavaScript และ Tree Shaking11:41
ทีนี้อีกครึ่งนึงคืออะไร
ทำยังไงให้วิธีนี้มันเป็น the best นะครับ อีกครึ่งนึงเนี่ยเป็นเรื่องของการเขียน CSS วิธีในการเขียน CSS เพื่อทำให้ component ของเราเนี่ย มันสามารถ scale ไปได้ แบบสไตล์ของเรามันสามารถ scale ไปได้ ในหลายๆ โปรเจคนะครับ ถึงตรงนี้เนี่ยผมคิดว่าทุกคนอาจจะยังมองไม่เห็นภาพว่า scale นี่คือยังไงนะครับ เดี๋ยวเรามาดูก่อน เราลองเอาตัวอย่างนึงมาดูก่อนนะครับ สร้างปุ่มแบบง่ายๆ เลย แล้วเรามาดูว่าเวลาถ้าเราเขียน CSS ปกติ
มันจะเจอปัญหาเรื่อง scale แบบไหนนะครับ อันนี้ผมยกตัวอย่างเป็นปุ่มแบบง่ายๆ นะครับ ของ design system อันนึง เรามี 4 variant ใช่มั้ย 4 รูปแบบอะ อาจจะเรียกว่าอะไรก็ได้นะครับ ถ้า no-brainer แบบเจอๆ อย่างงี้ปุ๊บทำไงครับ เราก็สร้างคลาสแยกเลย เวลาเขียน CSS จะเป็น .btn อะไรก็ตั้งชื่อ ตามที่เราคิดว่ามันเป็นชื่อของสไตล์นั้นๆ พอเราสร้างพวกนี้ขึ้นมาเสร็จนะครับ ในไฟล์ JavaScript ที่เป็นไฟล์ที่เราสร้าง component เนี่ย เราก็จะ import มาจาก CSS Modules อันนี้ใช่มั้ย แล้วเราก็จะใส่ class name เข้าไปปกติ
เอาง่ายๆ คือเราสร้าง component เรามี prop รับเข้ามานะครับ แล้วเราก็แตะคลาสเหมือนกับเชื่อมคลาสกัน นี่คือแบบ basic เลยนะครับที่เราจะทำ
ตัวอย่างปัญหา CSS แบบเดิมกับ Variants, สี, และขนาดของปุ่ม13:18
ทีนี้ถ้ามัน 4 variant ใช่มั้ยครับ ก็เหมือนกับว่าเรามี 4 คลาสใช่ปะ แล้วเวลาที่เรา render บน runtime มันก็จะเลือกคลาสอันนั้นมาใช่มั้ยครับ
โอเค ทีนี้ผมขอย่อง่ายๆ ไอ้ตัว class ที่สร้างมาเมื่อกี้ ขอย่อให้มันกลายเป็นไอคอนนะ เราจะได้เห็นว่าโอเค ถ้าเรามี 4 variants เราจะมี CSS เพิ่มขึ้นประมาณแบบเหมือน พูดง่ายๆ ก็ 4 เท่าอะไรประมาณเนี้ย ทีนี้นอกจาก variants นะครับ ใน design system เนี่ยเราก็จะมีหลายสีใช่มั้ย อันนี้ผมยกมา 4 สีแล้วกัน เอาที่มันแบบปกติที่ใช้ใน library นะครับ พอมี 4 สี เนื่องจากว่าสีเนี่ยมันค่อนข้างที่จะ
สอดคล้องกับตัว variants นะครับ แปลว่าเราก็ต้องคูณ 4 เท่าเข้าไปนะครับ ฝั่งขวาเนี่ยเราจะเห็นว่า CSS มันก็จะโตขึ้นนะ ใหญ่ขึ้นใช่มั้ยครับ ไม่ต้องสนใจว่ามันคูณ 4 หรือเปล่า เอาเป็นว่า CSS มันเยอะขึ้นนะครับ ไม่พอ เราก็ต้องมีหลาย size ในการเอาไปใช้ในเว็บนะครับ
มีคนถาม น่าจะกำลังทำอยู่ใช่มั้ย
โอเค พอมี 3 size CSS เราก็จะใหญ่ขึ้นนะครับ และเมื่อเราเอาไปใช้งานในหลายๆ โปรเจค พอมันเป็น design system นะครับ อันเนี้ยโปรเจคมันน้อยนะครับ แต่พอมันเป็นโปรเจคอาจจะแบบ 10 15 20 โปรเจค เป็น 100 โปรเจคเงี้ย คนที่ maintain ตัว design system เนี่ย เวลาอะไรมันซ้ำๆ กัน ด้วยความเป็นโปรแกรมเมอร์ใช่มั้ย เราก็จะยุบรวมกันเอาไปอยู่ในที่เดียวอะไรเงี้ย มันมีความเป็นไปได้ที่ style มันจะเพิ่มขึ้นไปเรื่อยๆ นะครับ ปัญหามันอยู่ตรงนี้ครับ ปัญหามันอยู่ที่ว่า ถ้าเราทำโปรเจค A อยู่ แล้วเราใช้ CSS ต้องการใช้ CSS แค่ 50% หรือ 80% ก็ได้
ของไอ้ปุ่มเนี้ย อีก 20% เราทำอะไรได้บ้าง เราไม่ต้องการใช่มั้ยครับ แต่เมื่อทุกอย่างมันอยู่ใน CSS เนี่ย มันทำ tree shaking ไม่ได้ อันนั้นคือปัญหา แล้วนี่คือแค่ 1 ปุ่มใช่มั้ยครับ ถ้าเรามีหลายเป็นแบบ 20 30 component อะไรเงี้ย นี่คือปัญหาของ CSS มัน scale ไม่ได้นะครับ เช่นเดียวกันกับ Tailwind Tailwind ก็ทำ tree shaking ไม่ได้นะครับ
แนวคิด: ย้าย Style เข้า JavaScript เพื่อ Tree Shaking15:37
โอเค รอแป๊บนึงนะครับ พอผมเห็นรูปเมื่อกี้ปุ๊บ ผมก็เลยนึกขึ้นมาได้เลยว่า เฮ้ย ปัญหาเนี้ยมันเคยแก้แล้วใน JavaScript โดยการทำ tree shaking นะครับ ผมก็เลยคิดว่า เฮ้ย ถ้าอย่างงี้เราเปลี่ยน class CSS พวกนี้ให้อยู่ใน JavaScript แทน
แล้วเราสร้างไฟล์ CSS ขึ้นมาอันนึง เป็น template ส่วนที่เป็น style ทั้งหมด อยู่ใน JavaScript inject เข้ามาในไฟล์ CSS แทนนะครับ ตรงนี้อาจจะดูซับซ้อน แต่ว่าในโค้ดแม่งโคตรง่ายเลย เราจะสามารถใช้ประโยชน์จาก framework ต่างๆ เพื่อทำ tree shaking ได้ เพราะอะไรครับ คือถ้า style อยู่ใน JavaScript มอง style เป็นเหมือนฟังก์ชันก็ได้ สมมุติเรา import module มาใช่มั้ย ในโมดูลนั้นมี 10 ฟังก์ชัน เรา import มา 3 ฟังก์ชัน เราที่เป็นโปรแกรมเมอร์นะครับ import มา 3 ฟังก์ชัน เวลาเรา build เนี่ย ไม่ว่า framework ไหนที่เราใช้นะครับ ส่วนใหญ่แล้วเนี่ยมันจะทำ tree shaking ให้ เอาง่ายๆ คือมันจะ tree shake
ส่วนที่เราไม่ได้ใช้ออกไปให้เลยจาก final bundle นะครับ อันนี้คือข้อดีของ JavaScript และเป็นสิ่งที่ผมรู้สึกว่า เราสามารถ leverage ไอ้ความสามารถตรงนี้ของ JavaScript ได้ เพราะว่า JavaScript มันพัฒนามาเป็น 10 ปีแล้วนะ แต่ในมุมของ bundle size หรือการ scale ของ CSS ไม่ค่อยมีการพัฒนาเท่าไหร่นะครับ มีแต่ feature ที่จะเพิ่มขึ้นมาทุกวันนะครับ โอเค เพราะฉะนั้นโมเดลนี้มันจะเวิร์กมากเลย ถ้าเราสามารถทำได้นะครับ แต่ละโปรเจคเค้าไม่ต้องมากังวลเลยว่า ไอ้ของมันมีอยู่เท่าไหร่ใช่มั้ย เค้าแค่อิมพอร์ตสิ่งที่เค้าต้องการใช้ แล้วเดี๋ยวที่เหลือ เดี๋ยว framework มันจะจัดการให้เอง ไอ้คนที่เป็นคนทำ design system ก็ไม่ต้องกลัวนะครับว่า เราเพิ่ม style เข้าไปแล้ว bundle size มันจะใหญ่ เพราะว่าสุดท้ายแล้ว framework มันทำ tree shaking ให้นะครับ
วิธีการ Implement: CSS Modules + Inline Style17:45
ทีนี้ทำยังไง ผมก็เลยลองจากโมเดลนี้เนี่ย ก็เลยลองหาวิธีนะครับ สรุปว่ามันออกมาเป็น CSS module บวกกับ inline style สเต็ปเป็นแบบนี้เลยครับ ถ่ายรูปไปได้ จำไปได้นะครับ ลองเอาไปใช้ดู 1 ไฟล์ CSS เนี่ยเราจะไม่เขียนค่าตรงๆ
เขียนเป็น custom property แบบนี้นะครับ
เรามี property อย่างงี้
เราเปลี่ยนทุกอย่างที่มันเกี่ยวข้องกับ ไอ้พวกสี variants size อะไรพวกเนี้ย เปลี่ยนให้เป็นตัว custom property ให้หมดนะ ซึ่งตรงเนี้ยคือ CSS นะครับ อันนี้คือ CSS นะ ถ้าเกิดใครยังไม่เคยใช้ตัว CSS variable เนี่ย อันนี้เวิร์กใน CSS นะครับ เหมือนเราทำให้เป็น template เป็น skeleton ไว้ใช่มั้ย ถ้าเราเอาไฟล์เนี้ยไป render ปุ่มใช่ป่ะ เราจะได้เป็นปุ่มโง่ๆ อันนึง ที่ไม่มีอะไรเลยนะครับ
มีแค่เหมือนเป็น skeleton น่ะ รอคนเอาค่ามาแปะให้
สเต็ปที่ 2 เราจะย้าย style ทั้งหมดที่เราสร้างเมื่อกี้
จาก class ต่างๆ เข้ามาอยู่ใน JavaScript แทน โดยการที่เรา export เป็นฟังก์ชันนะครับ หรือเราจะ export เป็น object ก็ได้ ตามใจชอบเลย เนี่ยเห็นป่ะ ค่ามันโคตรง่ายเลยครับทุกคน อย่างเราลองดูที่ button small ก็ได้ เนื่องจากอย่าง button small เนี่ย ผมตั้ง size เป็น 32 พิกเซลใช่ป่ะ gap เป็น 6 พิกเซล ไอ้ตัว key เนี่ย เป็น CSS variable ที่มันจะ reference ไปถึงไฟล์ template ที่เราทำเมื่อกี้นะครับ เสร็จแล้ว ฝั่งที่เป็นคนใช้งาน
เวลานำมาใช้ import button มา แล้วก็ import style มาจากไฟล์ JavaScript เมื่อกี้นะครับ แล้วเสร็จแล้วเวลาใช้งานก็คือส่งผ่าน inline style คือตอนที่ผมเจอท่าเนี้ย ผมรู้สึกว่า inline style อ่ะมันเป็นวิธีเดียว ที่เป็น native เลย ที่มันเชื่อมระหว่างโลก 2 โลก คือโลกของ JavaScript กับโลกของ CSS เป็นช่องทางเล็กๆ นะครับ ที่เราส่งผ่านแค่อ็อบเจกต์ได้ เป็น plain object แต่เรื่องของ media query เรื่อง selector อะไรมันไม่เวิร์กใช่มั้ย แต่วิธีเนี้ยแม่งโคตรเวิร์ก เพราะเราส่งผ่าน variable ได้นะครับ แล้วทุกอย่างก็ dynamic บน runtime ด้วยนะครับ แล้วเราก็จะได้ผลลัพธ์มาแบบนี้ สุดท้ายเวลาเราเอา component นี้มา มา render class ก็คือมาจาก CSS module ใช่มั้ย style มาจาก inline style ที่ส่งผ่านมาจาก JavaScript นะครับ แล้วเราก็จะได้ปุ่มแบบนี้มา เอาแป๊บนึง
เหมือนเค้าให้เราเบรก คิดซะว่าเค้าให้เราเบรกนะครับ
เปรียบเทียบขนาด Bundle Size กับ TailwindCSS พร้อม Dark Mode20:36
จริงเนี่ยวิธีนี้มีแค่นี้เลยนะครับ นี่คือวิธีที่ผมคิดว่าดีที่สุดละ เดี๋ยวเรามาดูผลลัพธ์กันนิดนึงว่ามันดีจริงรึเปล่านะครับ ผมก็เลยเอามาเทียบกับ Tailwind ถามว่าทำไมนะครับ เพราะว่า Tailwind เนี่ยมันรองรับทุก framework อยู่แล้วใช่ป่ะ มันเป็นแบบ utility class ใช่มั้ย ผมก็เลยสร้างแบบ โอเค เอาไอ้ปุ่มเมื่อกี้ 4 variant 4 สี 3 size มา render บนเพจ
เพจเดียวนะ แล้วก็สร้างมาเทียบกับ Tailwind ปรากฏว่าของ Tailwind เนี่ย อันนี้ผมเอาแค่ size ของปุ่มมานะ ประมาณ 1.9
วิธีที่ผมเสนอไปเมื่อกี้อ่ะ ประมาณ 1.6 นะครับ โอเค ทีนี้พอเราใส่ dark mode เข้าไปใน Tailwind ใช่มั้ย เราก็ใส่ dark class ใช่ป่ะ แล้วก็ใส่ style เข้าไป ก็ size มันก็จะเพิ่มขึ้นโดยปกติอยู่แล้วนะครับ ส่วนวิธีที่ผมบอกไปเนี่ย อันนี้เพิ่มขึ้นแค่ฝั่งที่เป็น CSS variable ที่เอาไว้สลับสีแค่นั้นเอง point ของสไลด์นี้เนี่ยไม่ได้บอกว่า วิธีที่ผมเสนอไปมันจะเล็กกว่า โดยเฉลี่ยมันจะเล็กกว่าแล้วกัน แต่ว่ามันก็ขึ้นอยู่กับว่าเราเขียน CSS ยังไงถูกมั้ย บางทีเราอาจจะไม่เขียน state ไม่เขียน hover เลยก็ได้ แบบมี background color อย่างเดียวอ่ะ สุดท้าย size มันก็ใกล้กันนะครับ point ก็คือจะบอกว่าวิธีเนี้ยมันสามารถเทียบกับ Tailwind ได้ หมายถึงว่าผลลัพธ์ที่เราได้ค่อนข้างที่จะสูสีกับ Tailwind ในเรื่องของ bundle size หรือบางทีต่ำกว่าด้วยซ้ำนะครับ
สรุปข้อดีของวิธี CSS Modules + Inline Style22:04
ตรงนี้เดี๋ยวเราจะมาสรุปกันแล้วครับ มันไม่ใช่แค่เล็กอย่างเดียวถูกมั้ยครับ มันทำงานกับทุก framework ได้นะครับ อย่างโค้ดเมื่อกี้ ผมลองเขียนโค้ดดูปุ๊บ แล้วผมเอาไปแปะบอก AI ว่า เฮ้ย ช่วยทำออกมาเป็น Svelte ให้หน่อย มันก็แก้นิดหน่อยนะครับ แล้วก็เอาไปใช้งานได้ หรือเปลี่ยนไปเป็น Vue.js ให้หน่อยเงี้ย มันก็แก้ได้นะครับ โค้ดแทบจะไม่ต่างเลย เพราะฉะนั้นน่ะดีมาก อันที่มันจะชนะ Tailwind เนี่ยคืออันนี้ คือเรื่องของ tree shaking นะครับ เพราะว่า style ทั้งหมดของเราเนี่ยมันอยู่ใน JavaScript นะครับ แล้วก็ style เนี่ยคือเข้าใจโค้ดง่าย เพราะมันไม่มีอะไรเลย นึกออกมั้ย มันก็เป็น function export เลือกเอาว่าเราจะเอาอะไรอ่ะ เราจะเอา variable อะไร value เท่าไหร่ก็ตามที่เราตั้ง
แล้วเราสามารถ export เป็นพันๆ style ได้ โดยที่เราไม่ต้องกังวลนะครับว่า final bundle size ของมันจะใหญ่ เพราะว่า framework มันทำ tree shaking ให้นะ อันนี้คือข้อดีที่มันจะชนะวิธีอื่นด้วยซ้ำนะครับ แล้วก็อันเนี้ยเป็นข้อดีอันนึงที่ผมจากประสบการณ์แล้วกันนะ ที่ทำ UI library คือผมชอบวิธีนี้ตรงนี้ด้วย คือมันง่ายต่อการ extend นะครับ อย่างที่ผมทำ Material UI เนี่ย เรามี prop ให้ใช่ป่ะ อย่างเช่น variant a b c d ต้องเข้าใจว่าคนที่เอา Material UI ไปใช้เนี่ยมีเยอะมาก หลายโปรเจคที่เอาไปทำเป็น design system ต่อด้วย ทีนี้ design system หลายๆ ครั้งเค้าก็จะมี context ของเค้าไม่เหมือนกันนึกออกมั้ย เค้าอาจจะไม่ใช้ variant a b c d กูอยากใช้ variant แบบ d e f อย่างเงี้ย ถ้าเกิดเค้าเอา library เอาไปใช้ เค้าจะลบ CSS ตรงนั้นออกอ่ะ มันลบไม่ได้ นึกออกมั้ย คือเค้าแค่ทำได้แค่เพิ่ม แล้วอาจจะทำอะไรบางอย่างกับ TypeScript เพื่อตัดค่าพวกนั้นทิ้ง แต่ CSS ที่เค้าเอาไปอ่ะ ยังไงก็ติดไปด้วย ถึงแม้ว่าเค้าจะไม่ได้ใช้ ซึ่งนั่นคือข้อเสียแบบเป็น trade-off เลยแล้วกันนะครับ ที่พวก CSS in JS อ่ะมันจะทำอะไรแบบนี้ยาก
แต่วิธีเนี้ย คุณไม่จำเป็นต้องเอา style ไปก็ได้ นึกออกป่ะ ถึงแม้ว่าคุณเอาไปแต่คุณไม่ได้ใช้มันก็เอาออกให้นะครับ คือคุณสามารถที่จะ extend ได้ง่ายมาก แล้วก็ component เห็นมั้ย มันจะ lean มาก เพราะว่ามันไม่มี prop อะไรเลย ทุกอย่างคือคุณแปะลงไปใน style ซึ่ง style มัน native ใช่ป่ะ ทุก framework มันมี inline style ให้อยู่แล้วอ่ะ คือดูโค้ดเรารู้สึกว่า clean กว่าเยอะ บางทีคนเอาไป extend นะครับ
แล้วก็ auto completion อันนี้เราก็ไม่ต้องทำอะไรเลย เพราะว่า export มันเป็น function ใช่ป่ะ เราแค่พิมพ์ อาจจะต้องจำชื่อนิดนึง ซึ่งมันก็คล้ายๆ Tailwind แหละนะ เราก็ต้องจำ แล้วทุกอย่างมันก็โผล่มาให้อ่ะ
แล้วก็อันสุดท้ายคือที่ผมชอบคือ อันนี้จากประสบการณ์ที่เขียนโค้ดมาระดับนึงนะครับ เราจะเริ่มรู้ว่า สิ่งที่ดีที่สุดน่ะ
คือสิ่งที่มันคือ simple ที่สุด อย่างเคสอันเนี้ยมันเรียกว่า close to native CSS
กับ JavaScript มากๆ อย่าง JavaScript function ง่ายๆ export อะไรไม่ได้มีอะไรซับซ้อนใช่มั้ยครับ CSS ก็เรายังเขียนทุกอย่างอยู่ในไฟล์ CSS อยู่ ถ้าวันนึงเราบอกว่า CSS module ไม่ตอบโจทย์เรา เราก็ก็อปปี้มันทั้งไฟล์เอาไปแปะใน CSS แล้วก็ยังใช้งานได้อยู่นึกออกป่ะ
อันนี้ก็เลยเป็นผมรู้สึกว่าวิธีเนี้ย คือวิธีที่ดีที่สุดเท่าที่ผมเห็น ณ ตอนนี้นะครับ ถ้าเปรียบเทียบกับเครื่องมือที่มีอยู่ในตลาด ในการ style reusable component นะครับ
ปิดท้าย: POC และอนาคตของ Library25:47
เพราะว่าทุกอย่างอ่ะ เราแทบจะเรียกว่า leverage เครื่องมือต่างๆ ที่มันมีอยู่แล้วอ่ะ โดยที่เราไม่ต้องทำอะไรเลยนะครับ โอเค อันนี้เป็นแค่จุดเริ่มต้นนะครับ ผมทำ POC มาแล้วแหละ มันก็ดูเวิร์คดีนะครับ
แต่ว่าแน่นอนว่าเดี๋ยวต้องเอาลองไปเทสต์ดูว่า ถ้า production library จริงๆ อ่ะ มันจะเจอข้อจำกัดอะไรบ้างนะครับ
ถ้าผมทำ library นี้เสร็จเมื่อไหร่ เดี๋ยวจะมาเล่าให้ฟังอีกทีนึงนะครับ แล้วไว้เจอกันใน episode หน้าครับ วันนี้ขอบคุณทุกคนมากครับที่รับฟัง
ขอบคุณทางพี่ศิริวัฒน์มากๆ นะครับ พี่