การจัดการ CSS ที่ไม่ได้ใช้ใน Sass เพื่อปรับปรุงประสิทธิภาพ

เผยแพร่แล้ว: 2022-03-10
สรุปโดยย่อ ↬ คุณรู้หรือไม่ว่า CSS ที่ไม่ได้ใช้มีผลกระทบต่อประสิทธิภาพหรือไม่ สปอยล์ : เยอะ! ในบทความนี้ เราจะมาสำรวจวิธีแก้ปัญหาเชิง Sass เพื่อจัดการกับ CSS ที่ไม่ได้ใช้ หลีกเลี่ยงความจำเป็นในการพึ่งพา Node.js ที่ซับซ้อนซึ่งเกี่ยวข้องกับเบราว์เซอร์ที่ไม่มีส่วนหัว และการจำลอง DOM

ในการพัฒนา front-end สมัยใหม่ นักพัฒนาควรตั้งเป้าที่จะเขียน CSS ซึ่งสามารถปรับขนาดได้และบำรุงรักษาได้ มิฉะนั้น อาจเสี่ยงต่อการสูญเสียการควบคุมเฉพาะ เช่น น้ำตกและความจำเพาะของตัวเลือกเมื่อ codebase เติบโตขึ้นและนักพัฒนามีส่วนร่วมมากขึ้น

วิธีหนึ่งที่สามารถทำได้คือการใช้วิธีการเช่น Object-Oriented CSS (OOCSS) ซึ่งแทนที่จะจัดระเบียบ CSS รอบบริบทของหน้า ส่งเสริมการแยกโครงสร้าง (ระบบกริด ระยะห่าง ความกว้าง ฯลฯ) จากการตกแต่ง (แบบอักษร ยี่ห้อ สี ฯลฯ)

ดังนั้นชื่อคลาส CSS เช่น:

  • .blog-right-column
  • .latest_topics_list
  • .job-vacancy-ad

ถูกแทนที่ด้วยทางเลือกอื่นที่นำกลับมาใช้ใหม่ได้ ซึ่งใช้สไตล์ CSS เดียวกัน แต่ไม่ได้เชื่อมโยงกับบริบทเฉพาะใดๆ:

  • .col-md-4
  • .list-group
  • .card

แนวทางนี้มักใช้ด้วยความช่วยเหลือของเฟรมเวิร์ก Sass เช่น Bootstrap, Foundation หรือบ่อยครั้งขึ้นเรื่อยๆ ซึ่งเป็นเฟรมเวิร์กที่ปรับแต่งได้เองเพื่อให้เข้ากับโปรเจ็กต์มากขึ้น

เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

ตอนนี้เรากำลังใช้คลาส CSS ที่คัดสรรจากเฟรมเวิร์กของรูปแบบ ส่วนประกอบ UI และคลาสยูทิลิตี้ ตัวอย่างด้านล่างแสดงให้เห็นระบบกริดทั่วไปที่สร้างโดยใช้ Bootstrap ซึ่งวางซ้อนกันในแนวตั้ง จากนั้นเมื่อถึงเบรกพอยต์ md จะสลับไปใช้เค้าโครง 3 คอลัมน์

 <div class="container"> <div class="row"> <div class="col-12 col-md-4">Column 1</div> <div class="col-12 col-md-4">Column 2</div> <div class="col-12 col-md-4">Column 3</div> </div> </div>

คลาสที่สร้างโดยทางโปรแกรม เช่น .col-12 และ .col-md-4 ถูกใช้เพื่อสร้างรูปแบบนี้ แต่ .col-1 ถึง .col-11 , .col-lg-4 , .col-md-6 หรือ .col-sm-12 ล่ะ นี่คือตัวอย่างทั้งหมดของคลาสที่จะรวมอยู่ในสไตล์ชีต CSS ที่คอมไพล์แล้ว ดาวน์โหลดและแยกวิเคราะห์โดยเบราว์เซอร์ แม้จะไม่ได้ใช้งานอยู่ก็ตาม

ในบทความนี้ เราจะเริ่มด้วยการสำรวจผลกระทบที่ CSS ที่ไม่ได้ใช้อาจมีต่อความเร็วในการโหลดหน้าเว็บ จากนั้นเราจะพูดถึงวิธีแก้ปัญหาที่มีอยู่เพื่อลบออกจากสไตล์ชีต ตามด้วยโซลูชันที่เน้น Sass ของฉันเอง

การวัดผลกระทบของคลาส CSS ที่ไม่ได้ใช้

แม้ว่าฉันจะชื่นชอบเชฟฟิลด์ ยูไนเต็ด ผู้ทรงพลัง แต่ CSS ของเว็บไซต์ก็ถูกรวมไว้ในไฟล์ย่อขนาด 568kb ไฟล์เดียว ซึ่งถึง 105kb แม้ว่าจะบีบอัดไฟล์แล้วก็ตาม ที่ดูเหมือนมาก

นี่คือเว็บไซต์ของ Sheffield United ทีมฟุตบอลในพื้นที่ของฉัน (นั่นคือ Soccer สำหรับคุณในอาณานิคม) (ตัวอย่างขนาดใหญ่)

เราจะมาดูกันว่า CSS นี้ถูกใช้จริงมากแค่ไหนในหน้าแรกของพวกเขา? การค้นหาโดย Google อย่างรวดเร็วเผยให้เห็นเครื่องมือออนไลน์มากมายที่เหมาะกับงาน แต่ฉันชอบใช้เครื่องมือ ครอบคลุม ใน Chrome ซึ่งสามารถเรียกใช้โดยตรงจาก DevTools ของ Chrome ให้มันหมุน

วิธีที่รวดเร็วที่สุดในการเข้าถึงเครื่องมือความครอบคลุมในเครื่องมือสำหรับนักพัฒนาคือการใช้แป้นพิมพ์ลัด Control+Shift+P หรือ Command+Shift+P (Mac) เพื่อเปิดเมนูคำสั่ง ในนั้น ให้พิมพ์ coverage แล้วเลือกตัวเลือก 'แสดงความครอบคลุม' (ตัวอย่างขนาดใหญ่)

ผลลัพธ์แสดงให้เห็นว่า CSS เพียง 30kb จากสไตล์ชีต 568kb ถูกใช้โดยหน้าแรก โดยที่เหลืออีก 538kb เกี่ยวข้องกับสไตล์ที่จำเป็นสำหรับส่วนที่เหลือของเว็บไซต์ ซึ่งหมายความว่าไม่ได้ใช้ CSS มากถึง 94.8%

คุณสามารถดูการกำหนดเวลาเช่นนี้สำหรับเนื้อหาใดๆ ใน Chrome ในเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ผ่านเครือข่าย -> คลิกที่เนื้อหาของคุณ -> แท็บกำหนดเวลา (ตัวอย่างขนาดใหญ่)

