系统目录及源码由此进入

目录

1. 开发前准备

1.1 技术选型
1.2 整体设计
1.3 构建开发

2. 技术点

2.1 react
2.2 redux, react-router
2.3 server-render

3. 总结

正文

1. 开发前准备

1. 1 技术选型

对于个人的博客系统而言,服务器计算能力往往不是需要考虑,而其中的 I/O 操作是比较复杂的,同理对前端的交互要求也是较高的,所以这次主要还是围绕 Node系 ,React系 框架进行开发。对于 2016 年后的互联网产品, React 搭建的 SPA ( single page ) 以及 React-Native 搭建的类似 hybrid 的原生应用,这样的开发模式,会引导今后 3 年产品的开发。

1.2 整体设计

图描绘的很简单,简单来说前端采用 React + React-router + Redux 以 flux 模式进行开发,后端采用了两个 Node Server 提供 React 服务器端渲染和数据提供,这里可以先看为一个服务器,为啥要采用两个,后面会提到。如果你有开发前后端分离项目的经验,你可以将提供 React 服务器端渲染这一块与前端合并,我们可以在上面书写 xtpl , ejs , jade 这些模板,开发起来更为流畅。

由于我的服务器是在华北地区,加上 React 这一系列的库又都是非常大的,即使我将 js , css 文件都打包成一个文件,访问起资源加载也是特别慢,所以 CDN 也是必不可少的。

1.3 构建开发

对工程完成大致设计后,我们需要利用前端工具做一些利于开发的构建,可以大致分为以下 3 个任务。

method1: 本地服务器的热加载

开发静态组件阶段为了提升开发效率,减少各位小白对 F5 的使用量,我们一般使用 webpack-dev-server 做本地服务,与一般的 webpack 配置文件不同之处也就在于入口点 entry 多加了点东西。

  1. entry: {
  2. app: [
  3. 'webpack-dev-server/client?http://localhost:3000',
  4. 'webpack/hot/only-dev-server',
  5. path.resolve(__dirname, '../views/index.js')
  6. ]
  7. }

将 webpack 中的选项传入到 webpack-dev-server (一个 express 服务器) 对象

  1. new WebpackDevServer(webpack(webpackConfig), {
  2. publicPath: '/',
  3. hot: true, // 热替换开启
  4. historyApiFallback: true, // 无刷更改url,配合react-router使用
  5. inline: true, // 热替换开启
  6. stats: {
  7. colors: true
  8. }
  9. }).listen(PORT, FUNC);

接着启动你的服务器即可完成构建。

method2: 静态资源分离

通常在开发阶段会有 import ./xxx.less 或 require('xxx.png') ES5 / ES6 语法来引入静态资源, 在打包时我们需要把所有静态文件和我们的组件解耦在合并成一个文件,这同样需要 webpack 来完成,同时要引入名为 extract-text-webpack-plugin 的插件,具体使用如下

  1. var ExtractTextPlugin = require('extract-text-webpack-plugin');
  2. module.export = {
  3. module: {
  4. loaders: [
  5. ... // other settings
  6. {
  7. test: /\.css/,
  8. loader: ExtractTextPlugin.extract('style', ['css'])
  9. },
  10. {
  11. test: /\.less/,
  12. loader: ExtractTextPlugin.extract('style', ['css', 'less'])
  13. },
  14. ]
  15. },
  16. plugins: [
  17. new ExtractTextPlugin('[name].css'),
  18. ... // other settings
  19. ]
  20. }

method3: 服务器端渲染

首先,明确一点的是 node 稳定的 4.x 版本并不能支持所有 ES6 的语法,因此采用 ES6 的语法写 node 服务器端,需要先转到 ES5 再执行,一般来说有两种方法。一是下载 babel-node 到操作系统直接执行,二是利用 webpack 引入 babel-loaderbabel-core 打包(其实两种方法是一种思想)。所以按照正常 ES6 -> ES5 的构建流程打包即可。

  1. module.export = {
  2. node: {
  3. fs: 'empty',
  4. net: 'empty',
  5. // 防止打包错乱
  6. __filename: true,
  7. __dirname: true
  8. }
  9. }

如果打包过程中出现了大量有关 fs , net 模块的报错或者打包后出现了文件引入的错误,添加上述 webpack 选项即可解决问题,这两种都是在 node 端打包经常出现的问题。

2. 开发

先来看看整个工程目录是怎样的。

build: 上述中各构建文件

server: 用于服务器端渲染的文件

views: 前端组件及redux状态管理文件系统

2.1 react

对于 react 语法这里就不提了,重点提下文件的组织方式,以便我们开发和日常维护。若只针对于工作量不大 react ,目录很简单,只需区分展示级组件( compnent ) 和 复合型组件( containers )。

--- views/

​ --- components/ 各展示级组件

