首页服务器vue服务器端渲染,vue项目改造SSR(服务端渲染)

vue服务器端渲染,vue项目改造SSR(服务端渲染)

编程之家2023-10-2399次浏览

大家好,如果您还对vue服务器端渲染不太了解,没有关系,今天就由本站为大家分享vue服务器端渲染的知识,包括vue项目改造SSR(服务端渲染)的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

vue服务器端渲染,vue项目改造SSR(服务端渲染)

vue项目改造SSR(服务端渲染)

缺点:1、SEO问题

2、首屏速度问题

3、消耗性能的问题

优点:

1、更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面

vue服务器端渲染,vue项目改造SSR(服务端渲染)

2、首屏渲染速度快

SSR简单来说就是将页面在服务端渲染完成后在客户端直接展示。

index.template.html

vue服务器端渲染,vue项目改造SSR(服务端渲染)

server.js

vue项目是通过虚拟 DOM来挂载到html的,所以对spa项目,爬虫才会只看到初始结构。虚拟 DOM,最终要通过一定的方法将其转换为真实 DOM。虚拟 DOM也就是 JS对象,整个服务端的渲染流程就是通过虚拟 DOM的编译成完整的html来完成的。

需要通过Webpack打包生成两份bundle文件:

Client Bundle,给浏览器用。和纯Vue前端项目Bundle类似

Server Bundle,供服务端SSR使用,一个json文件

不管项目先前是什么样子,是否是使用vue-cli生成的。都会有这个构建改造过程。在构建改造这里会用到 vue-server-renderer库,这里要注意的是 vue-server-renderer版本要与Vue版本一样。

打包之后目录结构

vue.config.js

index.template.html

打包成客户端和服务器端

启动node服务

github地址: https://github.com/wang12321/SSR

react和vue哪个比较好

vue比较好。

VUE是iOS和Android平台上的一款 Vlog社区与编辑工具,允许用户通过简单的操作实现 Vlog的拍摄、剪辑、细调、和发布,记录与分享生活。还可以在社区直接浏览他人发布的 Vlog,与 Vloggers互动。

随着手机摄像头的发展,越来越多的人开始使用手机拍照和摄像。摄像一般来说要比拍照门槛高,但是视频传播的信息量又远大于照片。VUE就诞生在这样的背景下,希望用拍照一样简单的操作,帮助用户在手机上拍摄精美的短视频。

主要功能:

分镜头:通过点按改变视频的分镜数实现简易的剪辑效果,而剪辑能够让视频传达更多的信息。

实时滤镜:由电影调色专家调制的12款滤镜供选择,切换至前置摄像头会出现自然的自拍美颜功能。

贴纸:支持40款手绘贴纸,还可以编辑贴纸的出现时间。

自由画幅设置:支持1:1、16:9、2.39:1三种画幅的视频拍摄。

怎样使用React服务器端渲染

这次给大家带来怎样使用React服务器端渲染,使用React服务器端渲染的注意事项有哪些,下面就是实战案例,一起来看一下。

React提供了两个方法 renderToString和 renderToStaticMarkup用来将组件(Virtual DOM)输出成 HTML字符串,这是 React服务器端渲染的基础,它移除了服务器端对于浏览器环境的依赖,所以让服务器端渲染变成了一件有吸引力的事情。

服务器端渲染除了要解决对浏览器环境的依赖,还要解决两个问题:

前后端可以共享代码

前后端路由可以统一处理

React生态提供了很多选择方案,这里我们选用 Redux和 react-router来做说明。

Redux

Redux提供了一套类似 Flux的单向数据流,整个应用只维护一个 Store,以及面向函数式的特性让它对服务器端渲染支持很友好。

2分钟了解 Redux是如何运作的

关于 Store:

整个应用只有一个唯一的 Store

Store对应的状态树(State),由调用一个 reducer函数(root reducer)生成

