现代Web开发系列教程_07
文章目录
今天结合前面说到的前后端开发知识,做一个小工程,这个小工程并不完全具体的业务功能,但该工程包括前后端,可以作为以后复杂工程的起点。
前端代码
前端代码稍微复杂一点,就先从前端代码开始。
frontend/js/demo6.js
import React from 'react';
import ReactDOM from 'react-dom';
import ReactRouter from 'react-router';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
class App extends React.Component{
render(){
return <div>{this.props.children}</div> ;
}
}
class Home extends React.Component{
render(){
return <h1>Home Page</h1> ;
}
}
class About extends React.Component{
render(){
return <h1>About Page</h1> ;
}
}
class Features extends React.Component{
render(){
return <h1>Features Page</h1> ;
}
}
document.body.innerHTML = '<div id="reactHolder"></div>';
ReactDOM.render(
<Router history={browserHistory}>
<Route path='/' component={App}>
<IndexRoute component={Home} />
<Route path='about' component={About} />
<Route path='features' component={Features} />
<Route path='*' component={Home} />
</Route>
</Router>,
document.getElementById('reactHolder')
);
可以看到就是定义了几个React组件,并用react-router
定义了一个很简的路由,这个路由的history
使用的是browserHistory
。react
的用法可参考这里,react-router
的用法可参考这里
写前端代码编译脚本
webpack.config.js
const webpack = require("webpack");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
demo6 : __dirname + '/frontend/js/demo6.js'
},
output: {
path: __dirname + '/public',
publicPath: '/',
filename: 'js/[name].js',
hotUpdateMainFilename: 'hot-update/[hash].hot-update.json',
chunkFilename: 'js/chunks/[name].js',
hotUpdateChunkFilename: 'hot-update/chunks/[id].[hash].hot-update.js',
},
plugins: [
new webpack.SourceMapDevToolPlugin({
test: /\.(js|css|less)($|\?)/i,
filename: '[file].map'
}),
new HtmlWebpackPlugin({
title: 'demo6',
filename: 'index.html',
hash : true,
chunks : ['demo6']
})
],
module: {
loaders: [
{test: /\.(js|jsx)$/, loaders: ["babel"]}
]
},
resolve: {
extensions: ['', '.js', '.jsx']
},
devtool: 'eval'
};
.babelrc
{ "presets": ["react", "es2015"] }
上面的webpack
编译配置很简单,就是配置把frontend/js/demo6.js
编译到public/js/demo6.js
,同时生成public/index.html
,其引用生成的public/js/demo6.js
利用npm-scripts来进行webpack的调用
"scripts": {
"wpack": "./node_modules/.bin/webpack --watch --progress"
},
后端代码
backend/server.js
"use strict";
const koa = require('koa');
const serve = require('koa-static');
const sendfile = require('koa-sendfile')
const path = require('path');
const Promise = require('bluebird');
const fs = require('fs');
const statAsync = Promise.promisify(fs.stat);
const app = koa();
app.use(serve(__dirname + '/../public'));
app.use(function *(next){
let p = path.resolve(__dirname, '..', 'public', this.path);
let stats = null;
try{
stats = yield statAsync(p);
}catch(ignore){}
if (!stats) {
try {
stats = yield sendfile(this, path.resolve(__dirname, '..', 'public', 'index.html'));
}catch(ignore){}
if (!stats) this.throw(404);
}
});
const port = 5000;
app.listen(port);
console.log("server started on port " + port);
因为前端使用了browserHistory
路由,后端要实现类似nginx的try_files逻辑,详情见这里,如果后端是用Java写法,可以考虑使用TryFilesFilter
这里使用bluebird
的promisify
方法将NodeJS风格的API fs.stat
转化成返回Promise对象的方法,这个是为配合koa
的yield
而为,详见这里
同样利用npm-scripts启动后端server
"scripts": {
"serve": "node ./backend/server.js"
},
运行测试
打开两个终端,在一个里面执行npm run serve
启动后端server,在另一个里面执行npm run wpack
启动webpack对前端代码进行编译。最后使用浏览器分别访问http://127.0.0.1:5000/
、http://127.0.0.1:5000/about
、http://127.0.0.1:5000/features
,即可看到路由切换的效果。
本篇源代码地址
文章作者 Jeremy Xu
上次更新 2016-05-15
许可协议 © Copyright 2020 Jeremy Xu