mirror of
https://github.com/Febbweiss/springboot-react-webpack.git
synced 2026-03-04 22:25:34 +00:00
Prepare ES6 migration
This commit is contained in:
14
package.json
14
package.json
@@ -2,7 +2,7 @@
|
|||||||
"name": "springboot-react-webpack-demo",
|
"name": "springboot-react-webpack-demo",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap": "^3.3.6",
|
"bootstrap": "^3.3.6",
|
||||||
"jquery": "^2.2.2",
|
"jquery": "^2.2.2",
|
||||||
"marked": "^0.3.5",
|
"marked": "^0.3.5",
|
||||||
"react": "^0.14.7",
|
"react": "^0.14.7",
|
||||||
@@ -10,10 +10,15 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "^6.7.4",
|
"babel-core": "^6.7.4",
|
||||||
|
"babel-eslint": "^6.0.2",
|
||||||
"babel-loader": "^6.2.4",
|
"babel-loader": "^6.2.4",
|
||||||
"babel-preset-es2015": "^6.6.0",
|
"babel-preset-es2015": "^6.6.0",
|
||||||
"babel-preset-react": "^6.5.0",
|
"babel-preset-react": "^6.5.0",
|
||||||
"css-loader": "^0.23.1",
|
"css-loader": "^0.23.1",
|
||||||
|
"eslint": "^2.5.3",
|
||||||
|
"eslint-config-airbnb": "^6.2.0",
|
||||||
|
"eslint-loader": "^1.3.0",
|
||||||
|
"eslint-plugin-react": "^4.2.3",
|
||||||
"extract-text-webpack-plugin": "^1.0.1",
|
"extract-text-webpack-plugin": "^1.0.1",
|
||||||
"file-loader": "^0.8.5",
|
"file-loader": "^0.8.5",
|
||||||
"html-loader": "^0.4.3",
|
"html-loader": "^0.4.3",
|
||||||
@@ -27,8 +32,9 @@
|
|||||||
"webpack-dev-server": "^1.14.1"
|
"webpack-dev-server": "^1.14.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "NODE_ENV=development webpack-dev-server --hot --inline",
|
"dev-build": "NODE_ENV=development webpack --d --progress --colors",
|
||||||
"dev-build": "NODE_ENV=development webpack --d --progress --colors",
|
"lint": "eslint --ignore-pattern **/nashorn-*.js --ext .js,.jsx src/main/resources/static/js/**",
|
||||||
"prod-build": "webpack -d -p --colors"
|
"prod-build": "webpack -d -p --colors",
|
||||||
|
"watch": "NODE_ENV=development webpack-dev-server --hot --inline"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var React = require('react'),
|
|
||||||
marked = require('marked'),
|
|
||||||
$ = require('jquery');
|
|
||||||
|
|
||||||
var Comment = React.createClass({
|
|
||||||
rawMarkup: function() {
|
|
||||||
var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
|
|
||||||
return { __html: rawMarkup };
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
return (
|
|
||||||
<div className="comment">
|
|
||||||
<h2 className="commentAuthor">
|
|
||||||
{this.props.author}
|
|
||||||
</h2>
|
|
||||||
<span dangerouslySetInnerHTML={this.rawMarkup()} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var CommentForm = React.createClass({
|
|
||||||
getInitialState: function() {
|
|
||||||
return {author: '', text: ''};
|
|
||||||
},
|
|
||||||
handleAuthorChange: function(e) {
|
|
||||||
this.setState({author: e.target.value});
|
|
||||||
},
|
|
||||||
handleTextChange: function(e) {
|
|
||||||
this.setState({text: e.target.value});
|
|
||||||
},
|
|
||||||
handleSubmit: function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var author = this.state.author.trim();
|
|
||||||
var text = this.state.text.trim();
|
|
||||||
if( !text || !author ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.props.onCommentSubmit({author: author, text: text})
|
|
||||||
this.setState({author: '', text: ''});
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
return (
|
|
||||||
<form className="commentForm" onSubmit={this.handleSubmit}>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Your name"
|
|
||||||
value={this.state.author}
|
|
||||||
onChange={this.handleAuthorChange}
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Say something..."
|
|
||||||
value={this.state.text}
|
|
||||||
onChange={this.handleTextChange}
|
|
||||||
/>
|
|
||||||
<input type="submit" value="Post" />
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var CommentBox = React.createClass({
|
|
||||||
getInitialState: function() {
|
|
||||||
return {data: this.props.data || []};
|
|
||||||
},
|
|
||||||
loadCommentsFromServer: function() {
|
|
||||||
$.ajax({
|
|
||||||
url: this.props.url,
|
|
||||||
dataType: 'json',
|
|
||||||
cache: false,
|
|
||||||
success: function(data) {
|
|
||||||
this.setState({data: data});
|
|
||||||
}.bind(this),
|
|
||||||
error: function(xhr, status, err) {
|
|
||||||
console.error(this.props.url, status, err.toString());
|
|
||||||
}.bind(this)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleCommentSubmit: function(comment) {
|
|
||||||
var comments = this.state.data;
|
|
||||||
comment.id = Date.now();
|
|
||||||
var newComments = comments.concat([comment]);
|
|
||||||
this.setState({data: newComments});
|
|
||||||
$.ajax({
|
|
||||||
url: this.props.url,
|
|
||||||
method: 'POST',
|
|
||||||
dataType: 'json',
|
|
||||||
data: comment,
|
|
||||||
success: function(data) {
|
|
||||||
this.setState({data: data});
|
|
||||||
}.bind(this),
|
|
||||||
error: function(xhr, status, err) {
|
|
||||||
this.setState({data: comments});
|
|
||||||
console.error(this.props.url, status, err.toString());
|
|
||||||
}.bind(this)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
this.loadCommentsFromServer();
|
|
||||||
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
return (
|
|
||||||
<div className="commentBox">
|
|
||||||
<h1>Comments</h1>
|
|
||||||
<CommentList data={this.state.data}/>
|
|
||||||
<CommentForm onCommentSubmit={this.handleCommentSubmit}/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var CommentList = React.createClass({
|
|
||||||
render: function() {
|
|
||||||
var commentNodes = this.props.data.map( function(comment) {
|
|
||||||
return (
|
|
||||||
<Comment author={comment.author} key={comment.id}>{comment.text}</Comment>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<div className="commentList">
|
|
||||||
{commentNodes}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
CommentBox: CommentBox,
|
|
||||||
CommentList: CommentList,
|
|
||||||
CommentForm: CommentForm,
|
|
||||||
Comment: Comment
|
|
||||||
};
|
|
||||||
@@ -1,32 +1,27 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import ReactDOMServer from 'react-dom/server';
|
import ReactDOMServer from 'react-dom/server';
|
||||||
import App from './app.jsx';
|
import CommentBox from './comment_box.jsx';
|
||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
|
import 'bootstrap/dist/css/bootstrap.css';
|
||||||
|
import '../css/comments.css';
|
||||||
|
import '../css/comments.less';
|
||||||
|
|
||||||
require('bootstrap/dist/css/bootstrap.css');
|
global.renderClient = function renderClient(comments) {
|
||||||
require('../css/comments.css');
|
const data = comments || [];
|
||||||
require('../css/comments.less');
|
ReactDOM.render(
|
||||||
|
<CommentBox data={data} url="/api/comments" pollInterval={2000} />,
|
||||||
global.renderClient = function (comments) {
|
document.getElementById('content')
|
||||||
var data = comments || [];
|
);
|
||||||
ReactDOM.render(
|
|
||||||
<App.CommentBox data={data} url="/api/comments" pollInterval={2000}/>,
|
|
||||||
document.getElementById('content')
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
global.renderServer = function (comments) {
|
global.renderServer = function renderServer(comments) {
|
||||||
var data = Java.from(comments);
|
const data = Java.from(comments);
|
||||||
return ReactDOMServer.renderToString(
|
return ReactDOMServer.renderToString(
|
||||||
<App.CommentBox data={data} url="/api/comments" pollInterval={2000} />
|
<CommentBox data={data} url="/api/comments" pollInterval={2000} />
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if( !global.nashorn ) {
|
if (!global.nashorn) {
|
||||||
renderClient(initialData);
|
global.renderClient(global.initialData);
|
||||||
};
|
}
|
||||||
|
|||||||
23
src/main/resources/static/js/comment.jsx
Normal file
23
src/main/resources/static/js/comment.jsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import marked from 'marked';
|
||||||
|
|
||||||
|
class Comment extends React.Component {
|
||||||
|
rawMarkup() {
|
||||||
|
const rawMarkup = marked(this.props.children.toString(), { sanitize: true });
|
||||||
|
return { __html: rawMarkup };
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="comment">
|
||||||
|
<h2 className="commentAuthor">
|
||||||
|
{this.props.author}
|
||||||
|
</h2>
|
||||||
|
<span dangerouslySetInnerHTML={this.rawMarkup()} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Comment.propTypes = {
|
||||||
|
author: React.PropTypes.string,
|
||||||
|
children: React.PropTypes.node,
|
||||||
|
};
|
||||||
65
src/main/resources/static/js/comment_box.jsx
Normal file
65
src/main/resources/static/js/comment_box.jsx
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import $ from 'jquery';
|
||||||
|
import CommentForm from './comment_form.jsx';
|
||||||
|
import CommentList from './comment_list.jsx';
|
||||||
|
|
||||||
|
class CommentBox extends React.Component {
|
||||||
|
componentDidMount() {
|
||||||
|
this.loadCommentsFromServer();
|
||||||
|
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
|
||||||
|
}
|
||||||
|
getInitialStatefunction() {
|
||||||
|
return { data: this.props.data || [] };
|
||||||
|
}
|
||||||
|
loadCommentsFromServer() {
|
||||||
|
$.ajax({
|
||||||
|
url: this.props.url,
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
success: function success(data) {
|
||||||
|
this.setState({ data });
|
||||||
|
}.bind(this),
|
||||||
|
error: function error(xhr, status, err) {
|
||||||
|
console.error(this.props.url, status, err.toString());
|
||||||
|
}.bind(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
handleCommentSubmit(comment) {
|
||||||
|
const comments = this.state.data;
|
||||||
|
const copy = comment;
|
||||||
|
copy.id = Date.now();
|
||||||
|
const newComments = comments.concat([copy]);
|
||||||
|
this.setState({ data: newComments });
|
||||||
|
$.ajax({
|
||||||
|
url: this.props.url,
|
||||||
|
method: 'POST',
|
||||||
|
dataType: 'json',
|
||||||
|
data: comment,
|
||||||
|
success: function success(data) {
|
||||||
|
this.setState({ data });
|
||||||
|
}.bind(this),
|
||||||
|
error: function error(xhr, status, err) {
|
||||||
|
this.setState({ data: comments });
|
||||||
|
console.error(this.props.url, status, err.toString());
|
||||||
|
}.bind(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="commentBox">
|
||||||
|
<h1>Comments</h1>
|
||||||
|
<CommentList data={this.state.data} />
|
||||||
|
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CommentBox.propTypes = {
|
||||||
|
data: React.PropTypes.shape({
|
||||||
|
id: React.PropTypes.number,
|
||||||
|
author: React.PropTypes.string,
|
||||||
|
text: React.PropTypes.string,
|
||||||
|
}),
|
||||||
|
pollInterval: React.PropTypes.numbe,
|
||||||
|
url: React.PropTypes.string,
|
||||||
|
};
|
||||||
47
src/main/resources/static/js/comment_form.jsx
Normal file
47
src/main/resources/static/js/comment_form.jsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
class CommentForm extends React.Component {
|
||||||
|
getInitialState() {
|
||||||
|
return { 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={this.handleSubmit}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Your name"
|
||||||
|
value={this.state.author}
|
||||||
|
onChange={this.handleAuthorChange}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Say something..."
|
||||||
|
value={this.state.text}
|
||||||
|
onChange={this.handleTextChange}
|
||||||
|
/>
|
||||||
|
<input type="submit" value="Post" />
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CommentForm.propTypes = {
|
||||||
|
author: React.PropTypes.string,
|
||||||
|
text: React.PropTypes.string,
|
||||||
|
onCommentSubmit: React.PropTypes.func,
|
||||||
|
};
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
"use strict";
|
import 'react';
|
||||||
|
import 'react-dom';
|
||||||
|
import 'jquery';
|
||||||
|
|
||||||
require('react');
|
import 'bootstrap/dist/css/bootstrap.css';
|
||||||
require('react-dom');
|
|
||||||
require('jquery');
|
|
||||||
|
|
||||||
require('bootstrap/dist/css/bootstrap.css');
|
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ var config = {
|
|||||||
publicPath: 'http://localhost:' + dev_port + '/'
|
publicPath: 'http://localhost:' + dev_port + '/'
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
|
preLoaders: [
|
||||||
|
{
|
||||||
|
test: /\.jsx$|\.js$/,
|
||||||
|
loader: 'eslint-loader',
|
||||||
|
include: __dirname + '/src/main/resources/static/js'
|
||||||
|
}
|
||||||
|
],
|
||||||
loaders: [
|
loaders: [
|
||||||
{
|
{
|
||||||
test: /\.jsx?$/,
|
test: /\.jsx?$/,
|
||||||
@@ -83,7 +90,7 @@ var config = {
|
|||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
htmlLoader: {
|
htmlLoader: {
|
||||||
removeAttributeQuotes: false,
|
removeAttributeQuotes: false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user