日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

java vue 服务端渲染_vue ssr服务端渲染小白解惑

發布時間:2023/12/20 vue 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java vue 服务端渲染_vue ssr服务端渲染小白解惑 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

vue ssr服務端渲染小白解惑

>初學ssr入坑

初學vue服務端渲染疑惑非常多,我們大部分前端都是半路出家,上手都是前后端分離,對服務端并不了解,不說java、php語言了,連node服務都還沒搞明白,理解服務端渲染還是有些困難的;

網上有非常多的vue服務渲染的入門案例,但看了很久,很多,還是一頭霧水,搞不明白這些文件和關鍵字的聯系和意思:

server.js

entrt-client.js

server-js

built-server-bundle.js

vue-ssr-server-bundle.json

vue-ssrclientmanifest.json

createBundleRenderer

clientManifest

這篇內容會按照 基礎服務端渲染--vue實例渲染--加入vueRouter--加入vueX的順序入坑,后續應該還有--開發模式--seo優化--部分渲染,這里先不挖那么多坑了;

>基礎服務端渲染

顧名思義,得啟個服務:(建個新項目,不要用vue-cli)

//server.js

const express = require('express');

const chalk = require('chalk');//加個chalk就是console好看點。。

const server = express();

server.get('*', (req, res) => {

res.set('content-type', "text/html");

res.end(`

Hello

`)

})

server.listen(8080,function(){

let ip = getIPAdress();

console.log(`服務器開在:http://${chalk.green(ip)}:${chalk.yellow(8080)}`)

})

function getIPAdress(){//node下的os模塊可以拿到啟動該文件的服務端的部分信息

var interfaces = require('os').networkInterfaces();

for (var devName in interfaces) {

var iface = interfaces[devName];

for (var i = 0; i < iface.length; i++) {

var alias = iface[i];

if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {

return alias.address;

}

}

}

}

啟動 node server.js

再看頁面 正常,這就是最基礎的服務端渲染

其實就是一個get請求,返回一個字符串,瀏覽器默認展示返回結果;

然而對于這個字符串的解析還不明確,什么意思,比如:

去掉這句話,頁面就成了這樣,原因不深究,自己百度

>加入vue實例

跳過官網說的built-server-bundle.js應用,意思就是不用管這個文件了,只是一個過渡文件,項目中也不會用到。直接使用createBundleRenderer方法,直接用vue-ssr-server-bundle.json;

看下現在的目錄結構:

新增了5個文件;有關客戶端的配置entry-client.js不是必須的,這里先不管;

app.js是用來創建vue實例的;

entry-server.js是用來創建生成vue-ssr-server-bundle.json(需要用到app.js)所需的配置配件;是給webpack.server.config.js用的;

webpack.server.config.js是用來生成vue-ssr-server-bundle.json的;

vue-ssr-server-bundle.json是給server.js中的createBundleRenderer用的。

//app.js

import Vue from 'vue'

import Vue from './App.vue'//這里一定要寫上.vue,不然會匹配到app.js,require不區分大小寫0.0

export default createApp=function(){

return new Vue({

render:h => h(App)

})

}

一個createApp生成一個vue實例;

//App.vue

這是個app

export default {}

還沒用到

//weback-base.config.js

const path = require('path')

const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {

output:{

path:path.resolve(__dirname,'./dist'),

filename:'build.js',

},

module: {

rules: [

{

test:/\.js$/,

use: {

loader: 'babel-loader',

options: {

presets: ['@babel/preset-env']

}

},

exclude:[/node_modules/,/assets/]

},

{

test:/\.vue$/,

use:['vue-loader']

}

]

},

resolve: {

alias:{

'@':path.resolve(__dirname,'../')

},

extensions:['.js','.vue','.json']

},

plugins:[

new VueLoaderPlugin()

]

}

有關webpack配置不啰嗦

//webpack.server.config.js用來生成vue-ssr-server-bundle.json

const merge = require('webpack-merge')

const baseConfig = require('./webpack.base.js')

const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

module.exports = merge(baseConfig, {

entry: './entry-server.js',

// 這允許 webpack 以 Node 適用方式(Node-appropriate fashion)處理動態導入(dynamic import),

// 并且還會在編譯 Vue 組件時,

// 告知 `vue-loader` 輸送面向服務器代碼(server-oriented code)。

target: 'node',

// 對 bundle renderer 提供 source map 支持

devtool: 'source-map',

// 此處告知 server bundle 使用 Node 風格導出模塊(Node-style exports)

output: {

libraryTarget: 'commonjs2'

},

// 這是將服務器的整個輸出

// 構建為單個 JSON 文件的插件。

// 默認文件名為 `vue-ssr-server-bundle.json`

plugins: [

new VueSSRServerPlugin()

]

})