​ --- containers/各复合型组件

具体呈现形式可在 github 上了解

2.2 redux, react-router

刚开始写 react 的时候总是觉得 redux 和 react-router 是一个哗众取宠的存在,直到数据量和逻辑变复杂,后台逻辑愈加复杂,而前端的 react 组件还是如同开始的上手练习一样,一直做着自顶向下的数据传递和渲染,每次更新数据我们都会请求服务器,这无疑增加了服务器的压力(对较大型应用),同时没有发挥react的长处,所谓的单页应用更是纸上谈兵。

那将三者结合会是怎样的开发体验和用户体验呢?

redux

上图是 facebook 提出 flux 架构思想,是专门用于软件的结构问题的,对于 react 开发它提供一种非常简单清晰的思想。

View : 视图层 ( react 组件)
Action (动作): 视图层发出的消息(比如 mouseClick )
Dispatcher (派发器) : 用来接收 Actions 、执行回调函数
Store (数据层) : 用来存放应用的状态,一旦发生变动,就提醒 View 要更新页面

而 redux 提供了 action , dispatcher( redux 中是 reducer ), store 的实现 ,如何实现的呢?就拿个加载某一页数据做个例子。

action.js : loadThisPage 是一个action creater,每次调用就能创建一个带有 LOAD_THIS_PAGE 指令的对象给 reducer。

  1. const LOAD_THIS_PAGE = 'LOAD_THIS_PAGE';
  2. const loadThisPage = (pN) => {
  3. return {
  4. type: LOAD_THIS_PAGE,
  5. pN
  6. }
  7. }

reducer.js : 在 reducer 中,通过判断指令来调用 store 中的数据改变状态

  1. const LOAD_THIS_PAGE = 'LOAD_THIS_PAGE';
  2. const articleReducer = (state = {}, action) => {
  3. switch(action.type) {
  4. case LOAD_THIS_PAGE:
  5. return {
  6. allArticles: state.allArticles,
  7. articles: state.allArticles.slice(0, action.pN * 5)
  8. };
  9. default:
  10. return state;
  11. }
  12. };

store.js : 创建一个 store 对象,可以通过调用这个对象的 dispatch 方法传入 action。

  1. import { createStore, applyMiddleware} from 'redux';
  2. const store = createStore(
  3. reducers,
  4. applyMiddleware(thunk) // 若需要redux中间件才添加
  5. );

这些工作做完后,还需要将 store 和组件进行一个关联,也就是说组件要能获得 redux store。

  1. import { Provider, connect } from 'react-redux';
  2. // 通过connect连接组件和store
  3. const HomeApp = connect(
  4. (state) => {
  5. return {
  6. articles: state.articleReducer.articles,
  7. articleLen: state.articleReducer.allArticles.length
  8. };
  9. }
  10. )(Home);
  11. const routes = (
  12. <Route path="/" component={ LeftArea }>
  13. <IndexRoute component={ HomeApp } />
  14. </Route>
  15. );
  16. // store通过Provider传入到react组件
  17. render(
  18. <Provider store={store} key="index">
  19. <Router history={browserHistory} routes={routes}>
  20. </Router>
  21. </Provider>, document.getElementById('app')
  22. );

react-router

相比 redux , react-router 理解起来就好多了,每当 url 发生变化,改变的只是组件,而不会重新刷新页面。

对于这样一个SPA,用户访问只需加载一次数据,之后的逻辑都由浏览器来完成了~所以对交互性来说也是很大的提升。

2.3 server render

为什么需要去实现 server render ? 也就是说服务器端渲染比客户端渲染优在哪里?

server render vs client render

服务器端渲染更利于 SEO ,更容易被爬虫识别

服务器端渲染可以增加访问速度,用户访问时直接推送已经渲染好的 react 页面,不同于客户端渲染的将 react 放入浏览器中渲染。同时减少用户CPU开销,获得更好交互性,解决了首屏加载慢的问题。

分离前后端逻辑,利于开发

如何做到 react 服务器端渲染,其实 facebook 很早就给出了解决方案,并推出了 react-dom/server 库。

  1. import { renderToString } from 'react-dom/server';
  2. const html = renderToString(
  3. <Provider store={store}>
  4. <RoutingContext {...renderProps} />
  5. </Provider>
  6. );

最初的一个问题

为什么会采用两个node服务器呢?因为在进行 webpack 对 Node 的打包时,会将数据库的相关信息打包到一起,放在网络上是不安全的,所以需要创建另一个服务器专门用提供持久化数据服务。

3. 总结

这篇博文没有对技术做太多深入的探究,但提供了一个比较清晰地开发思路,刚从事开发工作或者还是小白的你可能在独立开发一个工程时会存在很多疑问,从构建到设计,从性能到安全都是需要考虑的。

