从零开始搭建React同构应用(一)
前言
毕业入职公司后开始搞React,从刚开始只会简单的setState,到后面webpack复杂的配置,Redux,Server Render,都一一上手。期间遇到很多问题,踩过很多坑,最近想以blog的方式把自己开发React同构应用的历程记录下来,一方面可以和大家分享下使用React的经验,另一方面也算是对自己一年来工作的小总结。
主要内容
webpack配置
babel-loader 的配置
在浏览器环境中使用async 函数
代码
这边文章的Demo我已经上传至Github
安装webpack
npm install webpack -D
这里要说明的一点是,webpack一般是全局安装,不过接下来的项目采用npm 命令来编译配置,npm run command 执行时会自动添加node_modules/.bin 目录至PATH 环境变量,因此不用担心找不到命令。
配置webpack.config.js
先创建一个最简单的webpack配置文件。
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 的配置。
更详细的配置说明,可以参照webapck的官方文档,这里就不一一说明了。
babel的配置
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一份代码研究,哈哈。
第一次写文章,大家多多包涵,有什么错误尽管指出来,^_^。 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|