理解 CSS 模塊化

2021-12-29 前端大全

(點擊上方公眾號,可快速關注)

原文:Hugo Giraudel

譯文:眾成翻譯

連結:www.zcfy.cc/article/understanding-the-css-modules-methodology-1329.html

在瞬息萬變的前端開發世界中,很難找到一個真正有意義的概念,並且將其清晰明了的向廣大人民群眾普及。

把目光投向CSS,一個重大轉折就是CSS預處理器的出現(在工具方面來看),其中,Sass應該是最為著名的一個。此外,還有 PostCSS,它和Sass略有不同,但是殊途同歸——都是用瀏覽器不能解析的語法編寫,並且最終編譯成瀏覽器能夠理解的語法。

現在,又有一位新的成員出現了,它就是CSS模塊。本文就將介紹CSS模塊化的諸多優點,以及如何編寫模塊化的CSS。

什麼是CSS模塊

首先,讓我們從官方文檔入手:

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. CSS模塊就是所有的類名都只有局部作用域的CSS文件。

事實稍微有一些複雜。由於類名需要默認具有局部作用域,這就涉及到一些初始設置、一個編譯過程,以及其他一些難以琢磨的東西。

但是最終,我們會為CSS模塊化帶來的好處而開心:CCS模塊將作用域限制於組件中,從而避免了全局作用域的問題。我們再也不用操心為組件尋找一個好的命名了,因為編譯過程已經幫你完成了這個任務。

它是如何工作的

CSS模塊需要在構建步驟進行管道化,這也就是說,它不是自動驅動的。它可以看成是webpack 或 Browserify的一個插件。其基本工作方式是:當你在一個JavaScript模塊中導入一個CSS文件時(例如,在一個 React 組件中),CSS模塊將會定義一個對象,將文件中類的名字動態的映射為JavaScript作用域中可以使用的字符串。舉個具體的例子:

如下是一個簡單的CSS文件。其中,.base類名不需要是工程中唯一的,因為它將不會是真正被解析的類名。它可以看成是在JavaScript模塊中使用的類在樣式表中的別名。

.base {

  color: deeppink;

  max-width: 42em;

  margin: 0 auto;

}

下面是該CSS類在JavaScript組件中的使用方式:

import styles from './styles.css';

 

element.innerHTML = `<div class="${styles.base}">

  CSS Modules are fun.

</div>`;

最終,它將生成下面這個東西(當使用webpack的默認步驟時):

`<div class="_20WEds96_Ee1ra54-24ePy">CSS Modules are fun.</div>`

._20WEds96_Ee1ra54-24ePy {

  color: deeppink;

  max-width: 42em;

  margin: 0 auto;

}

當然,生成的類名可以通過配置,使得它的長度更短或者遵循一些特定的模式。當然了,這些最終都不重要(雖然短的類名意味著更短的樣式表),重點在於這些類名是動態生成的、唯一的且和正確的樣式表一一對應的。

一些需要注意的地方

這就是CSS模塊工作的方式了。這時,你可能會想,「這到底是個什麼玩意兒,我甚至。。。」。OK,停下!我知道你想說什麼。現在就讓我一一解答你可能有的疑慮。

這看起來太醜了

確實如此。但是類名並不要求一定要長的好看對不對?只要可以將樣式正確的應用於元素就可以了嘛。而CSS模塊化方法完成的非常好,所以我覺得,這不是一個問題。

這非常難debug啊

由於需要有一個編譯的步驟,所以直接debug是非常困難的。其實,像Sass直接debug也是相當不容易的,所以我們才有了 sourcemaps。對於CSS模塊,我們也可以設置sourcemap。

其實,我還想說的是,雖然在模塊中,類的名字是自動生成而不可預知的,但是對於模塊來說,它還是比樣式表更容易debug的。只要你知道當前在開發者工具中查看的樣式屬於哪個模塊,在相應的樣式表中也是很容易定位。

這使得樣式不容易復用啦!

這句話既對也不對。一方面來說,確實如此。但這是因為模塊將CSS樣式和組件相綁定,從而不會發生全局樣式的衝突。這其實是一件好事,我相信你也會同意的對不對。

另一方面,要定義全局樣式也是可以的,只要使用:global()就好了。比如,作者需要保留的全局輔助樣式。

:global(.clearfix::after) {

  content: '';

  clear: both;

  display: table;

}

CSS模塊還可以從其他模塊中繼承樣式,這和Sass中的@extend方法其實是一樣的。它不會拷貝樣式,只是將選擇器連接到繼承的樣式中。

.base {

  composes: appearance from '../AnoherModule/styles.css';

}

它需要webpack,Browserify或者其他工具!

這和Sass需要將.scss文件編譯成CSS文件,PostCSS需要將樣式表處理成瀏覽器能夠識別的樣式其實是一樣的。無論如何,都需要一個構建步驟。

我們究竟為什麼要討論這個東西?

