国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

從零開(kāi)始搭建一個(gè)vue-ssr(上)

Winer / 2331人閱讀

摘要:從零開(kāi)始搭建一個(gè)背景是什么全拼是,服務(wù)端渲染。大家不妨可以打開(kāi)一些頁(yè)面或者一些公司的網(wǎng)站,查看源代碼,你會(huì)發(fā)現(xiàn),也是有這個(gè)標(biāo)記。這時(shí)候,我們發(fā)現(xiàn)頁(yè)面的路由切換生效了,并且不同頁(yè)面的源代碼也不一樣了。從零開(kāi)始搭建一個(gè)下項(xiàng)目源碼

從零開(kāi)始搭建一個(gè)vue-ssr 背景 What?SSR是什么?

SSR全拼是Server-Side Rendering,服務(wù)端渲染。
所謂服務(wù)端渲染,指的是把vue組件在服務(wù)器端渲染為組裝好的HTML字符串,然后將它們直接發(fā)送到瀏覽器,最后需要將這些靜態(tài)標(biāo)記混合在客戶端上完全可交互的應(yīng)用程序。

Why?為什么選擇SSR?

①滿足seo需求,傳統(tǒng)的spa數(shù)據(jù)都是異步加載的,爬蟲(chóng)引擎無(wú)法加載,需要利用ssr將數(shù)據(jù)直出渲染在頁(yè)面源代碼中。
②更寬的內(nèi)容達(dá)到時(shí)間(首屏加載更快),當(dāng)請(qǐng)求頁(yè)面的時(shí)候,服務(wù)端渲染完數(shù)據(jù)之后,把渲染好的頁(yè)面直接發(fā)送給瀏覽器,并進(jìn)行渲染。瀏覽器只需要解析html不需要去解析js。

How?SSR的原理

借用下面的一張圖,我們來(lái)簡(jiǎn)單闡述一下vue-ssr的原理。

我們可以看到,左側(cè)Source部分就是我們所編寫的源代碼,所有代碼有一個(gè)公共入口,就是app.js,緊接著就是服務(wù)端的入口
(entry-server.js)和客戶端的入口(entry-client.js)。當(dāng)完成所有源代碼的編寫之后,我們通過(guò)webpack的構(gòu)建,打包出兩個(gè)bundle,分別是server bundle和client bundle;當(dāng)用戶進(jìn)行頁(yè)面訪問(wèn)的時(shí)候,先是經(jīng)過(guò)服務(wù)端的入口,將vue組建組裝為html字符串,并混入客戶端所訪問(wèn)的html模板中,最終就完成了整個(gè)ssr渲染的過(guò)程。

開(kāi)始搭建 創(chuàng)建一個(gè)空白目錄并初始化

在終端輸入以下命令

mkdir ssr-demo
cd ssr-demo
npm init

由于我們這個(gè)只是一個(gè)demo項(xiàng)目,可以直接一路按回車鍵,直接忽略配置。
完成之后我們可以看到文件夾里面有一個(gè)package.json的文件,這就是配置表。

安裝依賴

該項(xiàng)目需要四個(gè)依賴,依次安裝

npm install express
npm install vue
npm install vue-router
npm install vue-server-renderer

其中express使我們node端的框架,vue用于創(chuàng)建vue實(shí)例,vue-router則用于實(shí)現(xiàn)路由控制,最后vue-server-renderer尤為關(guān)鍵,我們實(shí)現(xiàn)的vue-ssr依靠于這個(gè)庫(kù)提供的API。
在安裝依賴完畢之后,我們看到package.json中已經(jīng)把四個(gè)依賴都寫上了。

"express": "^4.17.1",
"vue": "^2.6.10",
"vue-router": "^3.0.6",
"vue-server-renderer": "^2.6.10"
創(chuàng)建一個(gè)node服務(wù)

在根目錄下我們新建一個(gè)server.js,用戶搭建node服務(wù)

const express = require("express");
const app = express();

app.get("*", (request, response) => {
    response.end("hello, ssr");
})

app.listen(3001, () => {
    console.log("服務(wù)已開(kāi)啟")
})

接著為了后續(xù)開(kāi)發(fā)的便利,我們?cè)趐ackage.json中添加一個(gè)啟動(dòng)命令:

"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "server": "node index.js"
 },

接著我們?cè)诮K端輸入 npm run server,然后再瀏覽器輸入localhost:3001,便可以看到頁(yè)面中的文字被成功渲染。

渲染html頁(yè)面

