原文地址:A Unified Styling Languagecss
原文做者:Mark Dalgleishhtml
譯文出自:掘金翻譯計劃前端
譯者:ZhangFereact
在過去幾年中,咱們見證了 CSS-in-JS 的興起,尤爲是在 React 社區。固然,它也飽含爭議。不少人,尤爲是那些已經對 CSS 很是熟悉的人都表示難以置信。android
"爲何有人要在 JS 中寫 CSS?webpack
這簡直是一個可怕的想法!ios
希望他們學過 CSS !"git
若是這就是你的反應,那麼請繼續讀下去。咱們來看看到底爲何在 JavaScript 中編寫樣式並非一個可怕的想法,而且爲何我認爲你應該關注這個快速發展的領域。github
React 社區常常被 CSS 社區誤解,反之亦然。對我來講這頗有趣,由於我常常混跡於這兩個社區。
我從九十年代後期開始學習 HTML,而且從基於表格佈局的黑暗時代以來就一直使用 CSS。受 CSS Zen Garden 啓發,我是最先一批將現有代碼向 語義化標籤 和級聯樣式表遷移的人。不久以後,我開始專一於先後端分離,使用非侵入式 JavaScript 和客戶端的交互來裝飾服務端渲染的 HTML。圍繞這些作法有一個小型且充滿活力的社區,而且咱們成爲第一代嘗試給瀏覽器平臺應有尊重的前端開發者。
伴隨這樣的背景,你可能會認爲我會強烈反對 React 的 HTML-in-JS 模式,它彷佛違背了咱們所堅持的原則,但實際上偏偏相反。根據個人經驗,React 的組件模型加上服務端渲染的能力,最終給咱們提供了一種構建大規模複雜單頁應用的方式,從而使咱們可以將快速,可訪問,逐漸加強的應用推送給咱們的用戶。在 SEEK 上咱們就利用了這種能力,這是咱們的旗艦產品,它是 React 單頁應用程序,當 JavaScript 被禁用時咱們的核心搜索流程依然可用,由於咱們經過在服務器端運行同構的 JavaScript 代碼來完成到傳統的網站優雅降級。
因此,也請考慮一下我拋出的從一個社區到另外一個社區的橄欖枝。讓咱們一塊兒嘗試理解這個轉變。它可能不完美,它可能不是你計劃在產品中使用的東西,它可能對你不是頗有說服力,可是至少值得你嘗試思考一下。
若是你熟悉我最近作的與 React 以及 CSS 模塊相關的工做,當看到我維護 CSS-in-JS 時你可能會很驚訝。
畢竟,一般那些但願有局部樣式可是又不但願在 JS 中寫 CSS 的開發者會選擇使用 CSS 模塊。事實上,甚至我本身在工做中也還沒用到 CSS-in-JS。
儘管如此,我任然對 CSS-in-JS 社區保持濃厚的興趣,對他們不斷提出的創意保持密切關注。不只如此,我認爲更普遍的 CSS 社區對它也應該很感興趣
緣由是什麼呢?
爲了更清楚地瞭解爲何人們選擇在 JavaScript 中編寫他們的樣式,咱們將重點關注採用這種方式時帶來的實際好處。
我把它分爲五個方面:
局部樣式
關鍵 CSS
智能優化
打包管理
在非瀏覽器環境下的樣式
讓咱們進一步的細分而且仔細看看 CSS-in-JS 提供的每一點優點。
想要在大規模項目中高效的構建 CSS 是很是困難的。當加入一個現有的長期運行的項目時,一般咱們會發現 CSS 是系統中最複雜的部分。
爲了解決這個問題,CSS 社區已經投入了巨大的努力,經過 Nicole Sullivan 的 OOCSS 和 Jonathan Snook 的 SMACSS 均可以使咱們的樣式更好維護,不過 Yandex 開發的 BEM 更流行一些。
根本上來講,BEM (純粹用於 CSS)只是一個命名規範,它要求樣式的類名要遵照 .Block__element--modifier
的模式。在任何使用 BEM 風格的代碼庫中,開發人員必須始終遵照 BEM 的規則。當嚴格遵照時,BEM 的效果很好,可是爲何這些如同做用域通常基礎的功能,卻只使用單純的命名規範來限制呢?
不管是否有明確表示,大多數 CSS-in-JS 類庫都遵循 BEM 的思路,它們嘗試將樣式定位到單個 UI 組件,只不過用了徹底不一樣的實現方式。
那麼在實際編寫代碼時什麼樣的呢?當使用 Sunil Pai 開發的 glamor 時,代碼看起來像下面這樣:
import { css } from 'glamor' const title = css({ fontSize: '1.8em', fontFamily: 'Comic Sans MS', color: 'blue' }) console.log(title) // → 'css-1pyvz'
你可能會注意到代碼中沒有 CSS 的類名。由於它再也不是一個指向定義在項目其餘位置 class 的硬編碼,而是由咱們的庫自動生成的。咱們沒必要再擔憂全局做用域內的選擇器衝突,這也意味着咱們再也不須要替他們添加前綴了。
這個選擇器的做用域與周圍代碼的做用域一致。若是你但願在你應用的其餘地方使用這個規則,你就須要將它改寫成一個 JavaScript 模塊而且在須要使用的地方引用它。就保持代碼庫的可維護性而言,它是很是強大的,它確保了任何給定的樣式均可以像其餘代碼同樣容易追蹤來源。
經過從僅僅是命名約定到默認強制局部樣式的轉變,咱們已經提升了咱們樣式質量的基準線。BEM 已經烙在裏面了,而再也不是一個可選項。
—
在繼續以前,我要說明相當重要的一點。
它生成的是真正的級聯樣式,而不是內聯樣式
大多數早期的 CSS-in-JS 庫都是將樣式直接添加到每一個元素上,可是這個模式有個嚴重的缺點,'styles' 屬性並不能作到 CSS 能夠作到的每件事。大多數新的庫再也不關注於動態樣式表,而是在運行時在全局樣式中插入和刪除規則。
舉個例子,讓咱們看看 Oleg Slobodskoi 開發的 JSS,這是最先的 CSS-in-JS 庫之一,而且它生成的是真實的 CSS。
當使用 JSS 時,你可使用標準的 CSS 特性,好比 hover 和媒體查詢,它們會映射到相應的 CSS 規則。
const styles = { button: { padding: '10px', '&:hover': { background: 'blue' } }, '@media (min-width: 1024px)': { button: { padding: '20px' } } }
一旦你將這些樣式插入到文檔中,你就可使用那些自動生成的類名。
const { classes } = jss.createStyleSheet(styles).attach()
不管你是使用一個完整的框架,仍是簡單的使用 innerHTML,你均可以在 JavaScript 中使用這些生成的 class,而不是硬編碼你的 class 字符串。
document.body.innerHTML = ` <h1 class="${classes.heading}">Hello World!</h1> `
單獨使用這種方式管理樣式並無多大的優點,它一般和一些組件庫搭配使用。所以,一般能夠找到用於最流行庫的綁定方案。例如,JSS 能夠經過 react-jss 的幫助輕鬆地綁定到 React 組件上,在管理生命週期的同時,它能夠幫你給每一個組件插入一小段樣式。
import injectSheet from 'react-jss' const Button = ({ classes, children }) => ( <button className={classes.button}> <span className={classes.label}> {children} </span> </button> ) export default injectSheet(styles)(Button)
經過將咱們的樣式集中到組件上,能夠將他們和代碼跟緊密的結合,這不就是 BEM 的思想麼?因此 CSS-in-JS 社區的不少人以爲在全部的樣式綁定樣板中,提取、命名和複用組件的重要性都丟失了。
隨着 Glen Maddern 和 Max Stoiber 提出了 styled-components 的概念,出現了一個新的思考這個問題的方式。
咱們直接建立組件,而不是建立樣式而後手動地將他們綁定到組件上。
import styled from 'styled-components' const Title = styled.h1` font-family: Comic Sans MS; color: blue; `
使用這些樣式時,咱們不會將 class 添加到存在的元素上,而是簡單地渲染這些被生成的組件。
<Title>Hello World!</Title>
雖然 styled-components 經過模板字面量的方式使用了傳統的 CSS 語法,可是有人更喜歡使用數據結構。來自 PayPal 的 Kent C. Dodds 開發的 Glamorous 是一個值得關注的替代方案。
Glamorous 和 styled-components 同樣提供了組件優先的 API,可是他的方案是使用對象而不是字符串,這樣就無需在庫中引入一個 CSS 解析器,能夠下降庫的大小並提升性能。
import glamorous from 'glamorous' const Title = glamorous.h1({ fontFamily: 'Comic Sans MS', color: 'blue' })
不管你使用什麼語法描述你的樣式,他們再也不僅僅是組件的一部分,他們和組件已經沒法分離。當使用一個像 React 這樣的庫時,組件是基本構建塊,而且如今咱們的樣式也成了構建這個架構的核心部分。若是咱們將咱們應用程序中的全部內容都描述爲組件,那麼爲何咱們的樣式不行呢?
—
考慮到咱們以前介紹的對系統作出改變的意義,對於那些有豐富 BEM 開發經驗的工程師來講,這一切看起來彷佛是一個很小的提高。事實上,CSS 模塊讓你在不用放棄 CSS 工具生態系統的同時得到了這些提高。不少項目堅持使用 CSS 模塊還有一個緣由,他們發現 CSS 模塊充分解決了編寫大規模 CSS 的問題,而且能夠保持編寫常規 CSS 時的習慣。
然而,當咱們開始在這些基本概念上構建時,事情開始變得更有趣。
在文檔頭部內聯關鍵樣式已經成爲一種比較新的最佳實踐,經過僅提供當前頁面所需的樣式能夠提升首屏時間。這與咱們經常使用的樣式加載方式造成了鮮明對比,以前咱們一般會強制瀏覽器在渲染以前爲應用下載全部的樣式。
雖然有工具能夠用於提取和內聯關鍵 CSS,好比 Addy Osmani 的 critical,可是他們沒法從根本上改變關鍵 CSS 難以維護和難以自動化的事實。這是一個棘手的、可選的性能優化,因此大部分項目彷佛放棄了這一步。
CSS-in-JS 則是一個徹底不一樣的故事。
當你的應用使用服務端渲染時,提取關鍵 CSS 不只僅是一個優化,從根本上來講,服務器端的 CSS-in-JS 是使用關鍵 CSS 的首要工做。
舉個例子,當使用 Khan Academy 開發的 Aphrodite 給元素添加 class 時,能夠經過內聯調用它的 css
函數來跟蹤在此次渲染過程當中使用的樣式。
import { StyleSheet, css } from 'aphrodite' const styles = StyleSheet.create({ title: { ... } }) const Heading = ({ children }) => ( <h1 className={css(styles.heading)}>{ children }</h1> )
即使你全部的樣式都是在 JavaScript 中定義的,你也能夠很輕鬆的從當前頁面中提取全部的樣式並生成一個 CSS 字符串,在執行服務端渲染時將它們插入文檔的頭部。
import { StyleSheetServer } from 'aphrodite'; const { html, css } = StyleSheetServer.renderStatic(() => { return ReactDOMServer.renderToString(<App/>); });
你能夠像這樣渲染你的關鍵 CSS:
const criticalCSS = ` <style data-aphrodite> ${css.content} </style> `;
若是你看過 React 的服務端渲染模型,你可能會發現這個模式很是熟悉。在 React 中,你的組件在 JavaScript 中定義他們的標記,但能夠在服務器端渲染成常規的 HTML 字符串。
若是你使用漸進加強的方式構建你的應用,儘管所有使用 JavaScript 編寫,但也有可能在客戶端根本就不須要 JavaScript
不管用哪一種方式,客戶端 JavaScript bundle 都要包含啓動單頁應用所需的代碼,它能讓頁面瞬間活起來,並與此同時開始瀏覽器中進行渲染。
因爲在服務器上渲染 HTML 和 CSS 是同時進行的,就像前面的例子所示, Aphrodite 這樣的庫一般會以一個函數調用的方式幫助咱們流式生成關鍵 CSS 和服務端渲染的 HTML。如今,咱們能夠用相似的方式將咱們的 React 組件渲染成靜態 HTML。
const appHtml = ` <div id="root"> ${html} </div> `
經過在服務器端使用 CSS-in-JS,咱們的單頁應用不只能夠脫離 JavaScript 工做,它甚至能夠加載的更快。
與咱們選擇器的做用域同樣,渲染關鍵 CSS 的最佳實踐現在已經烙在裏面了,而不是一個可選項。
咱們最近看到了構建 CSS 的新方式的興起,好比 Yahoo 的 Atomic CSS 和 Adam Morse 的 Tachyons,它們更喜歡短小的,單一用途的類名,而不是語義化的類名。舉個例子,當使用 Atomic CSS 時,你將使用相似於函數調用的語法去做爲類名,而且這些類名會在以後被用來生成合適的樣式表。
<div class="Bgc(#0280ae.5) C(#fff) P(20px)"> Atomic CSS </div>
經過最大程度地提升類的複用性以及用內聯樣式的方式同樣有效處理類名,能夠達到儘量地精簡 CSS 的目的。雖然文件大小的減小很容易體現,但對於你的代碼庫和團隊成員的影響確實是微乎其微的。這些優化會從底層引發你的 CSS 和標記語言的變化,使他們成爲構建工做中更重要的部分。
正如咱們已經介紹過的,當使用 CSS-in-JS 或者 CSS 模塊時,你再也不須要在 HTML 中硬編碼你的類名,而是動態引用由庫或者構建工具自動生成的 JavaScript 變量。
咱們這樣寫樣式:
<aside className={styles.sidebar} />
而不是:
<aside className="sidebar" />
這個變化可能看起來至關膚淺,可是從如何管理標記語言和樣式之間關係上來講,這倒是一個里程碑式的改變。經過給咱們的 CSS 工具不止修改樣式,還能修改最終提供給組件的 class 的能力,咱們爲咱們的樣式表解鎖了一個全新的優化方式。
若是看看上面的例子,就會發現 'styles.sidebar' 對應了一個字符串,但並無什麼去限制它只能是一個 class。就咱們所瞭解的,它能夠很容易的對應成表示十幾個 class 的字符串。
<aside className={styles.sidebar} /> // Could easily resolve to this: <aside className={'class1 class2 class3 class4'} />
若是咱們能夠優化咱們的樣式,爲每一套樣式生成多個類,咱們就能夠作一些很是有趣的事。
我最喜歡的例子是 Ryan Tsao 編寫的 Styletron。
與 CSS-in-JS 和 CSS 模塊自動添加 BEM 風格前綴的過程相同,Styletron 對 Atomic CSS 也作了相同的事。
它的核心 API 專一於一件事,爲每一個由屬性、值、媒體查詢組合起來的樣式定義一個獨立的 CSS 規則,而後返回自動生成的 class。
import styletron from 'styletron'; styletron.injectDeclaration({ prop: 'color', val: 'red', media: '(min-width: 800px)' }); // → 'a'
固然,Styletron 也提供了一些高級 API,好比它的 injectStyle
函數容許一次定義多個規則。
import { injectStyle } from 'styletron-utils'; injectStyle(styletron, { color: 'red', display: 'inline-block' }); // → 'a d' injectStyle(styletron, { color: 'red', fontSize: '1.6em' }); // → 'a e'
尤爲要注意上面生成的類名之間的相同點。
經過放棄對 class 自己的低級控制,而僅定義所須要的樣式集合,這些庫就能幫咱們生成最佳的 class 原子集合。
以前咱們經過手工查找的方式將樣式分割成可複用的 class,如今已經能夠徹底自動化的完成這種優化了,而且你應該也開始注意到這個趨勢。原子性 CSS 已經烙在裏面了,並不是一個可選項。
在談論這一點以前,咱們先停下來問本身一個看似簡單的問題。
咱們如何共享 CSS?
咱們已經從手動下載 CSS 文件向使用前端專門的模塊管理工具轉變,好比 Bower,或者如今經過 npm 可使用 Browserify 和 webpack。雖然這些工具已經自動處理了外部模塊的 CSS 依賴,可是目前前端社區大多仍是手工處理 CSS 的依賴關係。
不管使用哪一種方式,CSS 之間的依賴都不是很好處理。
大家許多人可能還記得,在使用 Bower 和 npm 管理 JavaScript 模塊時,出現過相似的狀況。
Bower 沒有依賴任何特定的模塊格式,而發佈到 npm 的模塊則要求使用 CommonJS 模塊格式。這種不一致,對發佈到二者任何一個平臺的包的數量都產生了巨大的影響。
小型可是有複雜依賴關係的模塊更願意使用 npm,Bower 則吸引了大量大型而獨立的模塊,固然,你可能也就有兩三個模塊,再加幾個插件,但因爲在 Bower 中你的依賴沒有一個模塊系統去做支撐,每一個包沒法簡單的利用它本身的依賴關係,因此在整合這一塊,基本上就留給開發者手動去操做了。
所以,隨着時間的推移,npm 上的模塊數量呈指數性增加,而 Bower 只能是有限的線性增加。雖然這多是各類緣由致使的,可是不得不說,主要緣由仍是在於兩個平臺處理運行時包與包之間的依賴關係的不一樣方法。
很不幸,這對於 CSS 社區來講太熟悉了,咱們發現相對於 npm 上的 JavaScript 來講,獨立 CSS 模塊的數量也增加的很慢。
若是咱們也想實現 npm 的指數增加該怎麼作?若是咱們想依賴不一樣大小不一樣層次的複雜模塊,而不是專一於大型、全面的框架呢?爲了作到這一點,咱們不只須要一個包管理器,還須要一個合適的模塊格式。
這是否意味着咱們須要專門爲 CSS 或者 Sass 和 Less 這樣的預處理器設計一個包管理工具?
有趣的是,在 HTML 上咱們已經實現了相似的功能。若是你問我相同的問題:咱們如何共享標記語言?你可能很快會想起來,咱們幾乎不會直接共享原始的 HTML —— 咱們共享 HTML-in-JS。
咱們經過 jQuery 插件,Angular 指令集 和 React 組件實現了這個功能。咱們的大組件由小組件組成,每個小組件都有着本身的 HTML,它們也都獨立的發佈在了 npm 上。HTML 這種格式可能不足以強大到完成這個功能,可是經過將 HTML 嵌入到完整的編程語言中,咱們就能夠很輕鬆的越過這個限制。
咱們能不能像 HTML 那樣,經過 JavaScript 去分享 CSS呢?能不能使用函數來返回對象和字符串而不是使用 mixins ?又或者咱們利用 Object.assign 和新的 object spread 操做符 來 merge 對象而不是用 extending classes 呢?
const styles = { ...rules, ...moreRules, fontFamily: 'Comic Sans MS', color: 'blue' }
一旦咱們開始用這種方式編寫咱們的樣式,咱們就可使用相同的模式、相同的工具、相同的基礎架構、相同的生態系統來編寫和分享咱們的樣式代碼,就像咱們應用程序中的其餘任何代碼同樣。
由 Max Stoiber、Nik Graf 和 Brian Hough 開發的 Polished 就是一個很好的例子。
Polished 就像是 CSS-in-JS 界的 Lodash,它提供了一整套完整的 mixins、顏色函數等等,使得在 JavaScript 中能夠獲得使用 Sass 編寫樣式的體驗。最大的區別在於,如今這些代碼在複用、測試和分享方面,都提升了一個層次,而且可以完整的使用 JavaScript 模塊生態系統。
當談到 CSS 時咱們會想,做爲一個由小型可複用的開源模塊組合成的一個樣式集合,咱們如何得到和 npm 上其餘模塊類似的開源程度?奇怪的是,咱們最終經過將咱們的 CSS 嵌入其餘的語言而且徹底擁抱 JavaScript 模塊實現了這一點。
到目前爲止,個人文章已經涵蓋了全部的要點,雖然在 JavaScript 中編寫 CSS 會容易的多,可是常規的 CSS 並不是完不成這些功能。這也是我把最有趣、最面向將來的一點留到如今的緣由。這一點並不必定能在現在的 CSS-in-JS 社區中發揮巨大的做用,但它可能會成爲將來設計的基礎層面。它不只會影響開發人員,也會影響設計師,最終它將改變這兩個領域相互溝通的方式。
首先,爲了介紹它,咱們須要先簡單介紹一下 React。
—
React 的理念是用組件做爲最終渲染的中間層。在瀏覽器中工做時,咱們構建複雜的虛擬 DOM 樹而不是直接操做 DOM 元素。
有趣的是,DOM 渲染相關的代碼並不屬於 React 的核心部分,而是由 react-dom 提供的。
import { render } from 'react-dom'
儘管最初 React 是爲 DOM 設計的,而且大部分狀況下仍是在瀏覽器中使用,可是這種模式也容許 React 只經過簡單地引入新的渲染引擎就能從容面對各類不一樣的使用環境。
JSX 不只僅能夠用於虛擬 DOM,他能夠用在任何的虛擬視圖上。
這就是 React Native 的工做原理,咱們經過編寫那些渲染成 native 的組件以實現用 JavaScript 編寫真正的 native 應用,好比咱們用 View 和 Text 取代了 div 和 span。
從 CSS 的角度來看,React 最有趣的就是它擁有本身的 StyleSheet API。
var styles = StyleSheet.create({ container: { borderRadius: 4, borderWidth: 0.5, borderColor: '#d6d7da', }, title: { fontSize: 19, fontWeight: 'bold', }, activeTitle: { color: 'red', } })
在這裏你會看到一組熟悉的樣式,咱們編寫了顏色、字體和邊框樣式。
這些規則都很是簡單,而且很容易映射到大部分的 UI 環境上,可是當涉及到 native 佈局時,事情就變得很是有趣了。
var styles = StyleSheet.create({ container: { display: 'flex' } })
由於在瀏覽器環境以外,因此 React Native 有本身的 flexbox 實現
最初發布時他是一個名爲 css-layout 的JavaScript 模塊,徹底用 JavaScript 從新實現了 flexbox(包含充分的測試),爲了更好的可移植性它如今已經遷移到 C 語言。
鑑於這個項目的影響力和重要性,它被賦予了更重要的品牌 ——— Yoga。
雖然 Yoga 專一於將 CSS 遷移到非瀏覽器環境中,可是僅關注於 CSS 特性的一小部分沒法擴大它的統治範圍。
"Yoga 的重點是成爲一個有表現力的佈局框架,而不是去實現一套完整的 CSS"
這看起來彷佛很難實現,可是當你回顧 CSS 體系的歷史時會發現使用 CSS 進行規模化的工做就是選擇一個合適的語言子集。
在 Yoga 中,爲了控制樣式的做用域,他們避開了級聯樣式,而且將佈局引擎徹底集中在 flexbox 上。雖然這樣會喪失不少功能,但它也爲須要嵌入樣式的跨平臺組件創造了驚人的機遇,咱們已經看到幾個試圖利用這個特性的開源項目。
Nicolas Gallagher 開發的 React Native for Web 旨在成爲 react-native 的一個替代品。當使用 webpack 這類打包工具時,很容易用別名來替換第三方庫。
module: { alias: { 'react-native': 'react-native-web' } }
使用 React Native for Web 後能夠在瀏覽器環境中運行 React Native 組件,包括 React Native 樣式 API
一樣,Leland Richardson 開發的 react-primitives 也提供了一套跨平臺的原始組件,它能夠抽象目標平臺的實現細節,爲跨平臺組件創造可行的標準。
甚至 微軟 也開始推出 ReactXP,這個庫旨在簡化跨 web 和 native 的工做流,它也有本身的跨平臺樣式實現
—
即便你不編寫 native 應用程序,也要注意一點:擁有一個真正的跨平臺組件抽象,可以使咱們將目標設定在那些高效的、無限可能的環境中去,有時這些會讓你沒法想象。
我所見過的最使人震驚的例子是 Airbnb 的 Jon Gold 開發的 react-sketchapp。
咱們不少人都花費了大量時間去嘗試標準化咱們的設計語言,而且儘量的避免系統中的重複。不幸的是,儘管咱們但願樣式只有一個來源,但咱們最多也只能減小到兩個,開發人員的動態樣式以及設計師的靜態樣式。雖然這已經比咱們以前的模式好了不少,可是它仍然須要咱們手工的將樣式從 Sketch 這樣的設計工具上同步到代碼裏。這也是 react-sketchapp 被開發出來的緣由。
感謝 Sketch 的 JavaScript API,以及 React 鏈接到不一樣渲染引擎的能力,react-sketchapp 讓咱們能夠用跨平臺的 React 組件渲染咱們的 Sketch 文件。
不用多說,這極可能改變設計師和開發人員的合做方式。如今,當咱們對設計進行迭代時,不管在設計工具仍是開發者工具上,咱們均可以經過相同的聲明引用同一個組件。
經過 Sketch 中的符號和 React 中的組件,咱們的行業已經開始從本質上趨於抽象,而且經過使用相同的工具咱們能夠更緊密的協做。
這麼多新的嘗試都來自 React 和其周邊的社區,看來這並非巧合。
在組件架構中,最重要的是將組件的功能集中在一塊兒。這天然包括它的局部樣式,往更復雜的方向延伸就涉及到數據的獲取。這裏要感謝 Relay 和 Apollo,讓這個過程變得簡單。這些成果解鎖了巨大了潛力,咱們如今所瞭解的,只是其中冰山一角。
雖然這對咱們編寫樣式產生了很大的影響,但其實它對咱們架構裏的一切都有很大的影響,固然,是出於好的理由。
經過統一單一語言開發組件的模式,咱們可以從功能上,而不是從技術上,將咱們的關注點進行更好的隔離。將組件的全部內容局部化,用他們構建大型可維護的系統,用以前沒法使用的方式進行優化,更容易的分享咱們的工做,以及利用小型開源模塊構建大型應用程序。更重要的是,完成這一切並不須要打破漸進加強的理念,也不會讓咱們放棄認真對待 web 平臺的理念。
最重要的是,我對使用單一語言編寫出的組件的潛力感到興奮,他們造成了一種新的、統一的樣式語言基礎,以一種史無前例的方式統一了前端社區。
在 SEEK,咱們正在努力利用這一功能,咱們圍繞組件模型來構建在線樣式指南,其中語義化、交互性和視覺風格都有統一的抽象。這構成了開發人員和設計師之間共享的通用設計語言。
構建一個頁面應該儘量的和拼裝組件同樣簡單,這樣能夠確保咱們工做的高品質,而且讓咱們在產品上線好久之後,也有能力去升級其設計語言。
import { PageBlock, Card, Text } from 'seek-style-guide/react' const App = () => ( <PageBlock> <Card> <Text heading>Hello World!</Text> </Card> </PageBlock> )
儘管咱們如今使用 React,webpack 和 CSS 模塊構建了這個樣式指南,可是這個架構,和任何你以前知道的 CSS-in-JS 系統是一致的。技術上可能不一致,可是核心理念是同樣的。
然而,將來這些技術選型可能也須要以一種意想不到的方式進行轉變,這也就是爲何保持對這個領域的持續關注,對與咱們不斷髮展的組件生態是如此的重要。咱們如今可能不會用 CSS-in-JS 這項技術,可是極可能沒過多久就會出現一個使人信服的理由讓咱們使用它。
CSS-in-JS 在短期裏有了出人意料的發展,但更重要的是,它只是這個宏偉藍圖的開始。
它還有很大的改進空間,而且它的創新尚未中止的跡象。新的庫正不斷涌現,它們解決了將來會出現的問題而且提高了開發人員的體驗 —— 好比性能的提高,在構建時抽取靜態 CSS,支持 CSS 變量以及下降了前端開發人員的入門門檻。
這也是 CSS 社區關注的地方。儘管這些對咱們的工做流程有很大的改動,可是他們不會改變你仍然須要學習 CSS 的事實。
咱們可能使用不一樣的語法,也可能以不一樣的方式構建咱們的應用,可是 CSS 的基本構建塊不會消失。一樣,咱們行業向組件架構的轉變是不可避免的,經過這種方式從新構想前端的意願只會愈來愈強烈。咱們很是須要共同合做以確保咱們的解決方案普遍適用於各類背景的開發人員,不管是專一於設計的仍是工程的。
雖然有時咱們的觀點不一致,可是 CSS 和 JS 社區對於改進前端,把 Web 平臺變得更加劇要以及改進咱們下一代 web 開發流程都有很大的激情。社區的潛力是巨大的,並且儘管到目前爲止咱們已經解決了大量的問題,仍然有不少工做尚未完成。
到這裏,可能你仍是沒有被說服,可是徹底不要緊。雖然如今在工做上使用 CSS-in-JS 不是很合適,但我但願它有合適的緣由,而不是僅僅由於語法就反對它。
不管如何,將來幾年這種編寫樣式的風格可能會愈來愈流行,而且值得關注的是它發展的很是快。我衷心但願你能夠加入咱們,不管是經過貢獻代碼仍是簡單的參與咱們的對話討論,都能讓下一代 CSS 工具儘量的提升前端開發人員的工做效率。或者,我但願已經讓大家至少了解爲何人們對這一塊如此飽含激情,或者,至少了解爲何這不是一個愚蠢的點子。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、React、前端、後端、產品、設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃。