畢業入職公司後開始搞React,從剛開始只會簡單的setState,到後面webpack複雜的配置,Redux,Server Render,都一一上手。期間遇到不少問題,踩過不少坑,最近想以blog的方式把本身開發React同構應用的歷程記錄下來,一方面能夠和你們分享下使用React的經驗,另外一方面也算是對本身一年來工做的小總結。javascript
webpack配置java
babel-loader
的配置node
在瀏覽器環境中使用async
函數react
這邊文章的Demo我已經上傳至Githubwebpack
npm install webpack -D
git
這裏要說明的一點是,webpack通常是全局安裝,不過接下來的項目採用npm
命令來編譯配置,npm run command
執行時會自動添加node_modules/.bin
目錄至PATH
環境變量,所以不用擔憂找不到命令。es6
先建立一個最簡單的webpack配置文件。github
const path = require('path'); //入口文件 let entry = { index: './module/index/Index_entry.js' }; //瀏覽器端的配置 let browserConfig = { entry, output: { path: path.join(__dirname, 'build'), publicPath: '/build', filename: "js/[name].bundle.js", chunkFilename: "js/[id].bundle.js" }, module: { loaders: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: `babel`, } ] } }; module.exports = [browserConfig];
這裏我將entry
和browserConfig
獨立開來,module.exports
導出的是一個數組,這是爲了方便後面server render
的配置。web
更詳細的配置說明,能夠參照webapck的官方文檔,這裏就不一一說明了。npm
babel
能作什麼通常我在開發React app的工做中有三個需求
將JSX轉換成ES5語法
將ES7轉換成ES5語法
啓用async函數的支持
babel-loader
先安裝babel-core
和babel-loader
。
npm install --save-dev babel-loader babel-core
在我剛剛學習webpack
的時候,天真的覺得裝完這兩個包,就能夠轉碼JSX了,結果就是一直報錯,提示說不識別JSX語法。。。弄的我疑惑了好久。。。後來才知道,裝完上面兩個包以後,還須要進一步的配置(presets)
,好比指定babel將當前的es7
的代碼轉換到 es2015
的代碼,將JSX語法 <Component/>
轉換成React.createElement(Component)
等等。
.babelrc
babel官方預先設定了6個經常使用的presets,咱們日常須要的是babel-preset-es2015
和babel-preset-react
。
npm install --save-dev babel-preset-es2015 babel-preset-react
在項目根目錄建立.babelrc
。固然這裏也能夠在webpack.config.js
中的loaders
配置。不過我的以爲在.babelrc
中配置會更清晰一些。
{ "presets": [ "react", "es2015" ] }
這樣前兩個需求就能夠完美解決了,哈哈。
async
函數regenerator
函數讓咱們有把異步的函數寫成同步的能力,使得代碼的可維護性和可閱讀性大大提升,而async
則是regenerator
的語法糖,通常來講regenerator
函數的執行是須要co
做爲其執行器的,而async
函數不用,所以使用起來更加方便優雅。關於async
函數的知識能夠參考阮一峯大神的書籍ECMAScript 6 入門。
若是如今用上面的配置,直接使用regenerator
函數的話,會報regeneratorRuntime is not defined
錯誤,這個錯誤以前也是困擾過我,後面才知道,regenerator
沒法直接被編譯成es5的代碼。必須添加polyfill,即regenerator
的runtime庫才能運行。
先安裝對應的babel plugin
,這個插件默認會幫咱們把async
函數轉換成regenerator
函數。
npm install babel-plugin-transform-regenerator
代碼轉換好了後,代碼運行時還要一個包 regenerator-runtime/runtime
。
npm i regenerator-runtime -S
而後在用到async
函數的文件頭部添加
import 'regenerator-runtime/runtime';
好比在Index.jsx
中
import React from 'react'; import 'regenerator-runtime/runtime'; export default class extends React.Component { constructor() { super(); this.state = { pageData: 'loading' } } getAsyncData() { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ code: 200, msg: 'success', data: 'hello!' }) }, 2000) }); } async componentDidMount() { let data = await this.getAsyncData(); this.setState({ pageData: data.data }) } render() { return ( <div> data: {this.state.pageData} </div> ) } }
將.babelrc
修改爲以下所示
{ "presets": [ "react", "es2015" ], "plugins": [ "transform-regenerator" ] }
至此,babel能夠完美解決咱們上面提出的3個需求啦。讓咱們能夠先編譯試試。
如今package.json
中添加
"scripts": { "watch": "webpack -d -w --progress --colors" },
執行
npm run watch
ok,編譯成功
推薦使用anywhere
,詳細配置在這
npm i anywhere -g
添加npm script
"scripts": { "watch": "webpack -d -w --progress --colors", "test-server": "anywhere -s -p 8000 -d ./build" },
咱們啓動HTTP服務器
npm run test-server
打開http://127.0.0.1:8000/
,正常的話以下圖所示
你們想親自嘗試的能夠fork一份代碼研究,哈哈。
第一次寫文章,你們多多包涵,有什麼錯誤儘管指出來,^_^。