在上一步我們已經(jīng)能成功渲染出一個(gè)文字,但是ssr并不是主要為了渲染文字,而是渲染一個(gè)html模板。
那么,接下來(lái),我們得告知瀏覽器,我們需要渲染的是html,而不只是text,因此我們需要修改響應(yīng)頭。
同時(shí),引入vue-server-renderer中的createRenderer對(duì)象,有一個(gè)renderToString的方法,可以將vue實(shí)例轉(zhuǎn)成html的形式。(renderToString這個(gè)方法接受的第一個(gè)參數(shù)是vue的實(shí)例,第二個(gè)參數(shù)是一個(gè)回調(diào)函數(shù),如果不想使用回調(diào)函數(shù)的話,這個(gè)方法也返回了一個(gè)Promise對(duì)象,當(dāng)方法執(zhí)行成功之后,會(huì)在then函數(shù)里面返回html結(jié)構(gòu)。)
修改server.js如下:

const express = require("express");
const app = express();
const Vue = require("vue");
const vueServerRender = require("vue-server-renderer").createRenderer();

app.get("*", (request, response) => {
    const vueApp = new Vue({
        data:{
           message: "hello, ssr"
        },
        template: `

{{message}}

` }); response.status(200); response.setHeader("Content-type", "text/html;charset-utf-8"); vueServerRender.renderToString(vueApp).then((html) => { response.end(html); }).catch(err => console.log(err)) }) app.listen(3001, () => { console.log("服務(wù)已開(kāi)啟") })

保存代碼,重啟服務(wù),然后重新刷新頁(yè)面。我們發(fā)現(xiàn),頁(yè)面好像沒(méi)什么不同,就是字體變粗了而已。其實(shí)并不是,你可以嘗試查看頁(yè)面源代碼,我們發(fā)現(xiàn)在源代碼中,已經(jīng)存在一個(gè)標(biāo)簽對(duì)h1,這就是html模板的雛形。同時(shí),細(xì)心的同學(xué)還會(huì)發(fā)現(xiàn),h1上面有一個(gè)屬性:
data-server-rendered="true",那這個(gè)屬性是干什么的呢?這個(gè)是一個(gè)標(biāo)記,表明這個(gè)頁(yè)面是由vue-ssr渲染而來(lái)的。大家不妨可以打開(kāi)一些seo頁(yè)面或者一些公司的網(wǎng)站,查看源代碼,你會(huì)發(fā)現(xiàn),也是有這個(gè)標(biāo)記。
雖然h1標(biāo)簽對(duì)被成功渲染,但是我們發(fā)現(xiàn)這個(gè)html頁(yè)面并不完整, 他缺少了文檔聲明,html標(biāo)簽,body標(biāo)簽,title標(biāo)簽等。

將Vue實(shí)例掛載進(jìn)html模板中

創(chuàng)建一個(gè)index.html,用于掛載Vue實(shí)例。







Hello, SSR


    

注意,body中的注釋不能去掉,這是Vue掛載的占位符。
然后修改server.js,將html模板引進(jìn)去。這里我們?cè)赾reateRenderer函數(shù)可以接收一個(gè)對(duì)象作為配置參數(shù)。配置參數(shù)中有一項(xiàng)為template,這項(xiàng)配置的就是我們即將使用的Html模板。這個(gè)接收的不是一個(gè)單純的路徑,我們需要使用fs模塊將html模板讀取出來(lái)。

let path = require("path");
const vueServerRender = require("vue-server-renderer").createRenderer({
    template:require("fs").readFileSync(path.join(__dirname,"./index.html"),"utf-8")
});

保存代碼,重啟服務(wù),然后重新刷新頁(yè)面。我們查看源代碼,發(fā)現(xiàn),已經(jīng)能成功渲染出一個(gè)完整的頁(yè)面了。

創(chuàng)建一個(gè)Vue項(xiàng)目的開(kāi)發(fā)目錄

上面的開(kāi)發(fā)模式,很顯然只是一個(gè)demo而已,接下來(lái)我們模擬一下正常的vue開(kāi)發(fā)的目錄結(jié)構(gòu)。
創(chuàng)建一個(gè)src文件夾,里面有一個(gè)router文件夾,再有一個(gè)index,js用作路由,并創(chuàng)建一個(gè)app.js,用作vue的入口,如下圖:

修改router/index.js

const vueRouter = require("vue-router");
const Vue = require("vue");

Vue.use(vueRouter);

module.exports = () => {
    return new vueRouter({
        mode:"history",
        routes:[
            {
                path:"/",
                component:{
                    template:`

this is home page

` }, name:"home" }, { path:"/about", component:{ template:`

this is about page

` }, name:"about" } ] }) }

修改app.js

const Vue = require("vue");
const createRouter = require("./router")

module.exports = (context) => {
    const router = createRouter();
    return new Vue({
        router,
        data:{
            message:"Hello,Vue SSR!",
        },
        template:`
            

{{message}}

  • home
  • about
` }); }

然后在server.js中,將app.js引入

const express = require("express");
const app = express();
const vueApp = require("./src/app.js");