状态树上的每个字段都可以进一步由不同的 reducer函数生成

Store包含了几个方法比如 dispatch, getState来处理数据流

Store的状态树只能由 dispatch(action)来触发更改

Redux的数据流:

action是一个包含{ type, payload}的对象

reducer函数通过 store.dispatch(action)触发

reducer函数接受(state, action)两个参数,返回一个新的 state

reducer函数判断 action.type然后处理对应的 action.payload数据来更新状态树

所以对于整个应用来说,一个 Store就对应一个 UI快照,服务器端渲染就简化成了在服务器端初始化 Store,将 Store传入应用的根组件,针对根组件调用 renderToString就将整个应用输出成包含了初始化数据的 HTML。

react-router

react-router通过一种声明式的方式匹配不同路由决定在页面上展示不同的组件,并且通过 props将路由信息传递给组件使用,所以只要路由变更,props就会变化,触发组件 re-render。

假设有一个很简单的应用,只有两个页面,一个列表页/list和一个详情页/item/:id,点击列表上的条目进入详情页。

可以这样定义路由,./routes.js

import React from'react';

import{ Route} from'react-router';

import{ List, Item} from'./components';

//无状态(stateless)组件,一个简单的容器,react-router会根据 route

//规则匹配到的组件作为 `props.children`传入

const Container=(props)=>{

return(

<p>{props.children}</p>

);

};

// route规则:

//- `/list`显示 `List`组件

//- `/item/:id`显示 `Item`组件

const routes=(

<Route path="/" component={Container}>

<Route path="list" component={List}/>

<Route path="item/:id" component={Item}/>

</Route>

);

export default routes;从这里开始,我们通过这个非常简单的应用来解释实现服务器端渲染前后端涉及的一些细节问题。

Reducer

Store是由 reducer产生的,所以 reducer实际上反映了 Store的状态树结构

./reducers/index.js

import listReducer from'./list';

import itemReducer from'./item';

export default function rootReducer(state={}, action){

return{

list: listReducer(state.list, action),

item: itemReducer(state.item, action)

};

}rootReducer的 state参数就是整个 Store的状态树,状态树下的每个字段对应也可以有自己的reducer,所以这里引入了 listReducer和 itemReducer,可以看到这两个 reducer的 state参数就只是整个状态树上对应的 list和 item字段。

具体到./reducers/list.js

const initialState= [];

export default function listReducer(state= initialState, action){

switch(action.type){

case'FETCH_LIST_SUCCESS': return [...action.payload];

default: return state;

}

}list就是一个包含 items的简单数组,可能类似这种结构:[{ id: 0, name:'first item'},{id: 1, name:'second item'}],从'FETCH_LIST_SUCCESS'的 action.payload获得。

然后是./reducers/item.js,处理获取到的 item数据

const initialState={};

export default function listReducer(state= initialState, action){

switch(action.type){

case'FETCH_ITEM_SUCCESS': return [...action.payload];

default: return state;

}

}Action

对应的应该要有两个 action来获取 list和 item,触发 reducer更改 Store,这里我们定义 fetchList和 fetchItem两个 action。

./actions/index.js

import fetch from'isomorphic-fetch';

export function fetchList(){

return(dispatch)=>{

return fetch('/api/list')

.then(res=> res.json())

.then(json=> dispatch({ type:'FETCH_LIST_SUCCESS', payload: json}));

}

}

export function fetchItem(id){

return(dispatch)=>{

if(!id) return Promise.resolve();

return fetch(`/api/item/${id}`)

.then(res=> res.json())

.then(json=> dispatch({ type:'FETCH_ITEM_SUCCESS', payload: json}));

}

}isomorphic-fetch是一个前后端通用的 Ajax实现,前后端要共享代码这点很重要。

另外因为涉及到异步请求,这里的 action用到了 thunk,也就是函数,redux通过 thunk-middleware来处理这类 action,把函数当作普通的 action dispatch就好了,比如 dispatch(fetchList())