CSS เป็นส่วนหนึ่งของเส้นทางการแสดงผลที่สำคัญของหน้าเว็บ ซึ่งเกี่ยวข้องกับขั้นตอนต่างๆ ทั้งหมดที่เบราว์เซอร์ต้องดำเนินการให้เสร็จสิ้นก่อนที่จะเริ่มแสดงหน้าเว็บ สิ่งนี้ทำให้ CSS เป็นเนื้อหาที่บล็อกการแสดงผล

ด้วยเหตุนี้ เมื่อโหลดเว็บไซต์ของ Sheffield United โดยใช้การเชื่อมต่อ 3G ที่ดี จึงต้องใช้เวลาทั้งหมด 1.15 วินาทีก่อนที่จะดาวน์โหลด CSS และการแสดงหน้าเว็บสามารถเริ่มต้นได้ นี่คือปัญหา.

Google รับรู้สิ่งนี้เช่นกัน เมื่อเรียกใช้การตรวจสอบ Lighthouse ทางออนไลน์หรือผ่านเบราว์เซอร์ของคุณ เวลาในการโหลดและการลดขนาดไฟล์ที่อาจเกิดขึ้นซึ่งสามารถทำได้โดยการลบ CSS ที่ไม่ได้ใช้จะถูกเน้น

ใน Chrome (และ Chromium Edge) คุณมีสิทธิ์ตรวจสอบ Google Lighthouse ได้โดยคลิกแท็บการตรวจสอบในเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ (ตัวอย่างขนาดใหญ่)

โซลูชั่นที่มีอยู่

เป้าหมายคือการกำหนดคลาส CSS ที่ไม่ต้องการและลบออกจากสไตล์ชีต มีโซลูชันที่มีอยู่ซึ่งพยายามทำให้กระบวนการนี้เป็นอัตโนมัติ โดยทั่วไปสามารถใช้ได้ผ่านสคริปต์บิลด์ Node.js หรือผ่านทางตัวดำเนินการเช่นอึก ซึ่งรวมถึง:

  • UNCSS
  • PurifyCSS
  • PurgeCSS

โดยทั่วไปแล้วสิ่งเหล่านี้ทำงานในลักษณะเดียวกัน:

  1. บน Bulld เว็บไซต์สามารถเข้าถึงได้ผ่านเบราว์เซอร์หัวขาด (เช่น: puppeteer) หรือการจำลอง DOM (เช่น: jsdom)
  2. ตามองค์ประกอบ HTML ของหน้า จะมีการระบุ CSS ที่ไม่ได้ใช้
  3. สิ่งนี้จะถูกลบออกจากสไตล์ชีต เหลือเพียงสิ่งที่จำเป็นเท่านั้น

แม้ว่าเครื่องมืออัตโนมัติเหล่านี้จะใช้งานได้อย่างสมบูรณ์ และฉันได้ใช้หลายตัวในโครงการเชิงพาณิชย์หลายโครงการอย่างประสบความสำเร็จ ฉันพบข้อเสียบางประการระหว่างทางซึ่งควรค่าแก่การแบ่งปัน:

  • หากชื่อคลาสมีอักขระพิเศษ เช่น '@' หรือ '/' ระบบอาจไม่จดจำชื่อเหล่านี้หากไม่ได้เขียนโค้ดที่กำหนดเอง ฉันใช้ BEM-IT โดย Harry Roberts ซึ่งเกี่ยวข้องกับการจัดโครงสร้างชื่อคลาสด้วยคำต่อท้ายที่ตอบสนอง เช่น: u-width-6/12@lg ดังนั้นฉันจึงเคยประสบปัญหานี้มาก่อน
  • หากเว็บไซต์ใช้การปรับใช้อัตโนมัติ อาจทำให้กระบวนการสร้างช้าลง โดยเฉพาะอย่างยิ่งถ้าคุณมีหน้าเว็บจำนวนมากและ CSS จำนวนมาก
  • จำเป็นต้องแชร์ความรู้เกี่ยวกับเครื่องมือเหล่านี้ทั่วทั้งทีม มิฉะนั้น อาจเกิดความสับสนและความยุ่งยากเมื่อ CSS หายไปอย่างลึกลับในสไตล์ชีตการผลิต
  • หากเว็บไซต์ของคุณมีสคริปต์บุคคลที่สามจำนวนมากที่ทำงานอยู่ บางครั้งเมื่อเปิดในเบราว์เซอร์ที่ไม่มีส่วนหัว สคริปต์เหล่านี้เล่นได้ไม่ดีนักและอาจทำให้เกิดข้อผิดพลาดในกระบวนการกรอง โดยทั่วไปแล้ว คุณต้องเขียนโค้ดที่กำหนดเองเพื่อแยกสคริปต์ของบุคคลที่สามเมื่อตรวจพบเบราว์เซอร์หัวขาด ซึ่งอาจเป็นเรื่องยากขึ้นอยู่กับการตั้งค่าของคุณ
  • โดยทั่วไป เครื่องมือประเภทนี้จะซับซ้อนและมีการพึ่งพาเพิ่มเติมมากมายในกระบวนการสร้าง เช่นเดียวกับกรณีของการพึ่งพาบุคคลที่สามทั้งหมด นี่หมายถึงการพึ่งพารหัสของคนอื่น

เมื่อคำนึงถึงประเด็นเหล่านี้ ข้าพเจ้าจึงตั้งคำถามกับตัวเองว่า

การใช้เพียง Sass เป็นไปได้ไหมที่จะจัดการ Sass ที่เราคอมไพล์ให้ดีขึ้นเพื่อให้สามารถยกเว้น CSS ที่ไม่ได้ใช้โดยไม่ต้องพึ่งการลบคลาสซอร์สใน Sass อย่างคร่าวๆ

การแจ้งเตือนสปอยเลอร์: คำตอบคือใช่ นี่คือสิ่งที่ฉันคิดขึ้นมา

Sass Oriented Solution

โซลูชันจำเป็นต้องจัดเตรียมวิธีที่รวดเร็วและง่ายดายในการเลือกสิ่งที่ Sass ควรคอมไพล์ ในขณะที่เรียบง่ายพอที่จะไม่เพิ่มความซับซ้อนให้กับกระบวนการพัฒนาหรือป้องกันไม่ให้นักพัฒนาใช้ประโยชน์จากสิ่งต่าง ๆ เช่น CSS ที่สร้างโดยทางโปรแกรม ชั้นเรียน

ในการเริ่มต้น มี repo ที่มีสคริปต์สำหรับบิลด์และรูปแบบตัวอย่างบางส่วนซึ่งคุณสามารถโคลนได้จากที่นี่

เคล็ดลับ: หากคุณติดขัด คุณสามารถอ้างอิงโยงกับเวอร์ชันที่สมบูรณ์บนมาสเตอร์แบรนช์ได้เสมอ

cd ลงใน repo รัน npm install จากนั้น npm run build เพื่อคอมไพล์ Sass ลงใน CSS ตามต้องการ สิ่งนี้ควรสร้างไฟล์ css ขนาด 55kb ในไดเร็กทอรี dist

