Part 1: Rewrite Facebook Tutorial using Babel 6, ES6 and Webpack
This is the first part of the series, you can also check the Part 2: Server Rendering a ES6 React.js App Using Ruby on Rails
Facebook have a very good tutorial on how to use React.js to build a comment system which you can post comment to the server, live update the comment list and retrieve comments from server using Ajax.
In this serials, we will first modify the tutorial a little bit, rewrite the sample use ES6, compile use Babel and Webpack in part 1, and then in part 2 we will pre-render the content in a Ruby on Rails app, and add caching to speed up the performance.
Prerequisites
You need to understand React.js a little bit, and went through Facebook official React.js tutorial first. This tutorial is on top of the original tutorial.
To get started, you need to make sure you have installed same node version. Using different versions might have different results which are hard to debug.
Install nvm
Install nvm
for node version manager. nvm
is a tool similar to rvm
, which helps to easily install multiple versions of node.
$ brew install nvm
Install node version 5.3.0
As the time of writing, version 5.3.0
is the latest stable node version available in nvm
, you can check all node versions using nvm ls-remote
.
$ nvm install 5.3.0
make sure your node version is correct by run
$ node -v
You should see correct
If your node version is something different, you might need to remove node or change path priority. brew uninstall node
.
Getting Started
1. Create project folder and package.json
Create a new folder for the demo, cd to the folder and run
$ npm init
You can leave everything as default for now.
2. Install dependencies
Install Webpack
$ npm install webpack webpack-dev-server --save-dev
Install babel
$ npm install babel-core babel-preset-react babel-preset-es2015 babel-loader --save-dev
Install eslint
$ npm install eslint eslint-config-airbnb --save-dev
Install React and other libraries used in the project
$ npm install react react-dom marked --save
3. Add configs
1. Add .nvmrc
It is good to make sure other people who came to this project also use the same node version as you. You can add a new file to the root.
5.3.0
New comer will just need to run nvm use
to switch to the version the project needs.
2. Add .babelrc
{
"presets": ["es2015", "react"]
}
3. Add .eslintrc.json
{
"extends": "airbnb",
"plugins": [
"react"
]
}
4. Add .eslintignore
node_modules/**
5. Add webpack.config.js
module.exports = {
entry: './App.js',
output: {
filename: 'bundle.js',
},
module: {
loaders: [
{ test: /\.jsx?$/, loader: 'babel', exclude: /node_modules/ },
],
},
resolve: {
extensions: ['', '.jsx', '.js'],
},
};
4. Add React files
Comment.js
import React, { Component, PropTypes } from 'react';
import marked from 'marked';
class Comment extends Component {
rawMarkup() {
return {
__html: marked(this.props.children.toString(), { sanitize: true }),
};
}
render() {
return (
<div className="comment">
<h2 className="commentAuthor">
{this.props.author}
</h2>
<span dangerouslySetInnerHTML={this.rawMarkup()} />
</div>
);
}
}
Comment.propTypes = {
children: PropTypes.node.isRequired,
author: PropTypes.string.isRequired,
};
export default Comment;
CommentList.js
import React from 'react';
import Comment from './Comment';
export default ({ data }) => (
<div className="commentList">
{data.map(comment =>
<Comment author={comment.author} key={comment.id}>
{comment.text}
</Comment>
)}
</div>
);
CommentForm.js
import React, { Component, PropTypes } from 'react';
class CommentForm extends Component {
constructor(props) {
super(props);
this.state = { author: '', text: '' };
}
handleAuthorChange(e) {
this.setState({ author: e.target.value });
}
handleTextChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
const author = this.state.author.trim();
const text = this.state.text.trim();
if (!text || !author) {
return;
}
this.props.onCommentSubmit({ author, text });
this.setState({ author: '', text: '' });
}
render() {
return (
<form className="commentForm" onSubmit={(e) => this.handleSubmit(e)}>
<input
type="text"
placeholder="Your name"
value={this.state.author}
onChange={(e) => this.handleAuthorChange(e)}
/>
<input
type="text"
placeholder="Say something..."
value={this.state.text}
onChange={(e) => this.handleTextChange(e)}
/>
<input type="submit" value="Post" />
</form>
);
}
}
CommentForm.propTypes = {
onCommentSubmit: PropTypes.func.isRequired,
};
export default CommentForm;
CommentBox.js
import React, { Component, PropTypes } from 'react';
import CommentList from './CommentList';
import CommentForm from './CommentForm';
class CommentBox extends Component {
constructor(props) {
super(props);
this.state = { data: props.data || [] };
}
handleCommentSubmit(comment) {
const comments = this.state.data;
const newComments = comments.concat([comment]);
comment.id = Date.now();
this.setState({ data: newComments });
// TODO: send to API
}
render() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={(comment) => this.handleCommentSubmit(comment)} />
</div>
);
}
}
CommentBox.propTypes = {
data: PropTypes.array,
};
export default CommentBox;
5. Add index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>React Tutorial</title>
</head>
<body>
<div id="content"></div>
<script src="bundle.js"></script>
</body>
</html>
6. Update package.json
scripts
"scripts": {
"eslint": "./node_modules/.bin/eslint .; exit 0",
"start": "./node_modules/.bin/webpack-dev-server"
},
You can run npm run eslint
to check your code syntax using Airbnb Javascript best practice.
You might see errors above which helps you to fix any potential Javascript errors.
7. Run in localhost
Now run
$ npm start
You should see something like this in your terminal
Now open your browser and go to localhost:8080
and you should see something like this
Try to post a new comment, it should update the comments automatically. If everything is working fine, we can move to Part 2: Server Rendering a ES6 React.js App Using Ruby on Rails.
You can check the full source codes in Github.
Other resources:
- Webpack: Pete Hunt's webpack-howto
- ES6:
- Babel's Learn ES-2015
- ES6 features