let path = require("path");
const vueServerRender = require("vue-server-renderer").createRenderer({
    template:require("fs").readFileSync(path.join(__dirname,"./index.html"),"utf-8")
});

app.get("*", (request, response) => {
    let vm = vueApp({});

    response.status(200);
    response.setHeader("Content-type", "text/html;charset-utf-8");

    vueServerRender.renderToString(vm).then((html) => {
        response.end(html);
    }).catch(err => console.log(err))
})

app.listen(3001, () => {
    console.log("服務(wù)已開(kāi)啟")
})

保存代碼,重啟服務(wù),然后重新刷新頁(yè)面。然后我們可以看到瀏覽器的路由已經(jīng)被成功渲染了,但是無(wú)論怎么點(diǎn)擊都沒(méi)反應(yīng),瀏覽器的url有更改,但是頁(yè)面內(nèi)容不變。
這是因?yàn)槲覀冎皇菍㈨?yè)面渲染的工作交給服務(wù)端,而頁(yè)面路由切換,還是在前端執(zhí)行,服務(wù)端并未能接收到該指令,因此無(wú)論怎么切換路由,服務(wù)端渲染出來(lái)的頁(yè)面根本沒(méi)變化。

實(shí)現(xiàn)服務(wù)端控制頁(yè)面路由

在src中創(chuàng)建一個(gè)entry-server.js文件,該文件為服務(wù)端入口文件,接收app和router實(shí)例:

const createApp = require("./app.js");

module.exports = (context) => {
    return new Promise(async (reslove,reject) => {
        let {url} = context;

        let {app,router} = createApp(context);
        router.push(url);
        //  router回調(diào)函數(shù)
        //  當(dāng)所有異步請(qǐng)求完成之后就會(huì)觸發(fā)
        router.onReady(() => {
            let matchedComponents = router.getMatchedComponents();
            if(!matchedComponents.length){
                return reject();
            }
            reslove(app);
        },reject)
    })
}

在src中創(chuàng)建一個(gè)entry-client.js文件,該文件為客戶端入口,負(fù)責(zé)將路由掛載到app里面。

const createApp = require("./app.js");
let {app,router} = createApp({});

router.onReady(() => {
    app.$mount("#app")
});

修改app.js,將router和vue實(shí)例暴露出去

const Vue = require("vue");
const createRouter = require("./router")

module.exports = (context) => {
    const router = createRouter();
    const app =  new Vue({
        router,
        data:{
            message:"Hello,Vue SSR!",
        },
        template:`
            

{{message}}

  • home
  • about
` }); return { app, router } }

最終修改server.js

const express = require("express");
const app = express();

const App = require("./src/entry-server.js");

let path = require("path");
const vueServerRender = require("vue-server-renderer").createRenderer({
    template:require("fs").readFileSync(path.join(__dirname,"./index.html"),"utf-8")
});

app.get("*", async(request, response) => {

    response.status(200);
    response.setHeader("Content-type", "text/html;charset-utf-8");

    let {url} = request;
    let vm;
    vm = await App({url})
    vueServerRender.renderToString(vm).then((html) => {
        response.end(html);
    }).catch(err => console.log(err))
})

app.listen(3001, () => {
    console.log("服務(wù)已開(kāi)啟")
})

保存代碼,重啟服務(wù),然后重新刷新頁(yè)面。這時(shí)候,我們發(fā)現(xiàn)頁(yè)面的路由切換生效了,并且不同頁(yè)面的源代碼也不一樣了。

數(shù)據(jù)傳遞

既然是服務(wù)端渲染,數(shù)據(jù)的接收也是來(lái)源于服務(wù)端,那怎樣才能把服務(wù)端接收到的數(shù)據(jù)傳輸給前端,然后進(jìn)行渲染呢?
修改entry-server.js,進(jìn)行同步或者異步獲取數(shù)據(jù)

const createApp = require("./app.js");

const getData = function(){
    return new Promise((reslove, reject) => {
        let str = "this is a async data!";
        reslove(str);
    })
}

module.exports = (context) => {
    return new Promise(async (reslove,reject) => {
        let {url} = context;

        // 數(shù)據(jù)傳遞
        context.propsData = "this is a data from props!"

        context.asyncData = await getData();

        let {app,router} = createApp(context);
        router.push(url);
        //  router回調(diào)函數(shù)
        //  當(dāng)所有異步請(qǐng)求完成之后就會(huì)觸發(fā)
        router.onReady(() => {
            let matchedComponents = router.getMatchedComponents();
            if(!matchedComponents.length){
                return reject();
            }
            reslove(app);
        },reject)
    })
}

修改app.js,接收數(shù)據(jù)并渲染

const Vue = require("vue");
const createRouter = require("./router")

