vue/react服務端渲染實例

vue和react官方已經給出了服務器渲染的方法,兩個框架自己也擁有服務器渲染的相應api,可是不管是next.js仍是nuxt.js,仍是說網上各類服務器端渲染的方案,我的認爲都有很大的侷限性,這對於咱們快速研發來講很麻煩。javascript

現行服務器渲染缺點

最大的一點就在於前端代碼和後端代碼耦合太重。他們須要公用一部分生命週期,那麼在這些生命週期中有一些對象是在服務器端纔有的,有的是在瀏覽器端纔有的,好比window對象等,這在寫代碼的時候感受超級不爽,我想在公用生命週期中使用localstorage等這些瀏覽器端纔有的對象,是會直接報錯的。php

而後學習成本,在語言的使用上,目前網上流行的服務器端渲染採用的方案絕大部分是使用nodejs進行渲染,有的研發不會nodejs只會java,這也會形成一部分的困惑和學習成本。css

而後就是代碼構成。對於已經構建好的項目若是改爲服務器端渲染,修改爲本也是很是高的,有時候不亞於從新構建一個。html

重構服務器渲染

根據上面提出的一些缺點,我想了一個方案來解決,下面我先來講一下具體實現的思路。前端

  • 前端代碼正常構建,而後打包生成文件,將打包後的文件放到後臺渲染服務器的項目中。
  • 後端添加和前端相同的路由,若是前端採用的不是問號加參數的方式(oecom.cn/article?id=… 而是經過動態路由匹配(oecom.cn/article/123 ), 咱們能夠採用路由匹配的方案來建立後臺路由。
  • 根據路由參數去接口服務器或者數據庫、redis中查詢得到數據,拼接成html,而後返回給頁面,若是java則將打包後的index.html修改爲jsp頁面,經過el表達式渲染,若是是nodejs後臺,則採用ejs等模板引擎來渲染
  • 在頁面中將服務器返回數據渲染到頁面,同時將樣式修改成:display:none,以保證用戶看不到,可是爬蟲能夠看到

經過上面的思路想必你們應該明白了,其實這個方案也有必定的使用範圍,若是是新聞稿件、我的博客等這種相似文章稿件的網站使用這種方式會特別的簡單方便,無需重改前端代碼,無須有共享耦合的代碼,後臺語言也相對比較靈活不管是java仍是php仍是nodejs均可以使用,前端框架也不侷限於vue或react。若是是一個官網頁面數據比較複雜,構成部分比較多,須要大量的異步獲取,採用這種方案就比較麻煩,因此根據本身的須要酌情使用。vue

這個方案還有一個優勢就是關鍵字、描述、title均可以進行服務器渲染,增長seo的效果,對於給爬蟲看的樣式並不須要添加,只是內容堆疊便可。java

構建示例

對於前端打包我在這裏就不在贅述,我只來講一下打包完成之後的示例,這裏採用的依然是nodejs,使用其餘語言的小夥伴可自行使用本身語言進行修改,原理都是相同的。node

<!doctype html>
<html lang="en">
<head>
    <% if(body) {%>
    <title><%=body?body.title:''%></title>
    <meta name="keywords" content="<%=body?body.keywords:''%>">
    <meta name="description" content="<%=body?body.abstract:''%>">
    <%}%>
    <% if(!body) {%>
    <title></title>
    <%}%>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="/manifest.json">
    <link rel="shortcut icon" id="favIcon" href="/favicon.ico">
    <link href="/static/css/main.c36009f4.css" rel="stylesheet">
</head>
<body>
<% if(body) {%>
<div style="display:none">
    <h1><%=body.title%></h1>
    <div><%-body.content%></div>
    <h2>熱門排行</h2>
    <div><%-hostHTML%></div>
</div>
<%}%>
<div id="root"></div>
<script type="text/javascript" src="/static/js/main.9c32e239.js"></script>
</body>
</html>
複製代碼

上方代碼是一個打包後的完整index頁面,我在頁面中經過模板語言來進行添加,判斷是否有這個返回對象,若是有就進行渲染,渲染的部分樣式設置爲none,隱藏起來,並不進行多餘的樣式調整。react

再來看一下服務器端的代碼web

//文章詳情頁
router.get('/article', function (req, res, next) {
    console.log("訪問的是article");
    var params = url.parse(req.url, true).query;
    var pageId = params.pageId.split('_');
    var queryParams = {
        sid: params.sid ? params.sid : pageId[3],
        cid: pageId[1],
        aid: pageId[0]
    }
    common.getArticle(queryParams.sid,queryParams.cid,queryParams.aid, req, function (success, data) {
        if (success) {
               res.render('html', data);
         } else {
                res.render("error");
                return
         }
    }).catch(error=>{
    	res.render("error");
    });
});

複製代碼

這部分代碼我只是摘取了其中一個路由,而且前端路由採用的是用問號來添加參數的方式,咱們後臺封裝了獲取文章稿件的方法,獲取成功之後將內容拼接好返回,也就是上面返回的data,若是查詢失敗這個data就是null,這個data中不只包含TDK,也包含須要返回的文章稿件內容和熱門排行。

添加熱門排行的緣由是讓爬蟲在網站中自行按照之後連接進行爬取,加快網頁收錄速度並增長收錄量。

後記

文章發表自:www.oecom.cn/vue-react-s…

歡迎加入qq羣共同討論:383711855

相關文章
相關標籤/搜索