จากนั้น หากคุณเปิด /dist/index.html ในเว็บเบราว์เซอร์ของคุณ คุณจะเห็นส่วนประกอบมาตรฐาน ซึ่งเมื่อคลิกจะขยายเพื่อแสดงเนื้อหาบางส่วน คุณยังสามารถดูสิ่งนี้ได้ที่นี่ ซึ่งจะใช้เงื่อนไขเครือข่ายจริง คุณจึงทำการทดสอบของคุณเองได้

เราจะใช้องค์ประกอบ UI ของตัวขยายนี้เป็นหัวข้อทดสอบของเราเมื่อพัฒนาโซลูชันที่เน้น Sass สำหรับการจัดการ CSS ที่ไม่ได้ใช้ (ตัวอย่างขนาดใหญ่)

การกรองที่ระดับบางส่วน

ในการตั้งค่า SCSS ทั่วไป คุณน่าจะมีไฟล์ manifest เดียว (เช่น: main.scss ใน repo) หรือหนึ่งไฟล์ต่อหน้า (เช่น: index.scss , products.scss , contact.scss ) โดยที่เฟรมเวิร์กบางส่วน ถูกนำเข้า ตามหลักการ OOCSS การนำเข้าเหล่านั้นอาจมีลักษณะดังนี้:

ตัวอย่างที่ 1

 /* Undecorated design patterns */ @import 'objects/box'; @import 'objects/container'; @import 'objects/layout'; /* UI components */ @import 'components/button'; @import 'components/expander'; @import 'components/typography'; /* Highly specific helper classes */ @import 'utilities/alignments'; @import 'utilities/widths';

หากบางส่วนเหล่านี้ไม่ได้ใช้งาน วิธีธรรมชาติในการกรอง CSS ที่ไม่ได้ใช้นี้คือปิดการใช้งานการนำเข้า ซึ่งจะป้องกันไม่ให้คอมไพล์

ตัวอย่างเช่น หากใช้เฉพาะคอมโพเนนต์ expander โดยทั่วไปแล้วไฟล์ Manifest จะมีลักษณะดังนี้:

ตัวอย่าง 2

 /* Undecorated design patterns */ // @import 'objects/box'; // @import 'objects/container'; // @import 'objects/layout'; /* UI components */ // @import 'components/button'; @import 'components/expander'; // @import 'components/typography'; /* Highly specific helper classes */ // @import 'utilities/alignments'; // @import 'utilities/widths';

อย่างไรก็ตาม ตาม OOCSS เรากำลังแยกการตกแต่งออกจากโครงสร้างเพื่อให้สามารถใช้ซ้ำได้สูงสุด ดังนั้นจึงเป็นไปได้ที่ตัวขยายอาจต้องการ CSS จากอ็อบเจ็กต์ ส่วนประกอบ หรือคลาสยูทิลิตี้อื่น ๆ เพื่อแสดงผลอย่างถูกต้อง เว้นแต่นักพัฒนาจะทราบถึงความสัมพันธ์เหล่านี้โดยการตรวจสอบ HTML พวกเขาอาจไม่ทราบว่าต้องนำเข้าบางส่วนเหล่านี้ ดังนั้นจึงไม่ได้รวบรวมคลาสที่จำเป็นทั้งหมด

ใน repo หากคุณดู HTML ของตัวขยายใน dist/index.html ดูเหมือนว่าจะเป็นกรณีนี้ โดยจะใช้สไตล์จากกล่องและออบเจ็กต์เลย์เอาต์ ส่วนประกอบตัวพิมพ์ และยูทิลิตี้ความกว้างและการจัดตำแหน่ง

dist/index.html

 <div class="c-expander"> <div class="o-box o-box--spacing-small c-expander__trigger c-expander__header" tabindex="0"> <div class="o-layout o-layout--fit u-flex-middle"> <div class="o-layout__item u-width-grow"> <h2 class="c-type-echo">Toggle Expander</h2> </div> <div class="o-layout__item u-width-shrink"> <div class="c-expander__header-icon"></div> </div> </div> </div> <div class="c-expander__content"> <div class="o-box o-box--spacing-small"> Lorum ipsum <p class="u-align-center"> <button class="c-expander__trigger c-button">Close</button> </p> </div> </div> </div>

มาจัดการปัญหานี้ที่รอให้เกิดขึ้นด้วยการทำให้ความสัมพันธ์เหล่านี้เป็นทางการภายใน Sass กัน ดังนั้นเมื่อนำเข้าส่วนประกอบแล้ว การขึ้นต่อกันใดๆ จะถูกนำเข้าโดยอัตโนมัติด้วย ด้วยวิธีนี้ นักพัฒนาจึงไม่ต้องเสียค่าใช้จ่ายเพิ่มเติมในการตรวจสอบ HTML เพื่อเรียนรู้ว่าต้องนำเข้าอะไรอีก

แผนที่การนำเข้าแบบเป็นโปรแกรม

เพื่อให้ระบบการพึ่งพานี้ทำงานได้ แทนที่จะแสดงความคิดเห็นในคำสั่ง @import ในไฟล์รายการ ตรรกะ Sass จะต้องกำหนดว่าคอมไพล์บางส่วนจะถูกคอมไพล์หรือไม่

ใน src/scss/settings ให้สร้างบางส่วนใหม่ชื่อ _imports.scss , @import ใน settings/_core.scss แล้วสร้างแผนที่ SCSS ต่อไปนี้:

src/scss/settings/_core.scss

 @import 'breakpoints'; @import 'spacing'; @import 'imports';

src/scss/settings/_imports.scss

 $imports: ( object: ( 'box', 'container', 'layout' ), component: ( 'button', 'expander', 'typography' ), utility: ( 'alignments', 'widths' ) );

แผนที่นี้จะมีบทบาทเหมือนกับรายการนำเข้าในตัวอย่างที่ 1

