详解react/redux的服务端渲染:页面性能与SEO
亟待解决的疑问
为什么服务端渲染首屏渲染快?(对比客户端首屏渲染)
为什么服务端渲染有利于SEO?(对比客户端渲染)
服务端渲染的具体的代码
export const increment = () => {
return { type:'INCREMENT' }
} export const decrement = () => {
return { type:'DECREMENT' }
}
import { combineReducers } from 'redux' const initState = { number:0 }
const counterReducer = (state = initState, action) => {
const { number } = state
switch (action.type) {
case 'INCREMENT':
return { number:number + 1}
case 'DECREMENT':
return { number:number - 1}
default:
return state
}
} export default combineReducers({ counterReducer })
import { createStore } from 'redux'
import reducer from '../reducer' export default (preloadedState={}) => {
const store = createStore(
reducer,
preloadedState
)
return store
}
import React from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import ComponentApp from '../component'
import * as NumberActions from '../action' const mapStateToProps = state => {
return { number:state.counterReducer.number }
} const mapDispatchToProps = dispatch => {
return bindActionCreators(NumberActions,dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(ComponentApp)
import React from 'react' class ComponentApp extends React.Component{
render () {
const { number, increment, decrement } = this.props
return (
<div>
<h1>{number}</h1>
<button onClick={increment}>增1</button>
<button onClick={decrement}>减1</button>
</div>
)
}
} export default ComponentApp
import React from 'react'
import path from'path'
import ReactDOMServer from 'react-dom/server'
import { Provider } from 'react-redux' import createStore from '../common/store'
import App from '../common/container' /************ 这部分代码参考自webpack-dev-middleware的官方文档 ************/
var express = require("express");
var webpackDevMiddleware = require("webpack-dev-middleware");
var webpack = require("webpack");
var webpackConfig = require('../../webpack.config.js'); var app = express(); var compiler = webpack(webpackConfig);
app.use(webpackDevMiddleware(compiler, {
// 这个publicPath参数要和webpack.config.js的`output.publicPath`参数保持一致
publicPath:webpackConfig.output.publicPath
})); /************ 这部分代码参考自webpack-dev-middlemare的官方文档 ************/
//链接 https://webpack.js.org/guides/development/#webpack-dev-middleware
/*
renderFullPage函数,渲染完整的首屏可视页面(这个页面渲染完毕后将被发送到客户端)
第一个参数是被转成字符串的APP,要将其插入入口HMTL文件中
第二个参数是初始化的state,将其放入window对象中以便在发送到客户端后能通过window.__INITIAL_STATE__取用
*/ const renderFullPage = (html, preloadState) => {
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<div id="root">${html}</div>
<script>window.__INITIAL_STATE__ =${JSON.stringify(preloadState)}</script>
<script src="/static/bundle.js"></script>
</body>
</html>`
} const handleRender = (req, res) => {
// 初始化store,有两个作用:1.放入Provider的store属性中 2. 通过store.getState()获取初始化的state
const store = createStore()
// 将APP转成字符串
const html = ReactDOMServer.renderToString(
<Provider store={store}>
<App />
</Provider>
)
// 取得初始化的state
const preloadState = store.getState()
// 将渲染完整的首屏可视页面(字符串)发送到客户端显示
res.send(renderFullPage(html, preloadState))
} // 注册中间件函数,每当从客户端接收到请求的时候,运行handleRender函数
app.use(handleRender) // 监听3000端口
app.listen(3000, (error) => {
if (error) {
console.error(error)
}
})
// 确保在node环境下能编译es6(es2015)和JSX(react)的语法
require('babel-core/register')({
presets: ['es2015', 'react']
})
require('./server')
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import createStore from '../common/store'
import App from '../common/container' // 取得服务端发送过来的初始化state
const initialState = window.__INITIAL_STATE__
// 初始化store
const store = createStore(initialState)
// reactDOM渲染
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
如何理解两个渲染过程?(ReactDOMServer.renderToString和 reactDOM.render的联系)
为什么要把state(redux)从服务端传到客户端?
解决服务端渲染代码中的“痛点”
在node环境运行ES6语法和JSX语法——babel-core/register的使用
require('babel-core/register')({
presets: ['es2015', 'react']
})
使发送到客户端的页面能访问打包后的bundle.js—— webpack.output.publicPath的使用
output:{
filename:'bundle.js',
path:path.join(__dirname,'dist'),
publicPath: '/static'
}
var webpackConfig = require('../../webpack.config.js');
// 省略其他内容
app.use(webpackDevMiddleware(compiler, {
publicPath:webpackConfig.output.publicPath // Same as `output.publicPath` in most cases.
}));
参考资料:文章标题,作者和链接(按先后顺序)
详解react/redux的服务端渲染:页面性能与SEO的更多相关文章
- 【redux】详解react/redux的服务端渲染:页面性能与SEO
亟待解决的疑问 为什么服务端渲染首屏渲染快?(对比客户端首屏渲染) react客户端渲染的一大痛点就是首屏渲染速度慢问题,因为react是一个单页面应用,大多数的资源需要在首次渲染前就加载 ...
- vuejs服务端渲染更好的SEO,SSR完全指南Nuxt.js静态站生成器
vuejs服务端渲染更好的SEO,SSR完全指南Nuxt.js静态站生成器SSR 完全指南https://cn.vuejs.org/v2/guide/ssr.html在 2.3 发布后我们发布了一份完 ...
- React(0.13) 服务端渲染的两个函数
1.React.renderToString 函数, 参数是组件,返回一个字符串 <!DOCTYPE html> <html> <head> <title& ...
- react+laravel与服务端渲染的几点思考
一.前后端完全分离 1.用React.js做MVC中的V,剩下的交给Laravel 2.Laravel用来做API接口开发. 3.好处:实现了前后端开发的分离,从而加快前后端开发效率.另外若是多端的如 ...
- Asp.Net MVC 模型验证详解-实现客户端、服务端双重验证
概要 在asp.net webform开发中经常会对用户提交输入的信息进行校验,一般为了安全起见大家都会在客户端进行Javascript(利于交互).服务端双重校验(安全).书写校验代码是一个繁琐的过 ...
- 解析Nuxt.js Vue服务端渲染摸索
本篇文章主要介绍了详解Nuxt.js Vue服务端渲染摸索,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指正. Nuxt.js 十分简单易用.一个简单 ...
- 教你如何在React及Redux项目中进行服务端渲染
服务端渲染(SSR: Server Side Rendering)在React项目中有着广泛的应用场景 基于React虚拟DOM的特性,在浏览器端和服务端我们可以实现同构(可以使用同一份代码来实现多端 ...
- react服务端渲染框架
客户端渲染 加载一个空的html页面,然后请求一个打包的js文件,然后再客户端执行这个js文件 动态生成html内容然后插入到DOM元素上,在源代码查询中也只能看到空的html文档 没有任何其他内容 ...
- 6.前端基于react,后端基于.net core2.0的开发之路(6) 服务端渲染(SSR)
0.源码地址 https://gitee.com/teambp/ScaffoldClient 这个地址下载对应源码. 1.服务端渲染是啥? 就是在服务器进行页面渲染(废话),当页面展示后,显示的就是 ...
随机推荐
- 【JavaScript你需要知道的基础知识~】
最近开始学习JavaScript,整理了一些相关的基础知识 JS注释方式:// 单行注释(Ctrl+/ )/* 段落注释(Ctrl+shift+/ )*/ [JavaScript基础]JavaScri ...
- .net 企业管理系统快熟搭建框架
简言 本人在博客园注册也2年多了,一直没有写自己的博客,因为才疏学浅一直跟着园子里的大哥们学习这.net技术.一年之前跳槽到现在的公司工作,由于公司没有自己一套的开发框架,每次都要重新 ...
- iOS最新企业证书的生成
PS:不知道什么原因 图片显示不出来 请看我简书里面的文章 http://www.jianshu.com/p/baab03ac43e9 1.生成CSR文件 SpotLight搜索>钥匙串访问 ...
- window.opener的用法
window.opener 主要用来打开窗体的父窗体,可以通过这种方式设置父窗体的值或者调用js方法. 例如: 1,window.opener.test(); ---调用父窗体中的test()方法 2 ...
- 全景技术大揭秘,市场核心早洞悉——VR全景加盟
未来已来,未来已见.2017是3D全景创业的天时,全景行业逐步走向成熟.全景智慧城市专注vr全景6年,技术国内遥遥领先.全景智慧城市市场总监常诚,透漏3D全景技术和市场的核心. 拍摄全景必备的设备:单 ...
- 翻译Algorithms Unlocked
写在前面 本书是由<算法导论>(Introduction to Algorithms)的作者之一Thomas H. Cormen编写的适合对算法感兴趣但自身基础又不好的同学阅读.很多人评价 ...
- OVS 中的 upcall 线程
总体概览如下: 假设upcall handler线程有两个,vport有四个,那么每个vport下都将持有两个NetLink连接的信息,这两个NetLink连接将被用来上送upcall消息. 每个Ne ...
- java基础(六章)
一.for循环的使用场合 l while循环--先判断,再循环 while(1.条件表达式){ //2.循环操作 //3.更改循环条件表达式 } l do-while--先循环 ...
- jQuery 提供多个与 AJAX 有关的方法。
jQuery 提供多个与 AJAX 有关的方法. 通过 jQuery AJAX 方法,您能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本.HTML.XML 或 JSON - ...
- CSDN删除上传资源的办法
转自网友:http://blog.csdn.net/ssergsw/article/details/12489101 我按照下面的方法一试,果然成功了. 昨天晚上进行测试,上传了一个压缩包和大家分享, ...