React
技術之火爆無須多言,其與webpack
的完美結合,也讓兩者毋庸置疑的成爲天生一對。爲了進行React
的快速和規範化開發,開源社區中涌現了不少React
+webpack
的boilerplate
項目。經過使用這些boilerplate
,咱們能夠快速的建立一個React項目的架構。javascript
蔥哥以前專門建立了一個Github項目用於收集這些boilerplate
:awesome-react-boilerplate。固然這裏不可能完整收錄,可是目前爲止已經有近30個了。連boilerplate都這麼多,真讓咱們眼花繚亂,無從下手。css
固然,因爲每一個人的使用習慣和技術背景的不一樣,每一個boilerplate
都會有本身的側重點,所以即使是公認比較好的boilerplate項目也未必適合全部人。咱們拿到這些開源項目,只是知其然可是並不知其因此然。蔥哥相信,只有適合本身的,纔是最好的。這就是本文的初衷,蔥哥會追根溯源,從項目開發的蠻荒階段開始,搭建開發環境,配置webpack
,在React
項目中使用webpack
,搭建項目的測試環境,一步一步構建適合適合本身的React
+ webpack
起始項目。html
本文陸陸續續寫了將近一個月的時間,所使用的技術和依賴庫均選用目前最新版本,其間大大小小的坑踩過不知道多少。本文供入門參考,若是你是前端大牛,請直接忽略此文。固然,若是讀後以爲對你有幫助,還請關注蔥哥的Github。前端
TL;DRjava
如前所述,本文的主要目的是構建適合適合本身的React
+ webpack
起始項目。與其餘多數相似項目不一樣的是,咱們不只要支持ES6,使用webpack,並且要搭建一套相對完整的單元測試和自動化測試體系。本文主要使用到的相關技術以下:node
Reactreact
webpackwebpack
babelgit
ES6es6
mocha
chai
sinon
karma
phantomJS
<!--more-->
Webpack是一個前端模塊管理工具,有點相似browserify,出自Facebook的Instagram團隊,但功能比browserify更爲強大,能夠說是目前最爲強大的前端模塊管理和打包工具。
Webpack將項目中的全部靜態資源都當作模塊,模塊之間能夠互相依賴,由webpack對它們進行統一的管理和打包發佈,下圖爲官方網站說明:
webpack對React有着與生俱來的良好支持,隨着React的流行,webpack也成了React項目中必不可少的一部分。特別是隨着ES6的普及,使得webpack有了更廣闊的用武之地。
安裝webpack以前,須要確認本機已經安裝好了nodejs。
若是尚未安裝,請去nodejs官網下載安裝便可。這裏使用的node版本是V4.4.1.
$ mkdir react_boilerplate $ cd react_boilerplate\ $ npm init -y Wrote to .\react_boilerplate\package.json: { "name": "react_boilerplate", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
npm init
加上一個-y
選項會生成一個默認的package.json
,關於這個文件,不是本文重點,在此不會詳述,能夠參考官方文檔。能夠簡單的理解,這個文件是用於管理項目裏面的依賴包的。
若是咱們使用git進行版本管理,一個.gitignore文件是必要的。這裏咱們能夠先將項目須要安裝的node包目錄添加進去。
node_modules
使用npm install
安裝的node包都會在node_modules
目錄下,這個目錄是不須要commit到git的。
安裝webpack很簡單,命令以下:
npm i webpack --save-dev
其中--save-dev
表示該包爲開發環境依賴包。安裝完後會生成一個node_modules
目錄,而且在package.json
文件中多出以下幾行:
...... "devDependencies": { "webpack": "^1.13.0" } }
若是寫爲--save
則表示該包爲生產環境依賴包,在package.json
文件中會新增或者修改dependencies
字段。
安裝完webpack
後,咱們能夠給項目中增長一些內容了。項目的簡單結構以下圖所示:
app
目錄用於存放項目代碼,dist
目錄爲編譯後的項目文件,webpack.config.js
爲webpack
的配置文件。
咱們給項目中的文件添加一些簡單的代碼,首先是組件代碼:
module.exports = function () { var element = document.createElement('h1'); element.innerHTML = 'Hello world'; return element; };
而後須要一個入口文件,在入口文件中使用上面定義的組件:
var component = require('./component'); document.body.appendChild(component());
咱們須要讓webpack知道如何處理咱們的項目目錄結構,所以須要配置文件webpack.config.js
。一個簡單的配置文件以下所示:
var webpack = require('webpack'); var path = require('path'); //引入node的path庫 var config = { entry: ['./app/index.js'], //入口文件 output: { path: path.resolve(__dirname, 'dist'), // 指定編譯後的代碼位置爲 dist/bundle.js filename: 'bundle.js' }, module: { loaders: [ // 爲webpack指定loaders //{ test: /\.js$/, loaders: ['babel'], exclude: /node_modules/ } ] } } module.exports = config;
到目前爲止,咱們已經可讓webpack工做了,在命令行執行
webpack
咱們看到,會有一個新的文件/dist/bundle.js
生成出來了。可是咱們還須要一個html文件來加載編譯後的代碼,這就須要用到一個webpack插件:html-webpack-plugin
。
html-webpack-plugin
使用以下命令安裝:
npm install html-webpack-plugin --save-dev
而後在咱們的webpack.config.js
中增長下面幾行:
plugins: [ new HtmlwebpackPlugin({ title: 'React Biolerplate by Linghucong' }) ]
如今在命令行下再次執行webpack
命令,會看到在dist
目錄下生成了兩個文件:bundle.js
和index.html
。其中index.html
內容以下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>React Biolerplate by Linghucong</title> </head> <body> <script src="bundle.js"></script></body> </html>
有必要提一下,若是咱們安裝webpack的時候使用的是全局安裝選項(npm install -g webpack
),能夠在命令行中直接執行webpack
命令;若是沒有使用-g
,那麼要用的webpack
可執行文件位於:
./node_modules/.bin/webpack
咱們能夠在package.json
中爲此命令增長一個快捷方式:
# package.json ... other stuff "scripts": { "build": "./node_modules/.bin/webpack" }
如今就能夠直接使用命令npm run build
來執行webpack了。
$ npm run build > react_boilerplate@1.0.0 build D:\node\react_boilerplate > webpack Hash: cbf754a65493b4d791d7 Version: webpack 1.13.0 Time: 919ms Asset Size Chunks Chunk Names bundle.js 233 kB 0 [emitted] main index.html 179 bytes [emitted] [0] multi main 52 bytes {0} [built] [75] ./app/index.js 82 bytes {0} [built] [76] ./app/component.js 142 bytes {0} [built] + 74 hidden modules Child html-webpack-plugin for "index.html": + 3 hidden modules
webpack-dev-server
webpack-dev-server
可讓咱們在本地啓動一個web服務器,使咱們更方便的查看正在開發的項目。其安裝也十分簡單:
npm i webpack-dev-server --save-dev
而後在webpack.config.js
文件中做以下修改:
# webpack.config.js # ... entry: [ 'webpack/hot/dev-server', 'webpack-dev-server/client?http://localhost:3000', './app/index.js' //入口文件 ], # ...
咱們能夠在package.json
中增長webpack-dev-server
的快捷方式:
# package.json ... other stuff "scripts": { "dev": "webpack-dev-server --port 3000 --devtool eval --progress --colors --hot --content-base dist", "build": "./node_modules/.bin/webpack" }
配置中指定web服務器端口號爲3000,指定目錄爲dist。
運行npm run dev
:
$ npm run dev > react_boilerplate@1.0.0 dev D:\node\react_boilerplate > webpack-dev-server --port 3000 --devtool eval --progress --colors --hot --content-base dist ...... Time: 1109ms Asset Size Chunks Chunk Names bundle.js 274 kB 0 [emitted] main index.html 179 bytes [emitted] chunk {0} bundle.js (main) 216 kB [rendered] [0] multi main 52 bytes {0} [built] ...... ...... ...... [77] ./app/component.js 142 bytes {0} [built] Child html-webpack-plugin for "index.html": chunk {0} index.html 505 kB [rendered] [0] ./~/html-webpack-plugin/lib/loader.js!./~/html-webpack-plugin/default_index.ejs 540 bytes {0} [buil t] [1] ./~/lodash/lodash.js 504 kB {0} [built] [2] (webpack)/buildin/module.js 251 bytes {0} [built] webpack: bundle is now VALID.
web服務器啓動完畢,此時訪問 http://localhost:3000/ 就能夠看到咱們的「Hello world」了。
須要特別說明的是,webpack-dev-server
是支持熱加載的,也就是說咱們對代碼的改動,保存的時候會自動更新頁面。好比咱們在文件中將「Hello world」改成「Linghucong」,會看到頁面實時更新了,無須再按F5刷新,爽吧?!
webpack-dev-server
的配置還能夠放在webpack.config.js
中,須要使用一個devServer
屬性,詳細能夠參考官方文檔。
項目中使用CSS是必不可少的。webpack中使用
loader的方式來處理各類各樣的資源,根據設定的規則,會找到相應的文件路徑,而後使用各自的loader來處理。CSS文件也須要特定的loader,通常須要使用兩個:css-loader
和 style-loader
,若是使用LESS或者SASS還須要加載對應的loader。這裏咱們使用LESS,所以安裝loaders:
npm install css-loader style-loader less-loader --save-dev
npm3.0以上須要單獨安裝less:npm install less --save-dev
。
而後在文件webpack.config.js
中配置:
{ test: /\.less$/, loaders: ['style', 'css', 'less'], include: path.resolve(__dirname, 'app') }
能夠看到,test裏面包含一個正則,包含須要匹配的文件,loaders是一個數組,包含要處理這些文件的loaders,注意loaders的執行順序是從右到左的。
新建一個LESS文件/app/index.less
,其內容以下:
h1 { color: green; }
在入口文件index.js
中引入這個文件:
require('./index.less');
而後運行webpack進行編譯:npm run build
:
$ npm run build > react_boilerplate@1.0.0 build D:\node\react_boilerplate > webpack Hash: 0c25c4bacdc334db1e04 Version: webpack 1.13.0 Time: 1902ms Asset Size Chunks Chunk Names bundle.js 243 kB 0 [emitted] main index.html 179 bytes [emitted] [0] multi main 52 bytes {0} [built] [75] ./app/index.js 110 bytes {0} [built] [80] ./app/component.js 141 bytes {0} [built] + 78 hidden modules Child html-webpack-plugin for "index.html": + 3 hidden modules
能夠看到, http://localhost:3000/ 頁面上的文字已經變成綠色了。
到目前爲止的代碼能夠在react_boilerplate _v1中查看。
Javascript中的包管理比較常見的有幾種方式:
//CommonJS 定義的是模塊的同步加載,主要用於NodeJS var MyModule = require('./MyModule'); // export at module root module.exports = function() { ... }; // alternatively, export individual functions exports.hello = function() {...};
//AMD 是異步加載,好比require.js使用這種規範 define(['./MyModule.js'], function (MyModule) { // export at module root return function() {}; }); // or define(['./MyModule.js'], function (MyModule) { // export as module function return { hello: function() {...} }; });
//ES6 變得愈來愈主流了 import MyModule from './MyModule.js'; // export at module root export default function () { ... }; // or export as module function, // you can have multiple of these per module export function hello() {...};
還有其餘格式如UMD、CMD等,在此再也不一一介紹。webpack對這些模塊格式均可以很好的支持。在咱們以前的項目中使用的是CommonJS格式的模塊管理,可是隨着ES6的普及和應用,同時得益於強大的Babel的存在,使咱們能夠方便的使用ES6的語法,而沒必要考慮瀏覽器支持的問題。
在webpack中支持ES6一樣只須要安裝配置相應的loader就能夠了。
安裝以下:
npm install babel-loader babel-core babel-preset-es2015 babel-preset-react --save-dev
在webpack.config.js
中添加loader以下:
{ test: /\.jsx?$/, loader: 'babel', exclude: /node_modules/, query: { presets: ['react', 'es2015'] } }
因爲後邊須要支持React的jsx文件,因此咱們在這裏安裝了babel-preset-react
。
順便提一下,咱們能夠在項目根目錄下建立一個.babelrc
文件,將loader中的presets
放在文件.babelrc
中:
# .babelrc { "presets": ["react", "es2015"] }
此時咱們運行npm run build
,正常編譯後,使用npm run dev
,啓動web服務器,打開 http://localhost:3000/ 能夠看到頁面已經能夠正常顯示了。
若是上面對於loader的配置寫爲(注意這裏是loaders
不是loader
):
{ test: /\.jsx?$/, loaders: ['babel'], exclude: /node_modules/, query: { presets: ['es2015', 'react'] } }
則可能會出現這樣的錯誤:
$ npm run build > react_boilerplate@1.0.0 build D:\node\react_boilerplate > webpack D:\node\react_boilerplate\node_modules\webpack-core\lib\LoadersList.js:54 if(!element.loader || element.loader.indexOf("!") >= 0) throw new Error("Cannot define 'query' and multiple loaders in loaders list"); ^ Error: Cannot define 'query' and multiple loaders in loaders list at getLoadersFromObject (D:\node\react_boilerplate\node_modules\webpack-core\lib\LoadersList.js:54:65) at LoadersList. (D:\node\react_boilerplate\node_modules\webpack-core\lib\LoadersList.js:78:12) at Array.map (native) at LoadersList.match ...
緣由是使用了多個loader
,而query
僅僅做用於babel-loader
。若是非要使用loaders
加載多個loader
,能夠作以下修改:
var babelPresets = {presets: ['react', 'es2015']}; ...... loaders: ['other-loader', 'babel-loader?'+JSON.stringify(babelPresets)] ......
到目前爲止的代碼能夠在react_boilerplate _v2中查看。
關於React的介紹和基本概念相信你已經有所瞭解,若是須要,能夠參考本文最後的「參考閱讀」中的連接,在此再也不詳述。
npm install react react-dom --save
這裏咱們使用的版本是15.0.1。
$ npm install react react-dom --save react_boilerplate@1.0.0 D:\node\react_boilerplate +-- react@15.0.1 | `-- fbjs@0.8.1 | +-- isomorphic-fetch@2.2.1 | | +-- node-fetch@1.5.1 | | | +-- encoding@0.1.12 | | | | `-- iconv-lite@0.4.13 | | | `-- is-stream@1.1.0 | | `-- whatwg-fetch@0.11.0 | `-- ua-parser-js@0.7.10 `-- react-dom@15.0.1
在項目中咱們使用了html-webpack-plugin插件來用webpack自動生成入口的index.html文件,可是裏面的內容咱們無法控制。html-webpack-plugin提供了一種模板的機制,可讓咱們對生成的文件內容進行定製。
咱們使用一個新的目錄templates用於存放模板文件,新建一個index.ejs文件:
<%= htmlWebpackPlugin.options.title %> Welcome to New Page
修改webpack.config.js
文件以下:
plugins: [ new HtmlwebpackPlugin({ title: 'React Biolerplate by Linghucong', template: path.resolve(__dirname, 'templates/index.ejs'), inject: 'body' }) ]
關於 html-webpack-plugin 更多高級用法能夠參考其項目主頁。
sourcemap的做用各位自行Google吧。要生成編譯出的js文件的sourcemap文件,只須要在webpack配置文件中加入以下一行配置便可:
devtool: 'source-map',
運行npm run build
能夠看到一個會在dist
目錄生成一個新的文件bundle.js.map
,這就是sourcemap文件。
要對生成的js文件進行壓縮,須要使用一個新的插件:UglifyJsPlugin。
修改webpack.config.js
以下:
...... var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin; var config = { ...... plugins: [ ...... new UglifyJsPlugin({ minimize: true }) ] } module.exports = config;
運行npm run build
能夠看到生成的bundle.js文件已經被minify了。
在實際的項目開發中,咱們在開發階段通常不須要將代碼minify,由於壓縮以後很不方便調試。所以,咱們有必要將開發模式和發佈模式區分開。咱們經過設置process.env.WEBPACK_ENV
來作區分。
修改webpack.config.js
以下:
...... var env = process.env.WEBPACK_ENV; var outputFile; var plugins = [new HtmlwebpackPlugin({ title: 'React Biolerplate by Linghucong', template: path.resolve(__dirname, 'templates/index.ejs'), inject: 'body' })]; if (env === 'build') { var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin; plugins.push(new UglifyJsPlugin({ minimize: true })); outputFile = 'bundle.min.js'; } else { outputFile = 'bundle.js'; } var config = { ...... output: { path: path.resolve(__dirname, 'dist'), filename: outputFile }, ...... plugins: plugins } module.exports = config;
同時須要修改npm run的快捷方式,在package.json
文件中修改以下:
"scripts": { "dev": "WEBPACK_ENV=dev webpack-dev-server --port 3000 --devtool eval --progress --colors --hot --content-base dist", "build": "WEBPACK_ENV=build webpack" },
在Windows系統上不能像上述那樣設置WEBPACK_ENV
,可使用set
來設置,以下:
"scripts": { "test": "mocha --compilers js:babel-register --require ./test/test_helper.js --recursive ./test", "test:watch": "npm test -- --watch", "dev": "set WEBPACK_ENV=dev&&webpack-dev-server --port 3000 --devtool eval --progress --colors --hot --content-base dist", "build": "set WEBPACK_ENV=build&&webpack" },
對咱們的組件稍做修改:
import './index.less'; import component from './component'; let content = document.getElementById("content"); content.appendChild(component());
而後編譯,運行:
$ npm run build $ npm run dev
能夠看到,目前訪問 http://localhost:3000/ 的頁面顯示已經發生了變化。
經過查看源代碼,能夠看到咱們頁面正是應用了咱們的模板文件。
到目前爲止的代碼能夠在react_boilerplate _v3中查看。
咱們將app/index.js
修改一下,建立一個新的React組件。
import React from 'react'; import ReactDOM from 'react-dom'; class HelloReact extends React.Component { render() { return Hello React! } } ReactDOM.render(, document.getElementById('content'));
代碼十分簡單,引入了react
和react-dom
,建立了一個叫作HelloReact的組件,並將其渲染到頁面上id爲content
的DOM元素內。
咱們在以前已經在webpack的配置中配置好了對React的支持,所以目前不須要作什麼修改了。
npm run build
以後就能夠在頁面上看到「Hello React!」了。
至此,咱們基於ES6並使用webpack和Babel的React初始項目已經能夠完美運行了。
到目前爲止的代碼能夠在react_boilerplate _v4中查看。
如上所見,我在這裏使用Mocha + Chai + Sinon 這幾個技術來搭建咱們的測試環境,簡單介紹以下:
Mocha:用於運行咱們的測試用例。
Chai:Mocha用的斷言庫。
Sinon:用於建立一些mocks/stubs/spys。
另外值得一提的是,AirBnB建立了一個專門針對React代碼測試的開源程序:Enzyme,有興趣的能夠研究一下。
安裝很簡單,命令以下:
npm i mocha chai sinon --save-dev
由於咱們要支持ES6的語法,所以還須要安裝一個額外的插件babel-register
:
npm i babel-register --save-dev
Mocha默認會去當前目錄下找test目錄,而後在其中去找後綴爲.js的文件。若是須要修改這個目錄,可使用Mocha的參數進行設置。
咱們這裏建立一個新的目錄,叫作test,而後一個新的Spec文件:
import { expect } from 'chai'; describe('hello react spec', () => { it('works!', () => { expect(true).to.be.true; }); });
這個時候咱們在命令行中使用命令mocha --compilers js:babel-register
運行mocha,若是順利的話,能夠看到以下結果:
$ mocha --compilers js:babel-register hello react spec √ works! 1 passing (11ms)
簡單解釋一下這裏的babel-register
。若是這裏沒有添加--compilers
選項,則mocha會按照默認的方式執行,也就是「讀取spec文件」->「運行測試用例」。使用了babel-register
以後,則執行順序爲「讀取spec文件」->「將ES6代碼編譯爲ES5代碼」->「運行測試用例」。
若是執行mocha --compilers js:babel-register
命令的時候,出現以下的錯誤:
$ mocha --compilers js:babel-register D:\node\react_boilerplate\test\index.spec.js:1 (function (exports, require, module, __filename, __dirname) { import { expect } from 'chai'; ^^^^^^ SyntaxError: Unexpected reserved word at exports.runInThisContext (vm.js:53:16) at Module._compile (module.js:373:25) at loader (D:\node\react_boilerplate\node_modules\babel-register\lib\node.js:126:5) at Object.require.extensions.(anonymous function) [as .js] (D:\node\react_boilerplate\node_modules\babel-register\lib\node.js:136:7) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Module.require (module.js:353:17) at require (internal/module.js:12:17) at C:\Users\i301792\AppData\Roaming\npm\node_modules\mocha\lib\mocha.js:219:27 at Array.forEach (native) at Mocha.loadFiles (C:\Users\i301792\AppData\Roaming\npm\node_modules\mocha\lib\mocha.js:216:14) at Mocha.run (C:\Users\i301792\AppData\Roaming\npm\node_modules\mocha\lib\mocha.js:468:10) at Object. (C:\Users\i301792\AppData\Roaming\npm\node_modules\mocha\bin\_mocha:403:18) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Function.Module.runMain (module.js:441:10) at startup (node.js:139:18) at node.js:968:3
這個錯誤多是因爲Babel的版本引入的。在這裏提供了一個解決方案:
在咱們項目中建立一個.babelrc文件,其內容以下:
{ "presets": ["react", "es2015"] }
其做用以前講過了。如今就能夠將咱們webpack.config.js
中對應設置刪除了:
#webpack.config.js ... { test: /\.jsx?$/, loader: 'babel', exclude: /node_modules/ },
注意到咱們在每一個測試spec文件中,都會須要引入chai庫的expect,這樣就會有不少重複代碼。固然還有其餘一些通用的幫助性代碼,所以咱們須要一個庫來集中進行管理。這裏咱們建立一個新的文件/test/test_helper.js
:
import { expect } from 'chai'; import sinon from 'sinon'; global.expect = expect; global.sinon = sinon;
在這裏我只是添加了chai的expect,以及引入了sinon。
如今就能夠將index.spec.js
文件的第一行刪除,而後經過以下的命令來執行mocha命令了:
mocha --compilers js:babel-register --require ./test/test_helper.js --recursive
執行結果以下:
λ mocha --compilers js:babel-register --require ./test/test_helper.js --recursive hello react spec √ works! 1 passing (12ms)
package.json
中的快捷方式在package.json
中咱們能夠建立上述mocha命令的快捷方式。在scripts
字段中做以下修改:
#package.json "scripts": { "test": "mocha --compilers js:babel-register --require ./test/test_helper.js --recursive ./test", "test:watch": "npm test -- --watch", "dev": "webpack-dev-server --port 3000 --devtool eval --progress --colors --hot --content-base dist", "build": "webpack" },
而後就可使用
npm run test
來直接運行mocha了。
注意這裏我還新增長了一個npm run test:watch
快捷方式,其實就是使用了mocha的--watch
選項。有了它,當咱們在對代碼進行修改的時候,就會自動運行test了。
到目前爲止的代碼能夠在react_boilerplate _v5中查看。
Karma是一個基於Node.js的前端測試啓動器(Test Runner),它出自Google的Angularjs團隊。該工具可用於測試全部主流Web瀏覽器,能夠支持Chrome、Safari、Firefox、IE、Opera甚至PhantomJS。
安裝Karma:
npm install karma --save-dev
而後還須要安裝咱們須要用到的一些依賴庫:
npm install lolex phantomjs-prebuilt phantomjs --save-dev npm install karma-chai karma-chai-plugins karma-chai-sinon karma-mocha karma-mocha-reporter karma-phantomjs-launcher karma-sinon karma-sinon-chai karma-sourcemap-loader karma-webpack --save-dev
不要問我爲何裝那麼多擴展,由於我踩過不少坑,這裏就直接跳過了:<
而後咱們就可使用karma命令來生成一個配置文件。
λ .\node_modules\.bin\karma.cmd init karma.conf.js Which testing framework do you want to use ? Press tab to list possible options. Enter to move to the next question. > mocha Do you want to use Require.js ? This will add Require.js plugin. Press tab to list possible options. Enter to move to the next question. > no Do you want to capture any browsers automatically ? Press tab to list possible options. Enter empty string to move to the next question. > PhantomJS > Chrome > What is the location of your source and test files ? You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js". Enter empty string to move to the next question. > app/*.js > test/*.spec.js > Should any of the files included by the previous patterns be excluded ? You can use glob patterns, eg. "**/*.swp". Enter empty string to move to the next question. > Do you want Karma to watch all the files and run the tests on change ? Press tab to list possible options. > yes Config file generated at "D:\node\react_boilerplate\karma.conf.js".
而後咱們就可使用karma start
命令來運行咱們的測試用例了。不過如今直接運行可能還有一些問題,暫時先無論。
咱們使用一個單獨的文件test.webpack.js
來保存測試文件的路徑,方便在karma設置中進行預處理。新建文件test.webpack.js
以下:
function requireAll(requireContext) { return requireContext.keys().map(requireContext); } var modules = requireAll(require.context("./test", true, /.+\.spec\.jsx?$/)); module.exports = modules
而後修改karma.config.js
:
var webpackConfig = require('./webpack.config'); webpackConfig.devtool = 'inline-source-map'; module.exports = function (config) { config.set({ browsers: [ 'PhantomJS' ], singleRun: true, frameworks: [ 'mocha', 'chai', 'sinon', 'sinon-chai' ], files: [ 'test.webpack.js' ], plugins: [ 'karma-phantomjs-launcher', 'karma-chrome-launcher', 'karma-chai', 'karma-mocha', 'karma-sourcemap-loader', 'karma-webpack', 'karma-mocha-reporter', 'karma-sinon', 'karma-sinon-chai' ], preprocessors: { 'test.webpack.js': [ 'webpack', 'sourcemap' ] }, reporters: [ 'mocha' ], webpack: webpackConfig, webpackServer: { noInfo: true }, autoWatch: true }); };
好了,到如今爲止,咱們能夠正常運行咱們的測試用例了。使用命令karma start
運行結果以下:
$ karma start START: 29 04 2016 13:26:50.350:INFO [karma]: Karma v0.13.22 server started at http://localhost:9876/ 29 04 2016 13:26:50.375:INFO [launcher]: Starting browser PhantomJS 29 04 2016 13:26:52.072:INFO [PhantomJS 2.1.1 (Windows 8 0.0.0)]: Connected on socket /#05AECTTMgBTkXK4kAAAA with id 76498752 hello react spec √ works!!! Finished in 0.008 secs / 0.001 secs SUMMARY: √ 1 test completed
能夠看到,測試用例測試經過了。
目前咱們在karma的配置文件中設置的瀏覽器類型是「browsers: [ 'PhantomJS' ]」,也就是會使用PhantomJS來運行。若是須要使用其餘瀏覽器,能夠作相應修改,甚至添加多個。好比咱們要支持打開Chrome瀏覽器運行測試,修改以下:
browsers: [ 'Chrome' ]
正常運做的前提是,必須事先安裝好了對應的插件,對應Chrome的就是'karma-chrome-launcher',其餘瀏覽器類型相似處理。
咱們以前使用npm run test
來運行測試,npm run test:watch
來監聽文件改變並運行測試。使用karma以後,須要在package.json
中做以下修改:
"scripts": { "test": "karma start", "test:watch": "watch \"npm run test\" app/", ...... }
另外須要安裝一個npm包:
npm install watch --save-dev
這樣咱們就可使用npm run test
來運行測試,npm run test:watch
來監聽文件改變並自動運行測試了:
到目前爲止咱們本身的react boilerplate已經建立完畢了!代碼能夠在react_boilerplate _v6中查看。
本文帶你一步步創建了本身的react boilerplate項目,可是須要知道的是,文中所述甚淺,只是帶你入門罷了。其中每個話題,均可以展開來再寫一系列的文章。好比測試所用的mocha+chai+sinon套裝,好比React測試利器Enzyme等。即使是文中已經成型的代碼,亦多有可優化的地方。若是你有好的意見或者建議,也歡迎到這個Github repo上來提pull request或者issue:
https://github.com/jiji262/react_boilerplate
最後,感謝閱讀。
Building Your First React.js App
Building modular javascript applications in ES6 with React, Webpack and Babel
STATIC SITE GENERATION WITH REACT AND WEBPACK
LEARN REACT.JS A LITTLE AT A TIME, PART 1
Setting up React for ES6 with Webpack and Babel
Mocha + Chai.js unit testing for ES6 with Istanbul code coverage