ตัวอย่างที่ 4

 $imports: ( object: ( //'box', //'container', //'layout' ), component: ( //'button', 'expander', //'typography' ), utility: ( //'alignments', //'widths' ) );

มันควรจะทำงานเหมือนชุดมาตรฐานของ @imports ซึ่งถ้ามีการใส่ความคิดเห็นบางส่วน (เช่นข้างบน) โค้ดนั้นก็ไม่ควรถูกคอมไพล์บนบิลด์

แต่เนื่องจากเราต้องการนำเข้าการขึ้นต่อกันโดยอัตโนมัติ เราก็ควรจะสามารถละเว้นแผนที่นี้ได้ภายใต้สถานการณ์ที่เหมาะสม

แสดงผล Mixin

มาเริ่มเพิ่มตรรกะ Sass กัน สร้าง _render.scss ใน src/scss/tools แล้วเพิ่ม @import ลงใน tools/_core.scss

ในไฟล์ ให้สร้างมิกซ์อินเปล่าชื่อ render()

src/scss/tools/_render.scss

 @mixin render() { }

ใน mixin เราต้องเขียน Sass ซึ่งทำสิ่งต่อไปนี้:

  • เรนเดอร์()
    “สวัสดีครับ $imports อากาศดีใช่หรือไม่? พูดว่าคุณมีวัตถุคอนเทนเนอร์ในแผนที่ของคุณหรือไม่"
  • $นำเข้า
    false
  • เรนเดอร์()
    “น่าเสียดาย ดูเหมือนว่าจะไม่ได้รับการรวบรวมแล้ว แล้วส่วนประกอบของปุ่มล่ะ?”
  • $นำเข้า
    true
  • เรนเดอร์()
    "ดี! นั่นคือปุ่มที่ถูกคอมไพล์แล้ว พูดสวัสดีกับภรรยาสำหรับฉัน”

ใน Sass สิ่งนี้แปลเป็นต่อไปนี้:

src/scss/tools/_render.scss

 @mixin render($name, $layer) { @if(index(map-get($imports, $layer), $name)) { @content; } }

โดยทั่วไป ให้ตรวจสอบว่าบางส่วนรวมอยู่ในตัวแปร $imports imports หรือไม่ และถ้าเป็นเช่นนั้น ให้แสดงผลโดยใช้คำสั่ง @content ของ Sass ซึ่งช่วยให้เราส่งบล็อกเนื้อหาไปยังมิกซ์อินได้

เราจะใช้มันดังนี้:

ตัวอย่างที่ 5

 @include render('button', 'component') { .c-button { // styles et al } // any other class declarations }

ก่อนใช้มิกซ์อินนี้มีการปรับปรุงเล็กน้อยที่เราสามารถทำได้ ชื่อเลเยอร์ (อ็อบเจ็กต์ ส่วนประกอบ ยูทิลิตี้ ฯลฯ) เป็นสิ่งที่เราสามารถคาดเดาได้อย่างปลอดภัย ดังนั้นเราจึงมีโอกาสที่จะปรับปรุงสิ่งต่าง ๆ เล็กน้อย

ก่อนการประกาศมิกซ์อินของการแสดงผล ให้สร้างตัวแปรชื่อ $layer และลบตัวแปรที่มีชื่อเหมือนกันออกจากพารามิเตอร์มิกซ์อิน ชอบดังนั้น:

src/scss/tools/_render.scss

 $layer: null !default; @mixin render($name) { @if(index(map-get($imports, $layer), $name)) { @content; } }

ตอนนี้ ในบางส่วนของ _core.scss ที่มีอ็อบเจ็กต์ ส่วนประกอบ และยูทิลิตี้ @imports อยู่ ให้ประกาศตัวแปรเหล่านี้เป็นค่าต่อไปนี้อีกครั้ง แสดงถึงประเภทของคลาส CSS ที่นำเข้า

src/scss/objects/_core.scss

 $layer: 'object'; @import 'box'; @import 'container'; @import 'layout';

src/scss/components/_core.scss

 $layer: 'component'; @import 'button'; @import 'expander'; @import 'typography';

src/scss/utilities/_core.scss

 $layer: 'utility'; @import 'alignments'; @import 'widths';

ด้วยวิธีนี้ เมื่อเราใช้ render() mixin สิ่งที่เราต้องทำคือประกาศชื่อบางส่วน

ล้อมการเรนเดอร์ render() มิกซ์อินไว้รอบ ๆ การประกาศคลาสส่วนประกอบและยูทิลิตี้แต่ละรายการตามด้านล่าง สิ่งนี้จะทำให้คุณใช้งานมิกซ์อินการแสดงผลได้หนึ่งรายการต่อบางส่วน

ตัวอย่างเช่น:

src/scss/objects/_layout.scss

 @include render('button') { .c-button { // styles et al } // any other class declarations }

src/scss/components/_button.scss

 @include render('button') { .c-button { // styles et al } // any other class declarations }

หมายเหตุ: สำหรับ utilities/_widths.scss การตัดฟังก์ชัน render() รอบส่วนทั้งหมดจะเกิดข้อผิดพลาดในการคอมไพล์ เช่นเดียวกับใน Sass คุณไม่สามารถซ้อนการประกาศมิกซ์อินภายในการเรียกมิกซ์อิน ให้ใส่การผสม render() ไว้รอบการเรียก create-widths() แทน ดังตัวอย่างด้านล่าง:

 @include render('widths') { // GENERATE STANDARD WIDTHS //--------------------------------------------------------------------- // Example: .u-width-1/3 @include create-widths($utility-widths-sets); // GENERATE RESPONSIVE WIDTHS //--------------------------------------------------------------------- // Create responsive variants using settings.breakpoints // Changes width when breakpoint is hit // Example: .u-width-1/3@md @each $bp-name, $bp-value in $mq-breakpoints { @include mq(#{$bp-name}) { @include create-widths($utility-widths-sets, \@, #{$bp-name}); } } // End render }

ด้วยสิ่งนี้ ใน build จะมีการคอมไพล์เฉพาะบางส่วนที่อ้างอิงใน $imports imports

ผสมและจับคู่ส่วนประกอบที่แสดงความคิดเห็นใน $imports imports และรัน npm run build ในเทอร์มินัลเพื่อลองดู

แผนที่อ้างอิง

ตอนนี้เรากำลังนำเข้าบางส่วนโดยทางโปรแกรม เราสามารถเริ่มใช้ตรรกะการพึ่งพาได้

ใน src/scss/settings ให้สร้างส่วนใหม่ที่เรียกว่า _dependencies.scss , @import ใน settings/_core.scss แต่ตรวจสอบให้แน่ใจว่าอยู่หลัง _imports.scss จากนั้นสร้างแผนที่ SCSS ต่อไปนี้:

src/scss/settings/_dependencies.scss

 $dependencies: ( expander: ( object: ( 'box', 'layout' ), component: ( 'button', 'typography' ), utility: ( 'alignments', 'widths' ) ) );

ในที่นี้ เราประกาศการพึ่งพาสำหรับคอมโพเนนต์ตัวขยายเนื่องจากต้องใช้สไตล์จากบางส่วนอื่นเพื่อแสดงผลอย่างถูกต้อง ดังที่เห็นใน dist/index.html

เมื่อใช้รายการนี้ เราสามารถเขียนตรรกะได้ ซึ่งหมายความว่าการขึ้นต่อกันเหล่านี้จะถูกคอมไพล์พร้อมกับส่วนประกอบที่ขึ้นต่อกันเสมอ ไม่ว่าสถานะของตัวแปร $imports จะเป็นอย่างไร

ด้านล่าง $dependencies ให้สร้างมิกซ์อินชื่อ dependency-setup() ในที่นี้ เราจะดำเนินการดังต่อไปนี้:

1. วนซ้ำแผนที่การพึ่งพา

 @mixin dependency-setup() { @each $componentKey, $componentValue in $dependencies { } }

2. หากพบส่วนประกอบใน $imports ให้วนซ้ำรายการการพึ่งพา

 @mixin dependency-setup() { $components: map-get($imports, component); @each $componentKey, $componentValue in $dependencies { @if(index($components, $componentKey)) { @each $layerKey, $layerValue in $componentValue { } } } }

3. หากการพึ่งพาไม่ได้อยู่ใน $imports ให้เพิ่ม

 @mixin dependency-setup() { $components: map-get($imports, component); @each $componentKey, $componentValue in $dependencies { @if(index($components, $componentKey)) { @each $layerKey, $layerValue in $componentValue { @each $partKey, $partValue in $layerValue { @if not index(map-get($imports, $layerKey), $partKey) { $imports: map-merge($imports, ( $layerKey: append(map-get($imports, $layerKey), '#{$partKey}') )) !global; } } } } } }

การรวมแฟล็ก !global จะบอกให้ Sass ค้นหาตัวแปร $imports ในขอบเขตโกลบอล แทนที่จะเป็นขอบเขตโลคัลของมิกซ์อิน

4. ถ้าอย่างนั้นก็แค่เรียกมิกซ์อิน

 @mixin dependency-setup() { ... } @include dependency-setup();

ดังนั้น สิ่งที่เรามีในตอนนี้คือระบบนำเข้าบางส่วนที่ได้รับการปรับปรุง ซึ่งหากมีการนำเข้าส่วนประกอบ นักพัฒนาก็ไม่จำเป็นต้องนำเข้าส่วนการพึ่งพาต่างๆ แต่ละรายการด้วยตนเองเช่นกัน

กำหนดค่าตัวแปร $imports เฉพาะส่วนประกอบ expander แล้วรัน npm run build คุณควรเห็นคลาสตัวขยายใน CSS ที่คอมไพล์แล้วพร้อมกับการพึ่งพาทั้งหมด

อย่างไรก็ตาม สิ่งนี้ไม่ได้นำสิ่งใหม่ๆ มาสู่ตารางในแง่ของการกรอง CSS ที่ไม่ได้ใช้ออกไป เนื่องจาก Sass จำนวนเท่าเดิมยังคงถูกนำเข้า ไม่ว่าจะแบบเป็นโปรแกรมหรือไม่ก็ตาม มาปรับปรุงเรื่องนี้กันเถอะ

ปรับปรุงการนำเข้าการพึ่งพา

องค์ประกอบอาจต้องการเพียงคลาสเดียวจากการพึ่งพา ดังนั้นเพื่อดำเนินการต่อและนำเข้าคลาสของการพึ่งพานั้นทั้งหมดจะนำไปสู่การขยายที่ไม่จำเป็นแบบเดียวกับที่เรากำลังพยายามหลีกเลี่ยง

เราสามารถปรับแต่งระบบเพื่อให้สามารถกรองแบบละเอียดมากขึ้นในแต่ละคลาสได้ เพื่อให้แน่ใจว่าคอมไพล์ส่วนประกอบด้วยคลาสการพึ่งพาที่พวกเขาต้องการเท่านั้น

ด้วยรูปแบบการออกแบบส่วนใหญ่ ไม่ว่าจะตกแต่งหรือไม่ มีคลาสขั้นต่ำที่ต้องแสดงในสไตล์ชีตเพื่อให้รูปแบบแสดงได้อย่างถูกต้อง

สำหรับชื่อคลาสที่ใช้หลักการตั้งชื่อที่กำหนดไว้เช่น BEM โดยทั่วไปแล้วคลาสที่มีชื่อ “บล็อก” และ “องค์ประกอบ” จะต้องเป็นขั้นต่ำ โดยที่ “ตัวดัดแปลง” มักจะเป็นตัวเลือก

หมายเหตุ: คลาสยูทิลิตี้มักจะไม่เป็นไปตามเส้นทาง BEM เนื่องจากพวกมันแยกจากกันตามธรรมชาติเนื่องจากการโฟกัสที่แคบ

ตัวอย่างเช่น ลองดูที่วัตถุสื่อนี้ ซึ่งน่าจะเป็นตัวอย่างที่รู้จักกันดีที่สุดของ CSS เชิงวัตถุ:

 <div class="o-media o-media--spacing-small"> <div class="o-media__image"> <img src="url" alt="Image"> </div> <div class="o-media__text"> Oh! </div> </div>

หากองค์ประกอบมีชุดนี้เป็นการพึ่งพา คุณควรคอมไพล์ .o-media , .o-media__image และ .o-media__text เนื่องจากเป็นจำนวน CSS ขั้นต่ำที่จำเป็นในการทำให้รูปแบบทำงาน อย่างไรก็ตาม ด้วย .o-media--spacing-small เป็น modifier ทางเลือก มันควรจะคอมไพล์ก็ต่อเมื่อเราพูดอย่างชัดเจนเท่านั้น เนื่องจากการใช้งานอาจไม่สอดคล้องกันในทุกอินสแตนซ์ออบเจกต์สื่อ

เราจะแก้ไขโครงสร้างของแผนที่ $dependencies เพื่อให้เราสามารถนำเข้าคลาสทางเลือกเหล่านี้ในขณะที่รวมถึงวิธีการนำเข้า เฉพาะ บล็อกและองค์ประกอบในกรณีที่ไม่จำเป็นต้องมีการปรับเปลี่ยน

ในการเริ่มต้น ให้ตรวจสอบตัวขยาย HTML ใน dist/index.html และจดบันทึกคลาสการพึ่งพาใดๆ ที่ใช้งานอยู่ บันทึกสิ่งเหล่านี้ในแผนที่ $dependencies ตามด้านล่าง:

src/scss/settings/_dependencies.scss

 $dependencies: ( expander: ( object: ( box: ( 'o-box--spacing-small' ), layout: ( 'o-layout--fit' ) ), component: ( button: true, typography: ( 'c-type-echo', ) ), utility: ( alignments: ( 'u-flex-middle', 'u-align-center' ), widths: ( 'u-width-grow', 'u-width-shrink' ) ) ) );

เมื่อค่าถูกตั้งค่าเป็น true เราจะแปลสิ่งนี้เป็น “คอมไพล์คลาสระดับบล็อกและองค์ประกอบเท่านั้น ไม่มีโมดิฟายเออร์!”

ขั้นตอนต่อไปเกี่ยวข้องกับการสร้างตัวแปรรายการที่อนุญาตพิเศษเพื่อจัดเก็บคลาสเหล่านี้ และคลาสอื่น ๆ (ที่ไม่ขึ้นต่อกัน) ที่เราต้องการนำเข้าด้วยตนเอง ใน /src/scss/settings/imports.scss หลังจาก $imports imports ให้สร้างรายการ Sass ใหม่ชื่อ $global-filter

src/scss/settings/_imports.scss

 $global-filter: ();

หลักฐานพื้นฐานที่อยู่เบื้องหลัง $global-filter คือคลาสใดๆ ที่เก็บไว้ที่นี่จะถูกคอมไพล์บน build ตราบใดที่บางส่วนที่เป็นของพวกมันถูกนำเข้าผ่าน $imports

ชื่อคลาสเหล่านี้สามารถเพิ่มโดยทางโปรแกรมได้ หากเป็นการพึ่งพาคอมโพเนนต์ หรือสามารถเพิ่มด้วยตนเองเมื่อมีการประกาศตัวแปร เช่นในตัวอย่างด้านล่าง:

ตัวอย่างตัวกรองทั่วโลก

 $global-filter: ( 'o-box--spacing-regular@md', 'u-align-center', 'u-width-6/12@lg' );

ต่อไป เราต้องเพิ่มตรรกะอีกเล็กน้อยให้กับมิกซ์ @dependency-setup ดังนั้นคลาสใดๆ ที่อ้างอิงใน $dependencies จะถูกเพิ่มลงในรายการ $global-filter ที่อนุญาตโดยอัตโนมัติ

ด้านล่างบล็อกนี้:

src/scss/settings/_dependencies.scss

 @if not index(map-get($imports, $layerKey), $partKey) { }

...เพิ่มตัวอย่างต่อไปนี้

src/scss/settings/_dependencies.scss

 @each $class in $partValue { $global-filter: append($global-filter, '#{$class}', 'comma') !global; }

สิ่งนี้จะวนซ้ำในคลาสการพึ่งพาใด ๆ และเพิ่มลงในรายการที่อนุญาตพิเศษของ $global-filter

ณ จุดนี้ หากคุณเพิ่มคำสั่ง @debug dependency-setup() เพื่อพิมพ์เนื้อหาของ $global-filter ในเทอร์มินัล:

 @debug $global-filter;

...คุณควรเห็นสิ่งนี้ในบิลด์:

 DEBUG: "o-box--spacing-small", "o-layout--fit", "c-box--rounded", "true", "true", "u-flex-middle", "u-align-center", "u-width-grow", "u-width-shrink"

ตอนนี้ เรามีคลาสที่อนุญาตพิเศษแล้ว เราต้องบังคับใช้สิ่งนี้กับอ็อบเจกต์ ส่วนประกอบ และบางส่วนของยูทิลิตี้ที่แตกต่างกันทั้งหมด

สร้างส่วนใหม่ที่เรียกว่า _filter.scss ใน src/scss/tools และเพิ่ม @import ลงในไฟล์ _core.scss ของเลเยอร์เครื่องมือ

ในบางส่วนใหม่นี้ เราจะสร้างมิกซ์อินที่เรียกว่า filter() เราจะใช้สิ่งนี้เพื่อใช้ตรรกะซึ่งหมายความว่าคลาสจะถูกคอมไพล์ก็ต่อเมื่อรวมอยู่ในตัวแปร $global-filter

เริ่มต้นง่ายๆ ให้สร้างมิกซ์อินที่ยอมรับพารามิเตอร์เดียว — $class ที่ตัวกรองควบคุม ต่อไป หาก $class รวมอยู่ในรายการที่อนุญาตพิเศษของ $global-filter ให้คอมไพล์มัน

src/scss/tools/_filter.scss

 @mixin filter($class) { @if(index($global-filter, $class)) { @content; } }

ในบางส่วน เราจะห่อมิกซ์อินรอบคลาสทางเลือก เช่น:

 @include filter('o-myobject--modifier') { .o-myobject--modifier { color: yellow; } }

ซึ่งหมายความว่าคลาส .o-myobject--modifier จะถูกคอมไพล์ก็ต่อเมื่อรวมอยู่ใน $global-filter ซึ่งสามารถตั้งค่าได้โดยตรงหรือโดยอ้อมผ่านการตั้งค่าใน $dependencies

ผ่าน repo และใช้ filter() มิกซ์อินกับคลาสตัวแก้ไขที่เป็นตัวเลือกทั้งหมดในเลเยอร์อ็อบเจ็กต์และองค์ประกอบ เมื่อจัดการองค์ประกอบการพิมพ์หรือเลเยอร์ยูทิลิตี้ เนื่องจากแต่ละคลาสไม่ขึ้นกับคลาสถัดไป จึงควรทำให้เป็นตัวเลือก ทั้งหมด ดังนั้นเราจึงสามารถเปิดใช้งานคลาสตามที่เราต้องการได้

นี่คือตัวอย่างบางส่วน:

src/scss/objects/_layout.scss

 @include filter('o-layout__item--fit-height') { .o-layout__item--fit-height { align-self: stretch; } }

src/scss/utilities/_alignments.scss

 // Changes alignment when breakpoint is hit // Example: .u-align-left@md @each $bp-name, $bp-value in $mq-breakpoints { @include mq(#{$bp-name}) { @include filter('u-align-left@#{$bp-name}') { .u-align-left\@#{$bp-name} { text-align: left !important; } } @include filter('u-align-center@#{$bp-name}') { .u-align-center\@#{$bp-name} { text-align: center !important; } } @include filter('u-align-right@#{$bp-name}') { .u-align-right\@#{$bp-name} { text-align: right !important; } } } }

หมายเหตุ: เมื่อเพิ่มชื่อคลาสต่อท้ายแบบตอบสนองให้กับมิกซ์อิน filter() คุณไม่จำเป็นต้องหลีกเลี่ยงสัญลักษณ์ '@' ด้วย '\'

ในระหว่างกระบวนการนี้ ในขณะที่ใช้ filter() มิกซ์อินกับบางส่วน คุณอาจ (หรืออาจไม่ได้สังเกต) สังเกตเห็นบางสิ่ง

ชั้นเรียนแบบกลุ่ม

บางคลาสใน codebase ถูกจัดกลุ่มเข้าด้วยกันและใช้สไตล์เดียวกัน ตัวอย่างเช่น

src/scss/objects/_box.scss

 .o-box--spacing-disable-left, .o-box--spacing-horizontal { padding-left: 0; }

เนื่องจากตัวกรองยอมรับเพียงคลาสเดียวเท่านั้น จึงไม่พิจารณาถึงความเป็นไปได้ที่บล็อกการประกาศสไตล์หนึ่งบล็อกอาจมีมากกว่าหนึ่งคลาส

เพื่อพิจารณาเรื่องนี้ เราจะขยาย filter() มิกซ์อิน ดังนั้นนอกจากคลาสเดียวแล้ว มันยังสามารถรับ Sass arglist ที่มีหลายคลาสได้ ชอบดังนั้น:

src/scss/objects/_box.scss

 @include filter('o-box--spacing-disable-left', 'o-box--spacing-horizontal') { .o-box--spacing-disable-left, .o-box--spacing-horizontal { padding-left: 0; } }

ดังนั้นเราต้องบอก filter() มิกซ์อินว่าถ้าหนึ่งในคลาสเหล่านี้อยู่ใน $global-filter คุณได้รับอนุญาตให้คอมไพล์คลาสได้

สิ่งนี้จะเกี่ยวข้องกับตรรกะเพิ่มเติมในการพิมพ์ ตรวจสอบอาร์กิวเมนต์ $class ของ mixin โดยตอบกลับด้วยการวนซ้ำหากมีการส่ง arglist เพื่อตรวจสอบว่าแต่ละรายการอยู่ในตัวแปร $global-filter หรือไม่

src/scss/tools/_filter.scss

 @mixin filter($class...) { @if(type-of($class) == 'arglist') { @each $item in $class { @if(index($global-filter, $item)) { @content; } } } @else if(index($global-filter, $class)) { @content; } }

ถ้าอย่างนั้น ก็แค่ย้อนกลับไปที่ส่วนต่อไปนี้เพื่อใช้ filter() mixin อย่างถูกต้อง:

  • objects/_box.scss
  • objects/_layout.scss
  • utilities/_alignments.scss

ณ จุดนี้ กลับไปที่ $imports และเปิดใช้งานเฉพาะองค์ประกอบ expander ในสไตล์ชีตที่คอมไพล์แล้ว นอกจากสไตล์จากเลเยอร์ทั่วไปและเลเยอร์องค์ประกอบแล้ว คุณควรเห็นสิ่งต่อไปนี้เท่านั้น:

  • คลาสบล็อกและองค์ประกอบที่เป็นของส่วนประกอบ expander แต่ไม่ใช่ตัวดัดแปลง
  • คลาสบล็อกและองค์ประกอบที่เป็นของการอ้างอิงของตัวขยาย
  • คลาสตัวดัดแปลงใด ๆ ที่เป็นของการพึ่งพาของตัวขยายซึ่งมีการประกาศอย่างชัดเจนในตัวแปร $dependencies

ในทางทฤษฎี ถ้าคุณตัดสินใจว่าคุณต้องการรวมคลาสเพิ่มเติมในสไตล์ชีตที่คอมไพล์แล้ว เช่น ตัวแก้ไขคอมโพเนนต์ของ expander ก็แค่เพิ่มลงในตัวแปร $global-filter ที่จุดประกาศ หรือต่อท้ายที่จุดอื่น ใน codebase (ตราบใดที่อยู่ก่อนจุดที่มีการประกาศตัวแก้ไข)

เปิดใช้งานทุกอย่าง

ดังนั้นตอนนี้ เรามีระบบที่ค่อนข้างสมบูรณ์ ซึ่งช่วยให้คุณนำเข้าอ็อบเจ็กต์ ส่วนประกอบ และยูทิลิตี้ลงไปยังแต่ละคลาสภายในบางส่วนเหล่านี้

ในระหว่างการพัฒนา ด้วยเหตุผลใดก็ตาม คุณอาจต้องการเปิดใช้งานทุกอย่างในครั้งเดียว เราจะสร้างตัวแปรใหม่ชื่อ $enable-all-classes แล้วเพิ่มตรรกะเพิ่มเติม ดังนั้นหากตั้งค่าเป็น true ทุกอย่างจะถูกคอมไพล์ไม่ว่าสถานะของ $imports imports และ $global-filter ตัวแปร $global-filter

ขั้นแรก ประกาศตัวแปรในไฟล์รายการหลักของเรา:

src/scss/main.scss

 $enable-all-classes: false; @import 'settings/core'; @import 'tools/core'; @import 'generic/core'; @import 'elements/core'; @import 'objects/core'; @import 'components/core'; @import 'utilities/core';

จากนั้นเราเพียงแค่ต้องทำการแก้ไขเล็กน้อยใน filter() และมิกซ์อินเรนเดอร์ render() เพื่อเพิ่มตรรกะการแทนที่ เมื่อตัวแปร $enable-all-classes ตั้งค่าเป็นจริง

ก่อนอื่น filter() มิกซ์อิน ก่อนการตรวจสอบที่มีอยู่ เราจะเพิ่มคำสั่ง @if เพื่อดูว่า $enable-all-classes ถูกตั้งค่าเป็น true หรือไม่ และถ้าเป็นเช่นนั้น ให้แสดง @content โดยไม่มีคำถามที่ถาม

src/scss/tools/_filter.scss

 @mixin filter($class...) { @if($enable-all-classes) { @content; } @else if(type-of($class) == 'arglist') { @each $item in $class { @if(index($global-filter, $item)) { @content; } } } @else if(index($global-filter, $class)) { @content; } }

ต่อไปในมิกซ์อิน render() เราแค่ต้องทำการตรวจสอบเพื่อดูว่าตัวแปร $enable-all-classes นั้นเป็นจริงหรือไม่ และถ้าเป็นเช่นนั้น ให้ข้ามการตรวจสอบเพิ่มเติม

src/scss/tools/_render.scss

 $layer: null !default; @mixin render($name) { @if($enable-all-classes or index(map-get($imports, $layer), $name)) { @content; } }

ดังนั้น หากคุณต้องตั้งค่าตัวแปร $enable-all-classes เป็น true และสร้างใหม่ ทุกคลาสที่เป็นทางเลือกจะถูกคอมไพล์ ช่วยให้คุณประหยัดเวลาในกระบวนการได้ค่อนข้างมาก

การเปรียบเทียบ

เพื่อดูว่าเทคนิคนี้ให้ผลกำไรประเภทใด เรามาลองเปรียบเทียบกันและดูว่าไฟล์มีความแตกต่างกันอย่างไร

เพื่อให้แน่ใจว่าการเปรียบเทียบนั้นยุติธรรม เราควรเพิ่มวัตถุ box และ container ใน $imports จากนั้นเพิ่ม o-box--spacing-regular modifier ของ $global-filter ดังนี้:

src/scss/settings/_imports.scss

 $imports: ( object: ( 'box', 'container' // 'layout' ), component: ( // 'button', 'expander' // 'typography' ), utility: ( // 'alignments', // 'widths' ) ); $global-filter: ( 'o-box--spacing-regular' );

วิธีนี้ช่วยให้แน่ใจว่าสไตล์สำหรับองค์ประกอบหลักของตัวขยายกำลังถูกคอมไพล์เหมือนที่มันจะเป็นหากไม่มีการกรองเกิดขึ้น

สไตล์ชีตดั้งเดิมและที่กรองแล้ว

มาเปรียบเทียบสไตล์ชีตดั้งเดิมกับคลาสทั้งหมดที่คอมไพล์แล้ว กับสไตล์ชีตที่กรองแล้วซึ่งมีคอมไพล์เฉพาะ CSS ที่คอมโพเนนต์ expander เท่านั้นที่คอมไพล์แล้ว

มาตรฐาน
สไตล์ชีต ขนาด (kb) ขนาด (gzip)
ต้นฉบับ 54.6kb 6.98kb
กรองแล้ว 15.34kb (เล็กกว่า 72%) 4.91kb (เล็กกว่า 29%)
  • ต้นฉบับ: https://webdevluke.github.io/handlingunusedcss/dist/index2.html
  • กรองแล้ว: https://webdevluke.github.io/handlingunusedcss/dist/index.html

คุณอาจคิดว่าการประหยัดเปอร์เซ็นต์ gzip หมายความว่าไม่คุ้มค่ากับความพยายาม เนื่องจากสไตล์ชีตดั้งเดิมและสไตล์ชีตที่กรองไม่ต่างกันมากนัก

ควรเน้นว่าการบีบอัด gzip ทำงานได้ดีกับไฟล์ที่ใหญ่และซ้ำซากกว่า เนื่องจากสไตล์ชีตที่กรองแล้วเป็นเพียงการพิสูจน์แนวคิด และมีเฉพาะ CSS สำหรับคอมโพเนนต์ expander เท่านั้น จึงไม่มีการบีบอัดมากเท่ากับในโปรเจ็กต์ในชีวิตจริง

หากเราต้องขยายขนาดแต่ละสไตล์ชีตขึ้น 10 เท่าเป็นขนาดทั่วไปของขนาดมัด CSS ของเว็บไซต์ ความแตกต่างของขนาดไฟล์ gzip นั้นน่าประทับใจกว่ามาก

ขนาด 10x
สไตล์ชีต ขนาด (kb) ขนาด (gzip)
ต้นฉบับ (10x) 892.07kb 75.70kb
กรอง (10x) 209.45kb (เล็กกว่า 77%) 19.47kb (เล็กกว่า 74%)

สไตล์ชีตที่กรองแล้วเทียบกับ UNCSS

นี่คือการเปรียบเทียบระหว่างสไตล์ชีตที่กรองแล้วกับสไตล์ชีตที่เรียกใช้ผ่านเครื่องมือ UNCSS

ถูกกรองเทียบกับ UNCSS
สไตล์ชีต ขนาด (kb) ขนาด (gzip)
กรองแล้ว 15.34kb 4.91kb
UNCSS 12.89kb (เล็กกว่า 16%) 4.25kb (เล็กกว่า 13%)

เครื่องมือ UNCSS ชนะที่นี่เล็กน้อย เนื่องจากการกรอง CSS ในไดเร็กทอรีทั่วไปและองค์ประกอบ

เป็นไปได้ว่าบนเว็บไซต์จริงที่มีองค์ประกอบ HTML หลากหลายกว่าที่ใช้อยู่ ความแตกต่างระหว่าง 2 วิธีนั้นอาจไม่สำคัญ

ห่อ

ดังนั้นเราจึงได้เห็นแล้วว่า — โดยใช้เพียงแค่ Sass — คุณสามารถควบคุมได้มากขึ้นว่าคลาส CSS ใดที่คอมไพล์บนบิลด์ ซึ่งจะช่วยลดปริมาณ CSS ที่ไม่ได้ใช้ในสไตล์ชีตสุดท้ายและเพิ่มความเร็วให้กับเส้นทางการแสดงผลที่สำคัญ

ในตอนต้นของบทความ ฉันได้ระบุข้อเสียบางประการของโซลูชันที่มีอยู่ เช่น UNCSS การวิพากษ์วิจารณ์วิธีแก้ปัญหาแบบ Sass ในลักษณะเดียวกันนั้นยุติธรรมเท่านั้น ดังนั้นข้อเท็จจริงทั้งหมดจะอยู่บนโต๊ะก่อนที่คุณจะตัดสินใจว่าวิธีใดดีกว่าสำหรับคุณ:

ข้อดี

  • ไม่จำเป็นต้องมีการพึ่งพาเพิ่มเติม คุณจึงไม่ต้องพึ่งพารหัสของคนอื่น
  • ใช้เวลาในการสร้างน้อยกว่าทางเลือกอื่นที่ใช้ Node.js เนื่องจากคุณไม่จำเป็นต้องเรียกใช้เบราว์เซอร์ที่ไม่มีส่วนหัวเพื่อตรวจสอบโค้ดของคุณ สิ่งนี้มีประโยชน์อย่างยิ่งกับการผสานรวมอย่างต่อเนื่อง เนื่องจากคุณอาจไม่ค่อยเห็นคิวของบิลด์
  • ให้ผลลัพธ์ในขนาดไฟล์ใกล้เคียงกันเมื่อเปรียบเทียบกับเครื่องมืออัตโนมัติ
  • นอกกรอบ คุณควบคุมได้อย่างสมบูรณ์ว่าโค้ดใดที่กำลังกรอง โดยไม่คำนึงว่าคลาส CSS เหล่านั้นจะถูกใช้ในโค้ดของคุณอย่างไร ด้วยทางเลือกอื่นที่ใช้ Node.js คุณมักจะต้องรักษารายการที่อนุญาตพิเศษแยกต่างหาก ดังนั้นคลาส CSS ที่เป็นของ HTML ที่ฉีดแบบไดนามิกจะไม่ถูกกรองออก

ข้อเสีย

  • โซลูชันที่เน้น Sass นั้นใช้งานได้จริงมากกว่า ในแง่ที่ว่าคุณต้องคอยติดตามตัวแปร $imports และ $global-filter นอกเหนือจากการตั้งค่าเริ่มต้น ทางเลือก Node.js ที่เราได้ตรวจสอบแล้วส่วนใหญ่เป็นแบบอัตโนมัติ
  • หากคุณเพิ่มคลาส CSS ให้กับ $global-filter แล้วลบออกจาก HTML ของคุณในภายหลัง คุณต้องอย่าลืมอัปเดตตัวแปร มิฉะนั้น คุณจะต้องคอมไพล์ CSS ที่คุณไม่ต้องการ ด้วยโปรเจ็กต์ขนาดใหญ่ที่นักพัฒนาหลายคนทำงานพร้อมกันในคราวเดียว การจัดการนี้อาจไม่ใช่เรื่องง่าย เว้นแต่คุณจะวางแผนไว้อย่างเหมาะสม
  • ฉันไม่แนะนำให้โบลต์ระบบนี้ไปยังฐานโค้ด CSS ที่มีอยู่ เนื่องจากคุณต้องใช้เวลาพอสมควรในการรวบรวมการพึ่งพาและใช้การเรนเดอร์ render() มิกซ์อินกับคลาสจำนวนมาก มันเป็นระบบที่ง่ายกว่ามากในการปรับใช้กับบิลด์ใหม่ โดยที่คุณไม่มีโค้ดที่ต้องต่อสู้ด้วย

หวังว่าคุณจะพบว่าสิ่งนี้น่าสนใจในการอ่านเช่นเดียวกับที่ฉันพบว่าน่าสนใจที่จะรวบรวม หากคุณมีข้อเสนอแนะ แนวคิดในการปรับปรุงแนวทางนี้ หรือต้องการชี้ให้เห็นข้อบกพร่องร้ายแรงที่ฉันพลาดไปทั้งหมด อย่าลืมโพสต์ในความคิดเห็นด้านล่าง