上一篇我們對React有了一個總體的認識,在介紹其中的技術細節之前,我們首先來瞭解一下用於React開發和模組管理的主流工具Webpack。稱之為React開發神器有點標題黨了,不過Webpack確實是筆者見過的功能最為強大的前端模組管理和打包工具。雖然Webpack是一個通用的工具,並不只適合於React,但是很多React的文章或者項目都使用了Webpack,尤其是react-hot-loader這樣的神器存在,讓Webpack成為最主流的React開發工具。
CommonJS和AMD是用於JavaScript模組管理的兩大規範,前者定義的是模組的同步載入,主要用於NodeJS;而後者則是非同步載入,通過requirejs等工具適用於前端。隨著npm成為主流的JavaScript組件發布平台,越來越多的前端項目也依賴於npm上的項目,或者自身就會發布到npm平台。因此,讓前端項目更方便的使用npm上的資源成為一大需求。於是誕生了類似browserify這樣的工具,代碼中可以使用require函數直接以同步文法形式引入npm模組,打包後再由瀏覽器執行。
Webpack其實有點類似browserify,出自Facebook的Instagram團隊,但功能比browserify更為強大。其主要特性如下: 同時支援CommonJS和AMD模組(對於新項目,推薦直接使用CommonJS); 串聯式模組載入器以及外掛程式機制,讓其具有更好的靈活性和擴充性,例如提供對CoffeeScript、ES6的支援; 可以基於配置或者智能分析打包成多個檔案,實現公用模組或者按需載入; 支援對CSS,圖片等資源進行打包,從而無需藉助Grunt或Gulp; 開發時在記憶體中完成打包,效能更快,完全可以支援開發過程的即時打包需求; 對sourcemap有很好的支援,易於調試。
Webpack將項目中用到的一切靜態資源都視之為模組,模組之間可以互相依賴。Webpack對它們進行統一的管理以及打包發布,其官方首頁用下面這張圖來說明Webpack的作用:
可以看到Webpack的目標就是對項目中的靜態資源進行統一管理,為產品的最終發布提供最優的打包部署方案。本文就將圍繞React對其相關用法做一個總體介紹,從而能讓你將其應用在自己的實際項目之中。 安裝Webpack,並載入一個簡單的React組件
Webpack一般作為全域的npm模組安裝:
npm install -g webpack
之後便有了全域的webpack命令,直接執行此命令會預設使用目前的目錄的webpack.config.js作為設定檔。如果要指定另外的設定檔,可以執行:
webpack —config webpack.custom.config.js
儘管Webpack可以通過命令列來指定參數,但我們通常會將所有相關參數定義在設定檔中。一般我們會定義兩個設定檔,一個用於開發時,另外一個用於產品發布。生產環境下的打包檔案不需要包含sourcemap等用於開發時的代碼。設定檔通常放在項目根目錄之下,其本身也是一個標準的CommonJS模組。
一個最簡單的Webpack設定檔webpack.config.js如下所示:
module.exports = { entry:[ './app/main.js' ], output: { path: __dirname + '/assets/', publicPath: "/assets/", filename: 'bundle.js' }};
其中entry參數定義了打包後的入口檔案,數組中的所有檔案會按順序打包。每個檔案進行依賴的遞迴尋找,直到所有相關模組都被打包。output參數定義了輸出檔案的位置,其中常用的參數包括: path: 打包檔案存放的絕對路徑 publicPath: 網站運行時的訪問路徑 filename: 打包後的檔案名稱
現在來看如何打包一個React組件。假設有如下專案檔夾結構:
- react-sample + assets/ - js/ Hello.js entry.js index.html webpack.config.js
其中Hello.js定義了一個簡單的React組件,使用ES6文法:
var React = require('react');class Hello extends React.Component { render() { return ( <h1>Hello {this.props.name}!</h1> ); }}
entry.js是入口檔案,將一個Hello組件輸出到介面:
var React = require('react');var Hello = require('./Hello');React.render(<Hello name="Nate" />, document.body);
index.html的內容如下:
<html><head></head><body><script src="/assets/bundle.js"></script></body></html>
在這裡Hello.js和entry.js都是JSX組件文法,需要對它們進行預先處理,這就要引入webpack的JSX載入器。因此在設定檔中加入如下配置:
module: { loaders: [ { test: /\.jsx?$/, loaders: ['jsx?harmony']} ]}
載入器的概念稍後還會詳細介紹,這裡只需要知道它能將JSX編譯成JavaScript並載入為Webpack模組。這樣在目前的目錄執行webpack命令之後,在assets目錄將產生bundle.js,打包了entry.js的內容。當瀏覽器開啟當前伺服器上的index.html,將顯示“Hello Nate!”。這是一個非常簡單的例子,示範了如何使用Webpack來進行最簡單的React組件打包。 載入AMD或CommonJS模組
在實際項目中,代碼以模組進行組織,AMD是在CommonJS的基礎上考慮了瀏覽器的非同步載入特性而產生的,可以讓模組非同步載入並保證執行順序。而CommonJS的require函數則是同步載入。在Webpack中筆者更加推薦CommonJS方式去載入模組,這種方式文法更加簡潔直觀。即使在開發時,我們也是載入Webpack打包後的檔案,通過sourcemap去進行調試。
除了項目本身的模組,我們也需要依賴第三方的模組,現在比較常用的第三方模組基本都通過npm進行發布,使用它們已經無需單獨下載管理,需要時執行npm install即可。例如,我們需要依賴jQuery,只需執行:
npm install jquery —save-dev
更多情況下我們是在項目的package.json中進行依賴管理,然後通過直接執行npm install來安裝所有依賴。這樣在項目的代碼倉庫中並不需要儲存實際的第三方依賴庫的代碼。
安裝之後,在需要使用jquery的模組中需要在頭部進行引入:
var $ = require('jquery');$('body').html<