Facebook的一幫子工程師在忙碌之餘開發除了一套前段UI框架React
。這個框架最大的有點就在於讓UI的開發都基於元件
,這樣View都是根據props和state變化的。
專案地址:https://github.com/future-challenger/petshop/tree/master/client
雖然學React
比起來其他的前端框架要容易不少,但是其生態的各種工具(Babel, Webpack)卻著實讓人費一番功夫。事實上,這些工具不只適用於React
。但是為了發揮ES2015
和JSX
的威力需要它們。這裡,我們主要討論如何建立React
的開發環境,工具的事不做主要討論。
現在開始進入正題
建立一個目錄react-demo的目錄,並在裡面初始化npm專案。
mkdir react-demo
cd react-demo
npm init
按照要求填寫npm init
命令需要的輸入內容就可以。
安裝配置Webpack
Webpack
是一個模組打包工具,可以把模組以及其依賴項一起打包成靜態資源的工具。由於對載入器的支援,webpack和React完美契合。本文的後面會詳細討論。
使用npm安裝webpack。
npm install webpack --save-dev
Webpack需要某些配置才能完成給他的工作。所以我們需要建立一個webpack.config.js
的配置檔案。
touch webpack.config.js
在該檔案中新增如下的程式碼。
var webpack = require(`webpack`);
var path = require(`path`);
var BUILD_DIR = path.resolve(__dirname, `src/client/public`);
var APP_DIR = path.resolve(__dirname, `src/client/app`);
var config = {
entry: APP_DIR + `/index.jsx`,
output: {
path: BUILD_DIR,
filename: `bundle.js`
}
};
module.exports = config;
Webpack的配置最少需要兩項,一個是入口屬性,一個是輸出屬性。APP_DIR
指向React專案的程式碼所在目錄,BUILD_DIR
指向打包後檔案的輸出目錄。
就如同配置項名稱所表達的一樣。entry是打包所需要的入口檔案。如果你對靜態語言,比如c/c++之類的熟悉的話。這個入口檔案就是c/c++包含main方法的檔案。Webpack支援多個入口檔案。這裡目錄src/client/app裡的index.jsx檔案就是整個應用的入口檔案。
output指明webpack在打包完成後需要做什麼。這裡,使用src/client/public目錄存放打包後生成的檔案bundle.js。
在src/client/app目錄下建立檔案index.jsx。並新增如下程式碼。
console.log(`Hello World!`);
在terminal裡輸入下面的命令。
$ ./node_modules/.bin/webpack -d
命令會呼叫webpack,生成開發環境下的bundle.js檔案以及關聯的map檔案bundle.js.map。這兩個檔案都在配置檔案制定的目錄src/client/public下。
但是目前只看到了編譯之後的js檔案,不夠直觀。在目錄src/client下建立一個index.html檔案。這樣js檔案是否載入成功都能看到了。
<html>
<head>
<meta charset="utf-8">
<title>React.js using NPM, Babel6 and Webpack</title>
</head>
<body>
<div id="app" />
<script src="public/bundle.js" type="text/javascript"></script>
<span style="float:center">Yo!</span>
</body>
</html>
現在開啟瀏覽器,你就會看到“Yo”了。
注意:
有一個webpack的載入器`html-loader`可以自動建立html檔案。裡面會把編譯以後的js檔案的路徑新增好。
使用Babel-Loader
就如前文所說,使用JSX和ES2015我們的開發效率會更高。但是JSX語法和ES2015在某些瀏覽器裡是不相容的。
因此,如果我們要使用React程式碼,我們就需要使用一個工具把JSX和ES2015翻譯成瀏覽器都支援的語法。Babel
就是幹這個用的。
在安裝webpack的時候我們就接觸到了一個概念載入器,Webpack就是用這個載入器來翻譯指定的檔案的。
使用npm安裝babel-loader。
npm install babel-loader babel-preset-es2015 babel-preset-react --save-dev
babel-preset-es2015和babel-preset-react是babel-loader
使用的外掛。專門用來翻譯JSX和ES2015語法。安裝之後還需要配置一下才能使用。
建立一個.babelrc的檔案,並新增一下內容。
touch .babelrc
{
"presets": ["es2015", "react"]
}
下一步就是告訴webpack使用babel-loader
來打包檔案。
開啟webpack.config.js並新增如下內容。
var webpack = require(`webpack`);
var path = require(`path`);
var BUILD_DIR = path.resolve(__dirname, `src/client/public`);
var APP_DIR = path.resolve(__dirname, `src/client/app`);
var config = {
entry: APP_DIR + `/index.jsx`,
output: {
path: BUILD_DIR,
filename: `bundle.js`
},
module: {
rules: [
{
test: /.jsx$/,
use: [
`babel-loader`,
],
include: [
// path.resolve(__dirname, "app")
APP_DIR
],
},
};
module.exports = config;
loaders
屬性對應的值是一個陣列。不過我們只是用babel-loader
。每一個載入器都需要通過test
屬性指定可以處理的檔案的字尾。我們的babel-loader
用來處理.js和.jsx檔案。include
屬性指定處理哪個目錄下的檔案。loader
屬性就是載入器的名稱。
現在環境配置就都完成了。下面寫幾行程式碼體驗一下。
Hello React
使用npm安裝react和react-dom。
npm install react react-dom --save
把index.jsx檔案裡的console.log(...)
替換成下面的程式碼。
import React from `react`;
import {render} from `react-dom`;
class App extends React.Component {
render() {
return <p> Yo, React </p>
}
}
render(<App />, document.getElementById(`app`));
執行我們上面說的命令。
./node_modules/.bin/webpack -d
現在你就可以在瀏覽器裡看到Yo React了。
更進一步
讓webpack監視檔案變化
每次修改了檔案之後還要停止-啟動一次webpack的命令實在是太麻煩了。我們可以簡單的修改一下命令。
./node_modules/.bin/webpack -d --watch
現在webpack就在監視模式下執行了,每次檔案修改發生之後都會自動打包。要看到實際效果,可以把Yo React修改成任何其他的字串。之後在瀏覽器裡重新整理一下就會看到結果。
如果你連重新整理瀏覽器都懶得可以使用react-hot-loader。
使用npm執行
命令./node_modules/.bin/webpack
可以簡化一下。
在packages.json檔案裡修改。
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"dev": "webpack -d --watch",
"build": "webpack -p"
},
現在使用命令npm run build
就可以讓webpack在產品模式下執行了。在這個模式下會自動壓縮打包好的檔案。命令npm run dev
會在監視模式下執行webpack。
新增一些檔案
在示例中,我們只有一個叫做App
的元件。我們來新增更多元件。
建立一個新的檔案叫做AwesomeComponent.jsx,並新增如下程式碼。
import React from `react`;
class AwesomeComponent extends React.Component {
constructor(props) {
super(props);
this.state = {likesCount: 0};
this.onLike = this.onLike.bind(this);
}
onLike() {
let newLikesCount = this.state.likesCount + 1;
this.setState({likesCount: newLikesCount});
}
render() {
return (
<div>
Likes: <span>{this.state.likesCount}</span>
<div><button onClick={this.onLike}>Like Me</button></div>
</div>
);
}
}
export default AwesomeComponent;
在index.jsx檔案中引入。
import React from `react`;
import {render} from `react-dom`;
import AwesomeComponent from `./AwesomeComponent.js`;
class App extends React.Component {
render() {
return (
<div>
<p> Yo, React </p>
<AwesomeComponent />
</div>
)
}
}
render(<App />, document.getElementById(`app`));
如果webpack已經執行在監視模式下了,那麼直接重新整理一下瀏覽器就可以看到AwesomeComponent
的執行結果了。
總結
本文可以用來指導你配置React的開發環境。