Webpact打包React后端Node+Express
前言
React官方推荐用Browserify或者Webpack 来开发React组件。
Webpack 是什么?是德国开发者 Tobias Koppers 开发的模块加载器。Instagram 工程师认为这个方案很棒, 似乎还把作者招过去了。在 Webpack 当中, 所有的资源都被当作是模块, js, css, 图片等等..Webpack 都有对应的模块 loader,如下文中将用到jsx-loader来加载带react语法的js文件
Express 是目前最流行的 Node.js Web MVC开发框架,最受 Web 开发人员欢迎。使用其强大的功能,开发人员可以创建单页和多页,和混合模式的 Web 应用程序。本实例用Json数组模拟实现数据model模块,在Express框架下实现Restful API
[1]后端
一、安装及配置环境[window环境]
1、打开命令行,安装监听代码变更可自动重启node服务器的supervisor
npm install -g supervisor
在开发nodejs程序,调试的时候,无论你修改了代码的哪一部分,都需要重启服务才能生效。Node.js的这种设计虽然有利于提高性能,却不利于开发调试,因为我们在开发过程中总是希望修改后立即看到效果,而不是每次都要终止进程并重启。supervisor 可以帮助你实现这个功能,它会监视你对代码的改动,并自动重启 Node.js。
2、命令行全局安装Nodejs MVC框架express。
注意:如果运行有问题可以加上版本号安装。
npm install -g express
3、使用Express创建项目
cd E: elson estexpress express -t ejs commentbox cd commentbox npm intall
如上:命令行下先定位到自己的目录E: elson estexpress ,再输入express -t ejs commentbox创建项目,此时,会自动生成一个commentbox文件夹。文件夹里面面会有model、public、routes和views文件夹,还有app.js和package.json两个文件。再命令行cd commentbox定位到commentbox文件夹下,然后输入npm install(这是必需的),此时,目录下会多出node_modules文件夹,这是node模块文件夹。
二、编写代码
1、添加model文件E: elson estexpresscommentboxmodelcomments.js
exports.comments = [ { author : '小明', text : "Nothing is impossible, the word itself says 'I'm possible'!"}, { author : '小强', text : "You may not realize it when it happens, but a kick in the teeth may be the best thing in the world for you"}, { author : '小兵', text : "Even the greatest was once a beginner. Don't be afraid to take that first step."}, { author : '拉登', text : "You are afraid to die, and you're afraid to live. What a way to exist."} ];
用json数组模拟后台数据,当然可以直接去连数据库,写数据库连接配好model就可以了。
2、修改应用入口文件E: elson estexpresscommentboxapp.js
/** * Module dependencies. */ var express = require('express'); var routes = require('./routes'); var comment = require('./routes/comment'); var http = require('http'); var path = require('path'); var app = express(); // all environments app.set('port', process.env.PORT || 3000); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'jade'); //app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.json()); app.use(express.urlencoded()); app.use(express.methodOverride()); app.use(express.bodyParser()); app.use(app.router); app.use(express.static(path.join(__dirname, 'public'))); // development only if ('development' == app.get('env')) { app.use(express.errorHandler()); } app.get('/', routes.index); app.get('/comments', comment.list); app.get('/comments/:id', comment.get); app.delete('/comments/:id', comment.delete); app.post('/comments', comment.add); app.put('/comments/:id', comment.update); http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); });
红色部分是自己加上去的,定义好增删改查api接口。代码书写方式遵从CommonJS规范
3、增加路由/控制器配置文件E: elson estexpresscommentbox outescomment.js
/* * GET comments listing. */ var comments = require('../model/comments').comments; exports.list = function(req, res){ res.json(comments); }; exports.get = function(req, res){ if(comments.length <= req.params.id || req.params.id < 0) { res.statusCode = 404; return res.send('Error 404: No comment found'); } var q = comments[req.params.id]; res.json(q); }; exports.delete = function(req, res){ if(comments.length <= req.params.id) { res.statusCode = 404; return res.send('Error 404: No comment found'); } comments.splice(req.params.id, 1); res.json(true); }; exports.update = function(req, res){ res.setHeader('Content-Type', 'application/json;charset=utf-8'); for(var i=0;i<comments.length;i++){ if(comments[i].author==req.body.author){ comments[i] = req.body; res.send({status:"success", message:"update comment success"}); console.log(comments); } } }; exports.add = function(req, res){ if(!req.body.hasOwnProperty('author') || !req.body.hasOwnProperty('text')) { res.statusCode = 400; return res.send('Error 400: Post syntax incorrect.'); } var newComment = { author : req.body.author, text : req.body.text }; comments.push(newComment); res.json(true); };
这里比较清晰的定义了增删改查的请求处理
4、命令行输入supervisor app.js,ok,现在打开浏览器输入localhost:3000你就可以运行并测试API接口了,也可以使用postman或者curl来测试,本例只用上了get与add请求。
supervisor app.js
浏览器打开http://localhost:3000/comments
结果如下:
[ { "author": "小明", "text": "Nothing is impossible, the word itself says 'I'm possible'!" }, { "author": "小强", "text": "You may not realize it when it happens, but a kick in the teeth may be the best thing in the world for you" }, { "author": "小兵", "text": "Even the greatest was once a beginner. Don't be afraid to take that first step." }, { "author": "拉登", "text": "You are afraid to die, and you're afraid to live. What a way to exist." } ]
浏览器打开http://localhost:3000/comments/1
结果如下:
{ "author": "小强", "text": "You may not realize it when it happens, but a kick in the teeth may be the best thing in the world for you" }
后端到此结束!
[2]前端
一、配置前端环境1、添加Webpack配置文件E: elson estexpresscommentboxwebpack.config.js
module.exports = { entry: [ './public/assets/js/entry.js' ], output: { path: __dirname + '/public/assets/', publicPath: "/public/assets/", filename: 'bundle.js' }, module: { loaders: [ { test: /.js?$/, loaders: ['jsx-loader?harmony'] } ] } };
webpack.config.js是webpack默认的配置文件。如果改了文件名要重新执行:webpack --config webpack.config.js 这样的命令,如果不改文件名就直接输入webpack就会自动打包文件。
2、命令行安装各种依赖模块。
npm install -g webpack(如果没安装wepack的话需要全局安装)
npm install --save-dev jsx-loader
npm install --save-dev react npm install --save-dev react-dom npm install --save-dev marked npm install --save-dev jquery
二、编写前端js代码
1、编写react 留言版组件:E: elson estexpresscommentboxpublicassetsjscommentbox.js
var React = require('react'); var ReactDOM = require('react-dom'); var marked = require('marked'); var $ = 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 CommentList = React.createClass({ render: function() { var commentNodes = this.props.data.map(function (comment) { return ( <Comment author={comment.author}> {comment.text} </Comment> ); }); return ( <div className="commentList"> {commentNodes} </div> ); } }); var CommentForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); var author = this.refs.author.value.trim(); var text = this.refs.text.value.trim(); if (!text || !author) { return; } this.props.onCommentSubmit({author: author, text: text}); this.refs.author.value = ''; this.refs.text.value = ''; return; }, render: function() { return ( <form className="commentForm" onSubmit={this.handleSubmit}> <input type="text" placeholder="你的名字" ref="author" /> <input type="text" placeholder="说些什么..." ref="text" /> <input type="submit" value="发表" /> </form> ); } }); var CommentBox = React.createClass({ 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) { // TODO: submit to the server and refresh the list var comments = this.state.data; var newComments = comments.concat([comment]); this.setState({data: newComments}); $.ajax({ url: this.props.url, dataType: 'json', type: 'POST', data: comment, success: function(data) { this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { console.error(this.props.url, status, err.toString()); }.bind(this) }); }, getInitialState: function() { return {data: []}; }, componentDidMount: function() { this.loadCommentsFromServer(); setInterval(this.loadCommentsFromServer, this.props.pollInterval); }, render: function() { return ( <div className="commentBox"> <h1>我的留言板</h1> <CommentList data={this.state.data} /> <CommentForm onCommentSubmit={this.handleCommentSubmit} /> </div> ); } }); module.exports = CommentBox;
这例子代码直接与react官方代码一样,只是改成了CommonJs风格。注意:webpack尊从CommonJS规范,使用起来非常方便,require相应的模块,如$ = require('jquery'),就可以直接使用jQuery,当然要先npm安装了要使用的模块。
2、webpack入口js文件:E: elson estexpresscommentboxpublicassetsjsentry.js
var React = require('react'); var ReactDOM = require('react-dom'); var CommentBox = require('./CommentBox'); ReactDOM.render( <CommentBox url="/comments" pollInterval={2000} />, document.getElementById('commentbox') );
可参考第1点配置文件里面定义好入口js文件,名称和路径要一致。
3、添加留言版静态html页面:E: elson estexpresscommentboxpublichtmlindex.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>我的留言板</title> </head> <body> <div id="commentbox"></div> <script src="/assets/bundle.js"></script> </body> </html>
bundle.js文件就是webpack打包好的js文件,引用进来就可以直接看到效果。
4、命令行输入webpack打包js文件
webpack
这时,根据配置文件,在目录E: elson estexpresscommentboxpublicassets下会自动生成bundle.js文件
5、好,大功告成;这时在刚才打开的浏览器页面修改url地址为:http://localhost:3000/html/index.html,效果如下:
在页面上面测试发表留言,测试通过,OK
前端React代码参考自官方教程,略有改动
--React Tutorial https://facebook.github.io/react/docs/tutorial.html
后端Restful API接口参考自
--NODE.JS AND EXPRESS - CREATING A REST API http://blog.modulus.io/nodejs-and-express-create-rest-api
--nodejs+Express实现Restful的web应用 http://blog.csdn.net/jthink_/article/details/9708087