毕业入职公司后开始搞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一份代码研究,哈哈。
第一次写文章,你们多多包涵,有什么错误尽管指出来,^_^。