這個配置哪都能找到,重點是VueSSRServerPlugin這個插件,生成vue-ssr-server-bundle.json全靠它,去掉的話生成的是built-server-bundle.js;關于merge插件,libraryTarget,target配置問題自己百度webpack去0.0;

//entry-server.js

import { createApp } from './src/app'

export default context => {

return createApp()

}

固定寫法,返回一個函數供createBundleRenderer使用;

生成vue-ssr-server-bundle.json

到目前為止安裝的插件有:

自己手動一個一個裝就行了。

生成vue-ssr-server-bundle.json,使用webpack命令

一切都手動,熟悉webpack;

修改server.js

const express = require('express');

const chalk = require('chalk');

const server = express();

const serverBundle = require('./dist/vue-ssr-server-bundle.json')//**新增**//

const renderer = require('vue-server-renderer').createBundleRenderer(serverBundle,{

runInNewContext: false, // 看名字也知道是生成某個新的Context對象,默認是true,改成false理解為某種緩存機制,提高服務器效率

template: require('fs').readFileSync('./index.html', 'utf-8'),

})//**新增**//

server.get('*', (req, res) => {

//res.set('content-type', "text/html");

//res.end(`

//

//

//

Hello

//

//

你好

//

//

//改成下面這樣

const context = {//這里的參數現在還沒用,但這個對象還是得用,要做renderToString的參數

url:req.url

}

renderer.renderToString(context, (err, html) => {

if (err) {

res.status(500).end('Internal Server Error')

return

} else {

res.end(html)

}

})

`)

})

server.listen(8080,function(){

let ip = getIPAdress();

console.log(`服務器開在:http://${chalk.green(ip)}:${chalk.yellow(8080)}`)

})

function getIPAdress(){//node下的os模塊可以拿到啟動該文件的服務端的部分信息,細節自己去node上面查

var interfaces = require('os').networkInterfaces();

for (var devName in interfaces) {

var iface = interfaces[devName];

for (var i = 0; i < iface.length; i++) {

var alias = iface[i];

if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {

return alias.address;

}

}

}

}

試一蛤:node server.js

正常,箭頭指的地方官網有解釋。別忘了inde.html中加入一行注釋:

后續修改title,meta頭部都是通過類似的注釋方式,原理就是正則匹配替換字符串-。-;

>加入路由vue-router

新增幾個文件

需要修改的文件有:

App.vue//加個router-view就行

//app.js

import Vue from 'vue'

import App from './App.vue'

import router from './router'

export function createApp(){

const app = new Vue({

router,

render:h => h(App)

})

return {app,router}

}

把app實例和router都拋出去,給entry-server.js用

// entry-server.js

import { createApp } from './src/app'

export default context => {

//這里用promise的原因有很多,其中有一個就是下面這個onReady方法是異步的。createBundleRenderer支持promise

return new Promise((resolve, reject) => {

const { app, router } = createApp()

router.push(context.url)

router.onReady(() => {//onReady方法還有getMatchedComponents方法還是需要了解一下

const matchedComponents = router.getMatchedComponents()

if (!matchedComponents.length) {

return reject({ code: 404 })

}

resolve(app)

}, reject)

})

}

最后看一下router.js

//router.js

import Vue from 'vue'

import VueRouter from 'vue-router'

//頁面要先聲明后使用,不要問為什么

import home from './pages/home'

import store from './pages/store'

Vue.use(VueRouter)

export default new VueRouter({

mode: 'history',

routes:[

{path:'/',name:'home',component:home},

{path:'/store',name:'store',component:store},

]

})

再看一下兩個頁面的代碼;

//store.vue

this is store

export default {}

改的差不多了,試一哈:

重新打個包webpack --config webpack.server.js

啟動node server

>entry-client.js是干啥的

到目前為止還沒用到entry-client.js叫客戶端配置,不著急使用,先做個測試,寫點邏輯試試:

修改下store.vue

//store.vue

{{msg}}

export default {

data(){

msg:'this is store'

},

created(){

this.msg = 'this is created'

},

mounted(){

this.msg = 'this is mounted'

},

methods: {

run(){

alert('this is methods')

}

}

}

看這個樣子頁面最終展示的結果應該是this is mounted,然而結果是這樣的:

