การจัดการ CSS ที่ไม่ได้ใช้ใน Sass เพื่อปรับปรุงประสิทธิภาพ
เผยแพร่แล้ว: 2022-03-10ในการพัฒนา 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 แม้ว่าจะบีบอัดไฟล์แล้วก็ตาม ที่ดูเหมือนมาก
เราจะมาดูกันว่า CSS นี้ถูกใช้จริงมากแค่ไหนในหน้าแรกของพวกเขา? การค้นหาโดย Google อย่างรวดเร็วเผยให้เห็นเครื่องมือออนไลน์มากมายที่เหมาะกับงาน แต่ฉันชอบใช้เครื่องมือ ครอบคลุม ใน Chrome ซึ่งสามารถเรียกใช้โดยตรงจาก DevTools ของ Chrome ให้มันหมุน
ผลลัพธ์แสดงให้เห็นว่า CSS เพียง 30kb จากสไตล์ชีต 568kb ถูกใช้โดยหน้าแรก โดยที่เหลืออีก 538kb เกี่ยวข้องกับสไตล์ที่จำเป็นสำหรับส่วนที่เหลือของเว็บไซต์ ซึ่งหมายความว่าไม่ได้ใช้ CSS มากถึง 94.8%
CSS เป็นส่วนหนึ่งของเส้นทางการแสดงผลที่สำคัญของหน้าเว็บ ซึ่งเกี่ยวข้องกับขั้นตอนต่างๆ ทั้งหมดที่เบราว์เซอร์ต้องดำเนินการให้เสร็จสิ้นก่อนที่จะเริ่มแสดงหน้าเว็บ สิ่งนี้ทำให้ CSS เป็นเนื้อหาที่บล็อกการแสดงผล
ด้วยเหตุนี้ เมื่อโหลดเว็บไซต์ของ Sheffield United โดยใช้การเชื่อมต่อ 3G ที่ดี จึงต้องใช้เวลาทั้งหมด 1.15 วินาทีก่อนที่จะดาวน์โหลด CSS และการแสดงหน้าเว็บสามารถเริ่มต้นได้ นี่คือปัญหา.
Google รับรู้สิ่งนี้เช่นกัน เมื่อเรียกใช้การตรวจสอบ Lighthouse ทางออนไลน์หรือผ่านเบราว์เซอร์ของคุณ เวลาในการโหลดและการลดขนาดไฟล์ที่อาจเกิดขึ้นซึ่งสามารถทำได้โดยการลบ CSS ที่ไม่ได้ใช้จะถูกเน้น
โซลูชั่นที่มีอยู่
เป้าหมายคือการกำหนดคลาส CSS ที่ไม่ต้องการและลบออกจากสไตล์ชีต มีโซลูชันที่มีอยู่ซึ่งพยายามทำให้กระบวนการนี้เป็นอัตโนมัติ โดยทั่วไปสามารถใช้ได้ผ่านสคริปต์บิลด์ Node.js หรือผ่านทางตัวดำเนินการเช่นอึก ซึ่งรวมถึง:
- UNCSS
- PurifyCSS
- PurgeCSS
โดยทั่วไปแล้วสิ่งเหล่านี้ทำงานในลักษณะเดียวกัน:
- บน Bulld เว็บไซต์สามารถเข้าถึงได้ผ่านเบราว์เซอร์หัวขาด (เช่น: puppeteer) หรือการจำลอง DOM (เช่น: jsdom)
- ตามองค์ประกอบ HTML ของหน้า จะมีการระบุ CSS ที่ไม่ได้ใช้
- สิ่งนี้จะถูกลบออกจากสไตล์ชีต เหลือเพียงสิ่งที่จำเป็นเท่านั้น
แม้ว่าเครื่องมืออัตโนมัติเหล่านี้จะใช้งานได้อย่างสมบูรณ์ และฉันได้ใช้หลายตัวในโครงการเชิงพาณิชย์หลายโครงการอย่างประสบความสำเร็จ ฉันพบข้อเสียบางประการระหว่างทางซึ่งควรค่าแก่การแบ่งปัน:
- หากชื่อคลาสมีอักขระพิเศษ เช่น '@' หรือ '/' ระบบอาจไม่จดจำชื่อเหล่านี้หากไม่ได้เขียนโค้ดที่กำหนดเอง ฉันใช้ 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
ในเว็บเบราว์เซอร์ของคุณ คุณจะเห็นส่วนประกอบมาตรฐาน ซึ่งเมื่อคลิกจะขยายเพื่อแสดงเนื้อหาบางส่วน คุณยังสามารถดูสิ่งนี้ได้ที่นี่ ซึ่งจะใช้เงื่อนไขเครือข่ายจริง คุณจึงทำการทดสอบของคุณเองได้
การกรองที่ระดับบางส่วน
ในการตั้งค่า 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()
มิกซ์อินกับคลาสจำนวนมาก มันเป็นระบบที่ง่ายกว่ามากในการปรับใช้กับบิลด์ใหม่ โดยที่คุณไม่มีโค้ดที่ต้องต่อสู้ด้วย
หวังว่าคุณจะพบว่าสิ่งนี้น่าสนใจในการอ่านเช่นเดียวกับที่ฉันพบว่าน่าสนใจที่จะรวบรวม หากคุณมีข้อเสนอแนะ แนวคิดในการปรับปรุงแนวทางนี้ หรือต้องการชี้ให้เห็นข้อบกพร่องร้ายแรงที่ฉันพลาดไปทั้งหมด อย่าลืมโพสต์ในความคิดเห็นด้านล่าง