Store

我们用一个独立的./store.js,配置(比如 Apply Middleware)生成 Store

import{ createStore} from'redux';

import rootReducer from'./reducers';

// Apply middleware here

//...

export default function configureStore(initialState){

const store= createStore(rootReducer, initialState);

return store;

}react-redux

接下来实现<List>,<Item>组件,然后把 redux和 react组件关联起来,具体细节参见 react-redux

./app.js

import React from'react';

import{ render} from'react-dom';

import{ Router} from'react-router';

import createBrowserHistory from'history/lib/createBrowserHistory';

import{ Provider} from'react-redux';

import routes from'./routes';

import configureStore from'./store';

// `INITIAL_STATE`来自服务器端渲染,下一部分细说

const initialState= window.INITIAL_STATE;

const store= configureStore(initialState);

const Root=(props)=>{

return(

<p>

<Provider store={store}>

<Router history={createBrowserHistory()}>

{routes}

</Router>

</Provider>

</p>

);

}

render(<Root/>, document.getElementById('root'));至此,客户端部分结束。

Server Rendering

接下来的服务器端就比较简单了,获取数据可以调用 action,routes在服务器端的处理参考 react-router server rendering,在服务器端用一个 match方法将拿到的 request url匹配到我们之前定义的 routes,解析成和客户端一致的 props对象传递给组件。

./server.js

import express from'express';

import React from'react';

import{ renderToString} from'react-dom/server';

import{ RoutingContext, match} from'react-router';

import{ Provider} from'react-redux';

import routes from'./routes';

import configureStore from'./store';

const app= express();

function renderFullPage(html, initialState){

return `

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

</head>

<body>

<p id="root">

<p>

${html}

</p>

</p>

<script>

window.INITIAL_STATE=${JSON.stringify(initialState)};

</script>

<script src="/static/bundle.js"></script>

</body>

</html>

`;

}

app.use((req, res)=>{

match({ routes, location: req.url},(err, redirectLocation, renderProps)=>{

if(err){

res.status(500).end(`Internal Server Error${err}`);

} else if(redirectLocation){

res.redirect(redirectLocation.pathname+ redirectLocation.search);

} else if(renderProps){

const store= configureStore();

const state= store.getState();

Promise.all([

store.dispatch(fetchList()),

store.dispatch(fetchItem(renderProps.params.id))

])

.then(()=>{

const html= renderToString(

<Provider store={store}>

<RoutingContext{...renderProps}/>

</Provider>

);

res.end(renderFullPage(html, store.getState()));

});

} else{

res.status(404).end('Not found');

}

});

});服务器端渲染部分可以直接通过共用客户端 store.dispatch(action)来统一获取 Store数据。另外注意 renderFullPage生成的页面 HTML在 React组件 mount的部分(<p id="root">),前后端的 HTML结构应该是一致的。然后要把 store的状态树写入一个全局变量(INITIAL_STATE),这样客户端初始化 render的时候能够校验服务器生成的 HTML结构,并且同步到初始化状态,然后整个页面被客户端接管。

最后关于页面内链接跳转如何处理?

react-router提供了一个<Link>组件用来替代<a>标签,它负责管理浏览器 history,从而不是每次点击链接都去请求服务器,然后可以通过绑定 onClick事件来作其他处理。

比如在/list页面,对于每一个 item都会用<Link>绑定一个 route url:/item/:id,并且绑定 onClick去触发 dispatch(fetchItem(id))获取数据,显示详情页内容。

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

推荐阅读:

怎样使用JS实现计算圆周率到小数点后100位

怎样使用vue axios给生产与发布环境配置接口地址

关于vue服务器端渲染和vue项目改造SSR(服务端渲染)的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

云服务器可以玩游戏吗(云服务器可以做游戏服务器吗)文件服务器是什么,什么是邮件服务器,与文件服务器区别大吗