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的開發環境。