很好解釋,服務端對于鉤子函數的理解也是很正確的,created會在頁面返回之前執行,而mounted是在vue實例成型之后執行,就是頁面渲染后,這個是要在客戶端才會執行,可是為什么頁面出來了沒有執行mounted,而且run的點擊事件沒有生效;

看看頁面:

一個js文件都沒加載,怎么執行邏輯,就是個靜態頁面0.0;

這時候entry-client.js就出場了

新增兩個文件

//entry-client.js

import { createApp } from './src/app.js';

const { app } = createApp();

app.$mount('#app');

基本配置;

//webpack.client.config.js

const merge = require('webpack-merge')

const baseConfig = require('./webpack.base.config.js')

const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')

module.exports = merge(baseConfig, {

entry: './entry-client.js',

optimization:{

runtimeChunk:true

},

plugins: [

// 此插件在輸出目錄中

// 生成 `vue-ssr-client-manifest.json`。

new VueSSRClientPlugin(),

]

})

這個地方重點除了VueSSRClientPlugin生成vue-ssr-client-manifest.json外,optimization是webpack4產物,用來分離生成共公chunk,配置還算復雜,可以看下這里webpack4 optimization總結

修改下server.js

//server.js

const express = require('express');

const chalk = require('chalk');

const server = express();

const serverBundle = require('./dist/vue-ssr-server-bundle.json')

const clientManifest = require('./dist/vue-ssr-client-manifest.json')//新增

const renderer = require('vue-server-renderer').createBundleRenderer(serverBundle,{

runInNewContext: false, // 推薦

template: require('fs').readFileSync('./index.html', 'utf-8'),

clientManifest // //新增

})

server.get('*', (req, res) => {

res.set('content-type', "text/html");

const context = {

url:req.url

}

renderer.renderToString(context, (err, html) => {

if (err) {

res.status(500).end('Internal Server Error')

return

} else {

res.end(html)

}

})

})

server.listen(8080,function(){

let ip = getIPAdress();

console.log(`服務器開在:http://${chalk.green(ip)}:${chalk.yellow(8080)}`)

})

function getIPAdress(){//node下的os模塊可以拿到啟動該文件的服務端的部分信息,細節自己去node上面查

var interfaces = require('os').networkInterfaces();

for (var devName in interfaces) {

var iface = interfaces[devName];

for (var i = 0; i < iface.length; i++) {

var alias = iface[i];

if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {

return alias.address;

}

}

}

}

打包下:webpack --config webpack.client.config.js

node server 一下,看看頁面

js有了,可是為什么還不行,不能點0.0;

看看。奧報錯了

讀取不到靜態文件;

修改server.js加個靜態文件托管:

再看看

事件也有了,頁面沒變化,console一下,發現值其實已經變了,

看看代碼,是這里忘加return了;

>加入vuex

加個sotre.js

// store.js

import Vue from 'vue'

import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({

state: {

msg: ''

},

actions: {

setMsg ({ commit }, val) {

commit('setMsg', val)

}

},

mutations: {

setMsg (state, val) {

Vue.set(state, 'msg', val)//關鍵

}

}

})

很基礎的邏輯,關鍵在Vue.set這個方法,增加響應式;

修改下app.js

//app.js

import Vue from 'vue'

import App from './App.vue'

import router from './router'

import store from './store'//加個store就行了

export function createApp(){

const app = new Vue({

router,

store,

render:h => h(App)

})

return {app,router}

}

store.vue改成這樣

{{msg}}

export default {

data(){},

created(){

this.$store.dispatch('setMsg','this is created')

},

computed:{

msg(){

return this.$store.state.msg;

}

},

mounted(){

this.$store.dispatch('setMsg','this is mounted')

},

methods: {

run(){

alert('this is methods')

}

}

}

重新打個包,想一下,修改頁面的話只需要重新打包client,如果修改了app.js兩個就要都重新打包了;

node server 一下

這回總算完成了;

>總結

服務端渲染東西還是挺多的,涉及領域也非常廣,比如vue,webpack,node,它們的生態圈都大的可怕,需要學習東西非常多,

坑又多,又大,又深,后面還有很多問題要解決:

異步數據加載;//html返回前先渲染一部分接口拿到的數據

怎么做seo優化;//做服務端渲染的重要原因,處理異步數據加載問題也是為了這個

緩存怎么加;

開發環境搭建;//你并不希望每改一行代碼就重新手動打個包,重啟下服務吧0.0

還有怎么實現部分頁面ssr;//一個項目不可能所有頁面都服務端渲染,太耗性能,服務器壓力大呀;

總結

以上是生活随笔為你收集整理的java vue 服务端渲染_vue ssr服务端渲染小白解惑的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。