module.exports = (context) => {
    const router = createRouter();
    const app =  new Vue({
        router,
        data:{
            message:"Hello,Vue SSR!",
            propsData: context.propsData,
            asyncData: context.asyncData
        },
        template:`
            

{{message}}

{{asyncData}}

{{propsData}}

  • home
  • about
` }); return { app, router } }

最后我們可以看到無(wú)論是同步還是異步獲取的數(shù)據(jù),都能成功地通過(guò)服務(wù)端渲染,展示在頁(yè)面源代碼中。
另外,你也可以在server.js中的request中,將數(shù)據(jù)傳遞下去。

總結(jié)

實(shí)現(xiàn)了一個(gè)簡(jiǎn)易版本的vue-ssr,下期我們會(huì)依賴于vue-cli,進(jìn)行webpack改造,實(shí)現(xiàn)一個(gè)通用且更實(shí)用的vue-ssr框架。從零開(kāi)始搭建一個(gè)vue-ssr(下)

項(xiàng)目源碼

https://github.com/TheWalking...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/105156.html

相關(guān)文章

  • 從零開(kāi)始搭建一個(gè)vue-ssr(下)

    摘要:開(kāi)始改建補(bǔ)充安裝依賴與上一次不同,這次我們基于進(jìn)行改建,已經(jīng)有了很多依賴庫(kù)了,但我們?nèi)涡枰a(bǔ)充一個(gè)核心修改客戶端的配置修改文件,添加插件添加了這個(gè)配置以后,重新啟動(dòng)項(xiàng)目通過(guò)地址就可以訪問(wèn)到,頁(yè)面中出現(xiàn)的內(nèi)容就是所需要的。 從零開(kāi)始搭建一個(gè)vue-ssr 前言 上次我們已經(jīng)實(shí)現(xiàn)了從零開(kāi)始,搭建一個(gè)簡(jiǎn)單的vue-ssr的demo:從零開(kāi)始搭建一個(gè)vue-ssr(上)。那么這次呢,我們基于v...

    Jochen 評(píng)論0 收藏0
  • vue服務(wù)端渲染demo將vue-cli生成的項(xiàng)目轉(zhuǎn)為ssr

    摘要:無(wú)需使用服務(wù)器實(shí)時(shí)動(dòng)態(tài)編譯,而是使用預(yù)渲染方式,在構(gòu)建時(shí)簡(jiǎn)單地生成針對(duì)特定路由的靜態(tài)文件。與可以部署在任何靜態(tài)文件服務(wù)器上的完全靜態(tài)單頁(yè)面應(yīng)用程序不同,服務(wù)器渲染應(yīng)用程序,需要處于運(yùn)行環(huán)境。更多的服務(wù)器端負(fù)載。 目錄結(jié)構(gòu) -no-ssr-demo 未做ssr之前的項(xiàng)目代碼用于對(duì)比 -vuecli2ssr 將vuecli生成的項(xiàng)目轉(zhuǎn)為ssr -prerender-demo 使用prer...

    whinc 評(píng)論0 收藏0
  • 用vue搭建的個(gè)人博客介紹----mapblog小站

    摘要:后端主要使用的框架,數(shù)據(jù)庫(kù)采用。后臺(tái)管理登錄采用與后端進(jìn)行登陸狀態(tài)的確認(rèn)。本文首發(fā)于小站,這是一個(gè)積累和分享知識(shí)的個(gè)人博客 這篇文章擱置了很長(zhǎng)時(shí)間,最終決定還是把它寫出來(lái),給剛開(kāi)始學(xué)習(xí)vue并且想用vue寫個(gè)人博客的同學(xué)一個(gè)參考。因?yàn)楫?dāng)初我也是參考了其他人分享的知識(shí),從一個(gè)vue小白變成了一個(gè)入門級(jí)選手,并最終完成了這個(gè)個(gè)人博客的搭建工作,代碼已托管在Github-justJokee。...

    Ashin 評(píng)論0 收藏0
  • 每個(gè)前端猿都有一個(gè)開(kāi)發(fā)屬于自己技術(shù)博客的心

    摘要:總算是今天成功把自己的孩子托付到阿里云的服務(wù)器上面了。中間還遇到很多很多坑最后看這自己所部署的三個(gè)網(wǎng)站安靜的躺在自己租的阿里云上。 一把桌子,一臺(tái)電腦,一瓶紅牛,一包紙巾,從白天到黑夜。歷經(jīng)一個(gè)多月的時(shí)間,從零到構(gòu)思到設(shè)計(jì),從設(shè)計(jì)到vue-ssr 的框架設(shè)計(jì),然后再?gòu)那岸说臉I(yè)務(wù)邏輯代碼的實(shí)現(xiàn),從 后臺(tái)nodejs 的 koa2框架到數(shù)據(jù)庫(kù)的設(shè)計(jì)到后端的業(yè)務(wù)邏輯的代碼實(shí)現(xiàn),從購(gòu)買阿里云服...

    wslongchen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<