如果你想用React構建一個新的JavaScript應用,而且你還想實踐ES6文法中的新特性,此外,你甚至想建立一些可重用組件並發布到NPM上,那麼你究竟應該怎樣實現這些需求。你如何將ES6代碼發布到NPM,又如何在後續的項目中使用這些代碼。我花了一些時間解決上面這些問題,現在我願意與你們分享我習得的新知識。
如果你真的不希望閱讀所有的細節,只想看看代碼最終的效果——可以直接閱讀最後一部分。
需求
我們先來搞清楚我們到底想要得到什麼,應該如何去實現。
我們的主要目標是:基於ES6,使用我們自訂的React組件建立一個React應用。其中最棘手的部分是自訂React組件。以下是實現這些目標的需求列表:
自訂群組件應該使用ES6編寫; 自訂群組件應該完全自給自足(使用方法足夠簡單:安裝,匯入,渲染); 自訂群組件應該提供自身所需的樣式(參考第2條,自給自足); 自訂群組件應該通過NPM安裝(因為bower有很多問題); 最後——所有自訂群組件應該有單元測試和程式碼涵蓋範圍報告; 加分項——自訂群組件不應該相互依賴,但是應該能夠相互影響。
此外,我們需要一些很棒的調試工具,例如:代碼檢查、源碼映射(因為代碼需要編譯,所以這是調試的必要工具)。
處理需求
現在我們已瞭解所有需求,可以開始尋找滿足這些需求的方法。所以,首先需要選定我們將使用的工具集和相關庫。
編譯
我們要基於ES6開發應用,目前的瀏覽器暫不完全支援所有新文法特性,所以我們需要將ES6編譯為ES5。同時我們希望通過NPM管理自訂群組件,需要選用一個相容CommonJS的工具集。
目前有兩種流行的可用選擇——Browserify和Webpack。二者都滿足我們的大部分需求,考慮到我們的項目需要使用樣式檔案,而Webpack對非JavaScript檔案(例如:樣式檔案、圖片、字型檔)非常友好,所以最終我們將選用Webpack。
Webpack已經能夠滿足大部分需求,我們將在此基礎上加入Gulp.js,協助我們完成更多任務(例如:單元測試、程式碼涵蓋範圍檢測、靜態資源伺服)。
使用ES6
現在我們已經知道如何使用Webpack和Gulp.js來構建代碼,可是如何才能滿足我們的第一個需求——使用ES6。我們可以使用轉譯器,協助我們將ES6代碼轉譯為主流瀏覽器支援的ES5代碼。目前流行的轉譯器有:Traceur、Babel.js、TypeScript(勉強算是),我們將選用Babel.js,它有一個更好的生態系統(外掛程式、擴充等)。如果你尚不知曉其為何物,請記住這是一個非常棒的項目,我推薦你閱讀它們的文檔。最棒的是,Babel.js不僅支援ES6文法,它還可以編譯JSX,所以我們可以在編譯步驟徹底棄用標準React JSX編譯器了。
如果你只想使用Babel.js,我推薦你閱讀它們的使用文檔。Axel Rauschmayer博士曾經撰寫《教你使用Babel.js》一文,也值得一讀,如果你對JavaScript感興趣,我也極力推薦訂閱他的部落格。
自給自足
現在我們選定了ES6轉譯器,讓我們討論一下自給自足的問題。如果我們開發純React組件——那麼可以輕鬆地讓它們獨立工作(可重用),你甚至可以參考官方指南學習編碼方式。但如果我們需要在組件內提供預設的自身樣式,需要怎樣實現呢。
當然,我們可以選擇“純JS”方法向我們的JSX檔案加入內聯樣式,就像這樣:
[js] view plain copy const render = function() { const defaultStyle = { color: 'red', }; return ( <div style={defaultStyle}> I have inline styles </div> ); };
JSX內聯樣式
這個方法存在一個問題,我們幾乎無法通過父應用控制這個組件的樣式。而且,如果我們需要載入圖片或自訂字型檔,這個方法就會失效。所以,是否有更好的方法呢。
Webpack可以幫你解決這個問題。幸運的是,Webpack 載入器可以載入許多類型的檔案。其背後的思想非常簡單——在載入過程中動態地對載入檔案進行可插拔轉換。從本質上來說,載入器為我們處理各種檔案。我們將選用一個特殊的babel-loader來將我們的ES6代碼轉譯為ES5代碼。
但最酷的是,載入器可以處理任何檔案。所以,如果我們想載入樣式——我們只需要添加style-loader。最終,我決定使用LESS,它稍微複雜一些——我將建立如下的載入鏈:
首先,使用less-loader處理*.less檔案,將其轉換為CSS; 然後,使用css-loader將編譯好的css傳遞給下一個步驟; 最後,使用style-loader將最終的樣式引入到產生的程式碼中。
通過這個載入鏈,我們可以使用LESS編寫組件的樣式,下面這段代碼示範了這種組件的進入點:
[js] view plain copy import './style/style.less'; import Component from './src/component'; export default Component;
藉助Webpack將樣式引入到JavaScript中
正如你所見,載入樣式像匯入檔案一樣簡單。的確,由less-loader、css-loader以及style-loader構成的載入鏈必須要在我們的Webpack設定檔中提前配置好(參考下一節的第一個樣本)。
現在我們可以從相互獨立的組件中載入樣式,但是CSS預設使用全域變數,這意味著如果兩個組件中使用了相同的類名,其中一個將被改寫,我們如何迴避這個問題呢。
我能想出來的最簡單的方法是:在HTML標籤和樣式檔案中,使用組件名稱作為最外層元素的類名,人為地建立組件的範圍。就像這樣:
[js] view plain copy .component-name { span { color: red; } } const render =