学习使用React一步步搭建普通博客应用
当我们考虑一些单页应用的时候(SPAs),一般考虑浏览器,JavaScript和速度,对搜索引擎是不可见的。由于单页应用使用JavaScript来渲染页面中的内容,同时web网络爬虫不通过浏览器来查看整个网页,这样就不能看到和索引页面中所有的内容。或者,更好的说,其中大部分是不能。一些开发人员试图以各种方式来解决这个问题。 在服务器端使用Node.js在客户端使用React,我们可以构建通用的JavaScript应用程序。这可以从服务器端和浏览器端的渲染中提供许多好处,允许搜索引擎和人类使用浏览器来查看单页应用中的内容。 在这个教程中分为两个部分,我将向您展示如何通过服务器端渲染大搭建一个普通的React博客应用系统来使应用对搜素引擎可见。然后,它能够使该应用在浏览器中快速和响应式。 开始该博客系统将使用到以下一些技术和工具:
开始之前,首先在命令行中运行一下内容: mkdir react-universal-blog
cd react-universal-blog
新建一个 {
"name": "react-universal-blog","version": "1.0.0","description": "","main": "app-server.js","dependencies": { "babel": "^5.8.29","babel-core": "^5.8.32","babel-loader": "^5.3.2","cosmicjs": "^2.0.0","events": "^1.1.0","express": "^4.13.3","flux": "^2.1.1","history": "^1.14.0","hogan-express": "^0.5.2","lodash": "^3.10.1","react": "^0.14.1","react-dom": "^0.14.1","react-router": "^1.0.1","webpack": "^1.12.2" },"scripts": { "development": "cp views/index.html public/index.html && NODE_ENV=development webpack && webpack-dev-server --content-base public/ --hot --inline --devtool inline-source-map --history-api-fallback" },"author": "","license": "ISC","devDependencies": { "react-hot-loader": "^1.3.0","webpack-dev-server": "^1.12.1" } }
在这个文件中你应该已经注意到了我们添加了一下内容:
配置webpack文件, // webpack.config.js
if(process.env.NODE_ENV === 'development'){
var loaders = ['react-hot','babel']
} else {
var loaders = ['babel']
}
module.exports = {
devtool: 'eval',entry: './app-client.js',output: {
path: __dirname + '/public/dist',filename: 'bundle.js',publicPath: '/dist/'
},module: {
loaders: [{
test: /.js$/,loaders: loaders,exclude: /node_modules/
}]
}
};
注意到我们这里添加了一个entery属性,属性的值为app-client.js。这个文件将作为我们应用的入口点,意味着webpack将从这个点开始打包我们的应用,并且将其输出到路径 在讲解与React相关的一些技术内容之前,先来看一些我们完成整个博客将要展现的样子。由于次教程中我们这里希望你能够将更多的精力放在搭建应用的功能性上而不是博客的样式上面,这里我们选择使用已经建好的前端样式主题,选择Start Bootsrtap样式里面的Clean Blog 新建一个文件夹,命名为 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>{{ site.title }}{{# page }} | {{ page.title }}{{/ page }}</title> <!-- Bootstrap Core CSS --> <link href="/css/bootstrap.min.css" rel="stylesheet"> <!-- Custom CSS --> <link href="/css/clean-blog.min.css" rel="stylesheet"> <link href="/css/cosmic-custom.css" rel="stylesheet"> <!-- Custom Fonts --> <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet" type="text/css"> <link href="//fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic" rel="stylesheet" type="text/css"> <link href="//fonts.googleapis.com/css?family=Open+Sans:300italic,600italic,700italic,800italic,400,300,600,800" rel="stylesheet" type="text/css"> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body class="hidden"> <div id="app">{{{ reactMarkup }}}</div> <script src="/js/jquery.min.js"></script> <script src="/js/bootstrap.min.js"></script> <script src="/js/clean-blog.min.js"></script> <script src="/dist/bundle.js"></script> </body> </html>
所有的公共JS和CSS文件下载GitHub repository。点击这里下载 通常为了防止使用jQuery,一般我会选择经典的React Bootstrap。然而为了简洁,在主题框架中使用了部分jQuery的功能。 在 在这个点上,你的应用程序拥有以下结构: package.json
public
|-css
|-bootstrap.min.css
|-cosmic-custom.css
|-js
|-jquery.min.js
|-bootstrap.min.js
|-clean-blog.min.js
views
|-index.html
webpack.config.js
搭建好静态目录之后,开始建立React的组件。 博客应用的基本组价开始搭建博客的应用界面,博客包括以下页面:
开始建立新的文件,命名 // app-client.js
import React from 'react'
import {render} from 'react-dom'
import {Route} from 'react-router'
import createBrowserHistory from 'history/lib/createBrowserHistory'
const history = createBrowerHistory()
// Routes
import routes from './routes'
const Routes = (
<Router history={history}>
{routes}
</Router>
)
const app = document.getElementById('app')
render(Routes,app)
如果你想进一步了解有关 添加 // routes.js
import React,{Component} from 'react'
import { Route,IndexRoute,Link} from 'react-router'
//Main component
class App extends Component{
componentDidMount(){
document.body.className=''
}
render(){
return (
<div>
<h1>React Universal Blog</h1>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/work">Work</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</nav>
{ this.props.children }
</div>
)
}
}
//Pages
class Home extends Component{
render(){
return (
<div>
<h2>Home</h2>
<div>Some home page content</div>
</div>
)
}
}
class About extends Component {
render(){
return (
<div>
<h2>About</h2>
<div>Some about page content</div>
</div>
)
}
}
class Work extends Component {
render(){
return (
<div>
<h2>Work</h2>
<div>Some work page content</div>
</div>
)
}
}
class Contact extends Component {
render(){
return (
<div>
<h2>Contact</h2>
<div>Some contact page content</div>
</div>
)
}
}
class NoMatch extends Component {
render(){
return (
<div>
<h2>NoMatch</h2>
<div>404 error</div>
</div>
)
}
}
export default (
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="about" component={About}/>
<Route path="work" component={Work}/>
<Route path="contact" component={Contact}/>
<Route path="*" component={NoMatch}/>
</Route>
)
到目前为止,我们搭建好了一个基本的包含不同页面的博客应用例子。现在,让我们来具体运行一下应用,在终端中运行一下内容: mkdir public
npm install
npm run development
在浏览器中输入网址http://localhost:8080来查看博客运行的基本效果。 上述步骤完成之后,现在运行至服务器端,新建文件 // app-server.js
import React from 'react'
import { match,RoutingContext } from 'react-router'
import ReactDOMServer from 'react-dom/server'
import express from 'express'
import hogan from 'hogan-express'
// Routes
import routes from './routes'
// Express
const app = express()
app.engine('html',hogan)
app.set('views',__dirname + '/views')
app.use('/',express.static(__dirname + '/public/'))
app.set('port',(process.env.PORT || 3000))
app.get('*',(req,res) => { match({ routes,location: req.url },(error,redirectLocation,renderProps) => { const reactMarkup = ReactDOMServer.renderToStaticMarkup(<RoutingContext {...renderProps}/>) res.locals.reactMarkup = reactMarkup if (error) { res.status(500).send(error.message) } else if (redirectLocation) { res.redirect(302,redirectLocation.pathname + redirectLocation.search) } else if (renderProps) { // Success! res.status(200).render('index.html') } else { res.status(404).render('index.html') } }) }) app.listen(app.get('port')) console.info('==> Server is listening in ' + process.env.NODE_ENV + ' mode') console.info('==> Go to http://localhost:%s',app.get('port'))
在 在接下来的步骤中,我们将建立文件 //app.js
require('babel/register')
require('./app-server.js')
我们将从该文件启动我们的服务, 不过首先,让我们先创建一个脚本。 打开 // ...
"scripts": {
"development": "cp views/index.html public/index.html && NODE_ENV=development webpack && webpack-dev-server --content-base public/ --hot --inline --devtool inline-source-map --history-api-fallback","production": "rm -rf public/index.html && NODE_ENV=production webpack -p && NODE_ENV=production node app.js","start": "npm run production"
}
// ...
到目前为止,已经部署好了生产环境的脚本代码,我们可以同时在服务器d端和客户端运行代码,终端中运行以下内容: npm start
在浏览器地址栏中输入http://localhsot:3000.你就可以看到你的博客单页应用了。 在浏览器中点击查看源码。 结论在这部分中,我们初步了解了使用React和Node.js一起搭建一个React普通博客应用。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |