從零開始,搭建基於webpack的react開發環境
利用react可以有效進行元件的開發與管理。其中webpack作為構建react元件的有效工具,可以大大提高我們的開發效率與使用效果。因此,網上也有了很多介紹文章。
但是,由於react與webpack版本的迭代導致在學習這些入門介紹教程時,或因存在版本問題,或因存在api變動,或因內容含糊而導致遇到很多坑。
因此,記錄了一下前段時間一次搭建過程,介紹如何基於webpack搭建一個最簡單的react開發環境。
準備
配置sublime
選擇一個合適開發工具非常重要。前端開發可以使用的工具非常多,本文使用的是sublime。使用其他工具可以跳過這一部分。
用sublime開發最好先安裝一些外掛,以便於支援es6語法與jsx語法,同時也能在jsx裡提供emmet的功能。
外掛推薦與安裝可以檢視
安裝node.js
node是基於高效能的 chrome V8 JavaScript引擎,將JavaScript的觸角拓展到了伺服器端。由於webpack的使用需要node環境,所以正式使用webpack與react進行開發之前,首先需要安裝node.js。
Node.js 是一個基於 Chrome V8 引擎的 JavaScript 執行環境。Node.js 使用了一個事件驅動、非阻塞式 I/O 的模型,使其輕量又高效。Node.js 的包管理器 npm,是全球最大的開源庫生態系統。
node支援window、mac、linux等平臺。我們可以進入node官網,下載與安裝所需要的node版本(本文使用的版本v6.5.0)。
安裝完畢後,輸入
node -v
可以測試安裝是否成功。
專案初始化
建立專案。專案的目錄結構如下:
- app
- components
- title.jsx
- clock.jsx
- entry.js
- components
- build
- index.html
- bundle.js(自動生成)
在當前專案根目錄下執行命令列,初始化專案,自動生成package.json檔案
npm init
檔案如下
{
"name": "alien-test",
"version": "1.0.0",
"description": "test for react",
"main": "index.js" ,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"react",
"test"
],
"author": "alienzhou",
"license": "ISC"
}
webpack配置
這一部分,會介紹如何使用webpack打包,包括監聽變化自動重新整理。
簡單的打包
首先,我們先做一個最簡單的打包例項,來理解webpack的工作方式。
npm install webpack --save-dev
安裝成功後在專案的node_modules(包模組)資料夾中可以看到剛下載的包。並且在pakage.json中添加了開發環境下的依賴:
"devDependencies": {
"webpack": "^1.13.2"
}
在專案根目錄建立一個webpack.config.js,該檔案是webpack的配置檔案,會指導webpack的打包動作。檔案如下
var path = require('path');
var config = {
entry: path.resolve('d:/project/react/test', 'app/entry.js'),
output: {
path: path.resolve('d:/project/react/test', 'build'),
filename: 'bundle.js',
}
}
module.exports = config;
可以看到,檔案中entry指定了一個檔案入口,webpack會讀取該檔案,輸出到output所指定的路徑內,生成bundle.js。而我們的index.html中需要引用打包檔案bundle.js
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>
我們現在已經有了html檔案,還需要一個入口檔案entry.js
var title = require('components/test.js');
document.body.appendChild(title());
以及一個元件檔案test.js
module.exports = function() {
var title = document.creatElement('h1');
title.text('HI, I\'m AlienZHOU');
return title;
}
需要為package.json的scripts部分新增一個新的指令build
,用以打包構建應用。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
}
這樣就可以使用指令代替node_modules/.bin/webpack
命令
npm run build
執行完畢,可以發現在build資料夾下生成了bundle.js檔案。直接在瀏覽器執行index.html就可以看到效果。
瀏覽器自動重新整理
監聽檔案變化,自動重新整理瀏覽器是非常有用的功能,使用webpack也可以非常方便實現。
webpack-dev-server是一個輕量級的node express伺服器,詳細介紹可以看官網相關介紹。
The webpack-dev-server is a little Node.js Express server, which uses the webpack-dev-middleware to serve a webpack bundle.
首先,安裝webpack-dev-server。
npm install webpack-dev-server --save-dev
在package.json中修改scripts,新增dev
指令內容,結果如下
{
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build"
}
}
這樣,啟動應用後,每次修改完檔案內容,就會自動打包生成新的bundle.js檔案。然而,現在還是不能實現瀏覽器的自動重新整理,所以還需要最後一個配置修改:在入口處新增一個入口點,實現瀏覽器自動重新整理。
entry: [
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080',
path.resolve('d:/project/react/test', 'app/entry.js')
]
現在,執行指令npm run dev
,在瀏覽器中輸入localhost:8080
,修改程式碼,可以看到瀏覽器會自動重新整理顯示最新的編譯結果。
react+es6
通過上一部分的介紹,應該已經瞭解了webpack的基本用法與邏輯。該部分使用es6結合webpack來構建一個react時鐘元件。關於這一部分,網上也有許多教程與例項,本文在行文中也會指出由於一些版本問題在較早期的文章中所存在的坑。
使用jsx-loader
使用jsx-loader對jsx檔案進行處理
npm install jsx-loader --save-dev
在webpack.config.js的module部分中新增新的loader處理器
module: {
loaders: [{
test: /\.jsx$/,
loader: 'jsx-loader?harmony'
}]
}
使用babel
安裝babel
npm install babel --save-dev
為babel新增配置檔案。在專案根目錄下新建檔案.babelrc,新增轉碼規則,檔案內容如下
{
"presets": ['es2015','react'],
"plugins": []
}
安裝es2015轉碼器
npm install babel-preset-es2015 --save-dev
安裝react轉碼器
npm install babel-preset-react --save-dev
需要stage-0語法
npm install babel-preset-stage-0 --save-dev
原因:使用es6來編寫react元件與es5中的語法有多處不同,其中非常重要的一部分就是,使用靜態變數來作為元件的預設屬性(defaultProps)。此處使用stage-0階段語法,是為了使用類中的靜態變數語法,這種行為(the direct export of an ES6 class with a static property)如果只是用es2015轉碼器則會導致報錯,在stackoverflow上有專門針對其的問題討論:
“ On GitHub I got told this is a stage-1 feature, namely transform-class-properties. So I would like to implement stage-0 right away”
ERROR in ./app/components/form/index.jsx
Module build failed: SyntaxError: /Library/WebServer/Documents/yarsk.test/app/components/form/index.jsx: Unexpected token (19:19)
17 | // ES6 React Component:
18 | export default class SurveyForm extends Component {
> 19 | static propTypes = {
| ^
安裝babel-loader
npm install babel-loader --save-dev
在webpack.config.js檔案中新增新的loader(注意,需要放在jsx-loader後面)
module: {
loaders: [{
test: /\.jsx$/,
loader: 'jsx-loader?harmony'
}, {
test: /\.js|jsx$/,
loaders: ['babel?presets[]=es2015,presets[]=react']
}, ]
}
需要注意的地方——部分文章配置如上,但由於babel最近的調整,將一些API從babel庫移至了babel-core庫。所以,需要安裝babel-core,否則會報錯。
react
安裝react與react-dom
npm install react --save-dev
npm install react-dom --save-dev
元件檔案components/hello.jsx
import React from 'react';
export default class Hello extends React.Component{
render() {
return <div><h1>hi alienzhou!</h1><h2>yoyoyo1</h2></div>;
}
}
入口檔案entry.js
import React from 'react';
import ReactDOM from 'react-dom';
import Hello from './components/hello.jsx';
main();
function main() {
ReactDOM.render(<Hello /> , document.getElementById('app'));
}
需要注意的地方——之前的文章使用React.render()方法。但是react從0.14版本之後被分成了react和react-dom兩個部分。createElement、createClass、Component、PropTypes、children等實在React下。而render、unmountComponentAtNode、findDOMNode則放在了ReactDOM。
因此,之前的某些教程中的React.render(<Hello />,document.getElementById('app'));
使用修改為ReactDOM.render(<Hello />,document.getElementById('app'));