其實,我甚至不確定CSS模塊在未來到底會不會繼續存在,不過,我確定這是一種編寫樣式的正確方式。試想,在拆分成許多細小組件的龐大站點中,卻擁有一個臃腫的全局樣式表,這肯定是不合適的。

CSS統一的名空間使得它既強大又脆弱。而CSS模塊化或者未來延續這個思想的其他工具可以在支持樣式復用的同時,避免命名衝突,這是一個雙贏的選擇。

入門

如前面所說的,你需要有webpack或者Browserify來實現CSS模塊化。

Webpack

先從webpack版本的模塊化開始。在webpack.config.js中,加上如下配置,使得webpack將CSS文件作為CSS模塊來看待:

{

  test: /\.css$/,

  loader: 'style-loader!css-loader?modules'

}

這時,它將把樣式注入到頁面中的元素中。這可能不是我們想要的,使用extract text plugin for webpack,我們可以很方便的抽取出樣式表:

{

  test: /\.css$/,

  loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules')

}

對於webpack,要講的就是這麼多了。

Browserify

我只在命令行中用過Browserify,所以我猜使用起來會更複雜一些。在package.json文件中,加入 npm script :

{

  "scripts": {

    "build": "browserify -p [ css-modulesify -o dist/main.css ] -o dist/index.js src/index.js"

  }

}

這條命令告訴Browserify運行src/index.js,返回dist/index.js,並且使用 css-modulesify將樣式表編譯至dist/main.css。如果你想再加上Autoprefixer,那麼命令可以寫成這樣:

{

  "scripts": {

    "build": "browserify -p [ css-modulesify --after autoprefixer -o dist/main.css ] -o dist/index.js src/index.js"

  }

}

如你所見,使用--after選項可以在編譯完成樣式表時候,繼續對它進行處理。

總結

從今天看來,CSS模塊化系統和生態確實有些原始了,從Browserify中的配置就能看出來。不過,我確信CSS模塊化將變得更好,並且越來越多的人將意識到不管對小項目還是大項目來說,這都是一個很好的方法。

我認為CSS模塊化背後的思想是正確的。當然,我不是說這個庫就是最佳解決方案,但是,它確實包含了一些CSS應該採用的寫法:模塊化、作用域隔離、同時支持復用。

關注「前端大全」

看更多精選前端技術文章

↓↓↓