今天微信小程序也正式上线了,赶紧去尝尝鲜~

基于React服务器端渲染的博客系统的更多相关文章

  1. vuejs+nodejs支持服务端渲染的博客系统

    感悟 历时两个多月,终于利用工作之余完成了这个项目的1.0版本,为什么要写这个项目?其实基于vuejs+nodejs构建的开源博客系统有很多,但是大多数不支持服务端渲染,也不支持动态标题,只是做到了前 ...

  2. 基于express+mongodb+pug的博客系统——pug篇

    很久之前就想自己搭一个博客了,最开始用hexo+github,但是换电脑后总是有些麻烦.后来使用WordPress,但是用WordPress总觉得没什么技术含量,前后端都是人家写好的,而且买的垃圾虚拟 ...

  3. 基于express+mongodb+pug的博客系统——后台篇

    上一篇介绍了模板引擎pug.js的用法,这一篇就主要写后台逻辑了. 后台的大部分的功能都有了,只是在已经登录的状态下,前台和后台的逻辑处理还不是很完善. 先上几张图吧,仿旧版的简书,改了下UI,因为没 ...

  4. 基于开源博客系统(jpress)搭建网站

    基于开源博客系统(jpress)搭建网站 JPress 使用 Java8 开发,基于流行的JFinal和Jboot框架. 目前JPress已经内置的文章和页面其实是两个模块,可以移除和新增其他模块,因 ...

  5. Asp.net博客系统收集和简单介绍

    国内Asp.net博客系统收集和简单介绍       [转载文章,仅供个人参考,引自http://www.soyaoo.com/Blog/post/92.html] 1.ZJ-Blog程序简介:基于A ...

  6. 基于react全家桶+antd-design+webpack2+node+express+mongodb开发的前后台博客系统

    很久没更新博客,最近也有点忙,然后业余时间搞了一个比较完整基于react全家桶+antd-design+webpack2+node+express+mongodb开发的前后台博客系统的流程系统,希望对 ...

  7. 分享个基于 Node.js + React 的博客系统

    是使用 ES2015+ 特性写的,使用了 ThinkJS 框架,后台使用了 React. 完全使用 Markdown 来写文章,还可以把文章推送到团队博客系统中(团队博客也需要使用该系统). 项目地址 ...

  8. 欢迎阅读daxnet的新博客:一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统

    2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为"希赛网" ...

  9. 一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统

    2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为“希赛网”)个人空间发布过一些 ...

随机推荐

  1. if (!floor) 小明.跳楼(); 请问小明会在哪些楼层跳楼?

    博客已经迁移到www.imyzf.com,本站不再更新,请谅解! 看到标题请先思考一下这个奇葩的问题..答案在文章最后揭晓.. 会出现这个问题的起源是这样的,一个同学问我: int main() { ...

  2. hdu 2222 Keywords Search ac自动机入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...

  3. 【intellij】异常信息汇总

    Application Server was not connected before run configuration stop, reason: javax.management.Instanc ...

  4. Windows store app Settings 的 应用 ( viewmodel + windows.storage)

    1.在首页 加入 一个元素(加下滑线的).此元素绑定了两个属性 <!DOCTYPE html> <html> <head> <meta charset=&qu ...

  5. AppExtention - today

    声明: 本文转自王巍 WWDC 2014 Session笔记 - iOS 通知中心扩展制作入门 本文是我的 WWDC 2014 笔记 中的一篇,涉及的 Session 有 Creating Exten ...

  6. swfupload 上传控件的配置

    第一:下载swfupload控件,点击下载: 第二,解压缩后,在项目中添加这四个文件,如图: 然后,在你的js文件中添加这段代码: /** * *定义swfupload配置文件对象 **/ var s ...

  7. java-development.sh

    vi /etc/profile.d/java-development.sh export JAVA_HOME=/usr/local/java/jdk1..0_55 export JRE_HOME=$J ...

  8. 【综述】(MIT博士)林达华老师-"概率模型与计算机视觉”

    [综述](MIT博士)林达华老师-"概率模型与计算机视觉” 距上一次邀请中国科学院的樊彬老师为我们撰写图像特征描述符方面的综述(http://www.sigvc.org/bbs/thread ...

  9. 匿名函数和Lambda表达式

    这个题目有点牵强,真不知道如何取一个比较中意的名称,写技术博客,我很少拘泥小节,但是注重细节,如果细节都出现问题了,那么这个博文也就失去了价值. 其实应该从委托说起,委托是C#中的一个重要的内容,记得 ...

  10. 通过Hibernate将数据库在myeclipse中逆向生成

    1.首先准备好数据库. 2.在MyEclipse的右上角切换透视图,切换到MyEclipse Database Explorer 3.在最左边点击右键,选择New(也就是新建一个数据库连接),然后编写 ...