相關焦點

  • 理解CSS模塊化
    此外,還有 PostCSS,它和Sass略有不同,但是殊途同歸——都是用瀏覽器不能解析的語法編寫,並且最終編譯成瀏覽器能夠理解的語法。現在,又有一位新的成員出現了,它就是CSS模塊。本文就將介紹CSS模塊化的諸多優點,以及如何編寫模塊化的CSS。
  • CSS 預處理語言的模塊化實踐
    對於小型項目來說,css的量還不至於龐大,問題沒有凸顯,而如果要開發和持續維護一個較為大型的項目,那就需要對css進行管理和規範了,否則會發生不可挽回的後果(嚇唬誰呢??)。背景上一節【從css談模塊化】我們通過規範的約束,將css的編寫方式進行了優化和改進,形成一種可持續發展的路線。但還是遺留了一些問題:冗餘。
  • 前端模塊化理解
    模塊化是前端工程化中最重要的一部分,因為目前的前端項目中,單個文件裡面的代碼已經多到非常臃腫的地步,不利於開發和管理。而模塊化開發是目前比較主流的解決方法,它通過將文件代碼安裝不同的功能來劃分為不同的模塊區域文件,以此來提高開發效率,降低維護成本模塊化本質上是一種思想,並不是一種具體的實現,需要的用其他的方式來實現代碼的模塊化在JS中,模塊化理想情況下應該允許我們:抽象代碼:將功能實現抽離到特定的庫,使用者無需去關注複雜的內部實現邏輯。封裝代碼:如果不希望代碼被修改,則將代碼隱藏在模塊中。
  • UI庫(CSS+HTML)
    2:移動端適配,移動端的高速發展,各種屏幕大小的適配,以及不同系統的兼容問題,以及市面上各種眼花繚亂的適配方案,讓我們頭暈目眩,在加上less,sass,scss的出現,多了些許邏輯在裡面,讓我們寫css代碼如同寫js。
  • 這幾個CSS概念你了解嗎?
    言歸正傳,css近年來了也催生了蠻多新的解決方案,比如 CSS Modules、styled-components(css in js )、Functional CSS、CSS 原子類、CSS沙盒等等❞1. CSS Module❝CSS Module 顧名思義就是 CSS 模塊化,為什麼需要模塊化?
  • 巧用 Postcss,增強你的 CSS 代碼
    PostCSS Preset Env 幫你將最新的 CSS 語法轉換成大多數瀏覽器都能理解的語法,並根據你的目標瀏覽器或運行時環境來確定你需要的 polyfills,此功能基於 cssdb 實現。首先就是安裝基礎插件:npm install postcss-loader postcss --save-devoryarn add postcss-loader postcss -D然後在你的
  • 如何理解JavaScript模塊化?
    1、模塊化是什麼模塊化簡單來說就是將一個完整的長篇代碼文件根據功能進行劃分成幾個文件
  • CSS module了解下
    ES678快速普及前端工程發愈發成熟,CSS 被被遠遠甩在了後面,JS語言模塊已經標準化,CSS還是在不斷探索,同時這也是一個急需解決的問題。要是你以前還從未聽說過CSS Modules,那麼這篇就是專門寫給你的。如果你了解過它,你就沒必要再看了,因為他真的很簡單(很強大)。CSS的痛點我們都知道,CSS入門簡單,深入就比較難,樣式簡單維護難。
  • CSS Modules 入門及 React 中實踐
    02為什麼我們需要CSS模塊化CSS全局作用域問題CSS的規則都是全局的,任何一個組件的樣式規則,都對整個頁面有效。相信寫css的人都會遇到樣式衝突(汙染)的問題。03CSS模塊化方案分類CSS 模塊化的解決方案有很多,但主要有三類。
  • PostCSS (一):認識 PostCSS
    它可以作為一款 CSS 前置處理器( preprocessor ) 使用, 就像 Sass 和 Less 等一樣,使用 postcss-simple-vars, postcss-mixins, postcss-nested, postcss-sass-extend 等插件來實現 Sass 提供的 變量, mixin,選擇器嵌套,extend 等功能。
  • 讓CSS更完美:PostCSS-modules
    但是我們並沒有一個可以模塊化CSS的方法。對於一個高質量項目來說,獨立的UI組件(也就是組件化)非常重要的 — 每個組件小巧獨立,可以拼合成複雜的頁面,這讓我們節省了很多的工作。但是我們始終有一個疑問,如何防止全局命名衝突那?
  • 【第584期】簡單易懂的CSS Modules
    本文由@acgtofe分享css modules。正文從這開始~不要誤會,CSS Modules可不是在說「css模塊化」這個好像在某些地方見過的詞,它其實是特指一種近期才出現的技術手段。什麼技術手段呢?請待後文說明。層疊樣式表我們知道,css的全名叫做層疊樣式表,這個「層疊」到底是什麼意思呢?
  • CSS Modules 與 scoped 的不一樣
    css 的作用域表現。CSS Modules是一個CSS文件,其中所有類名和動畫名稱默認為局部作用域。使用JS編譯原生的CSS文件,使其具備模塊化的能力,該文件需要import使用。Scoped在vue文件中的style標籤上,有一個特殊的屬性:scoped。
  • CSS Modules 詳解及 React 中實踐
    也變成了前端走向徹底模塊化前必須解決的難題。CSS 模塊化的解決方案有很多,但主要有兩類。一類是徹底拋棄 CSS,使用 JS 或 JSON 來寫樣式。Radium,jsxstyle,react-style 屬於這一類。
  • Normalize.css 與 Reset CSS 之間的區別
    Normalize.css 作者 necolas 很久之前在 stackoverflow.com 上回答過該問題,詳情可見 https://stackoverflow.com/users/1077469/necolas。知道Normalize.css和傳統Reset的區別是非常有價值的。1.
  • 談談 PostCSS
    css,是一種樣式腳本,好像和程式語言有著一定的距離,我們可以將之理解為一種描述方法。這似乎導致css被輕視了。不過,css近幾年來正在經歷著一次巨變——CSS Module。我記得js的井噴期應該可以說是node帶來的,它帶來了Module的概念,使得JS可以被工程化開發項目。那麼,今天的css,也將越來越美好。如果你喜歡我的文章,歡迎評論,歡迎Star~。
  • postcss開發實戰
    初識 postcsscss 是 web 開發中重要的一部分,然而 css 規範仍存在一些瀏覽器兼容性問題,由此出現了 sass、less、stylus 等 css 預處理器,提高了開發人員的效率。postcss 的官方定義:A tool for transforming CSS with JavaScript. 一個用 javascript 來處理 css 語法的工具。
  • 爬蟲逆向基礎,理解 JavaScript 模塊化編程 webpack
    這種寫法貌似沒有官方的名稱,相當於進行了模塊化編程,因此大多數人稱其為 webpack,上面的示例看起來比較費勁,簡單優化一下:!function test() {    console.log(this.firstName + " " + this.lastName)}var data = {firstName: "John", lastName: "Doe"}test.bind(data)()  // John Doe理解
  • 為什麼不會有CSS4了?
    CSS2.1的PDF版有430頁(https://www.w3.org/TR/CSS2/css2.pdf)。這就給勘誤和進一步升級帶來了極大不便。因為文檔不同部分升級的進度不可能強求一致。於是,CSS工作組決定從CSS2.1之後開始採取模塊化的路線。就是把需要升級的內容獨立成模塊拆分出來,新增的需求也以新模塊的方式立項。從此以後,CSS就進入了Level 3。
  • 如何理解 css - BFC
    css視覺格式化模型(visual formatting model)總結,visual formatting model決定瀏覽器如何顯示如何處理文檔樹。盒子類型和定位方案決定元素盒子如何在文檔樹中顯示和放置。