Vue SSR中的Bundle是指打包包含服务端和客户端代码的文件,在服务器端生成HTML时将其注入页面中并携带客户端代码。这样做的好处在于针对不同的用户使用不同的请求路径,服务端就可以通过Bundle调用不同的组件,从而生成相应的HTML页面,提升页面的渲染速度和用户体验。
具体步骤如下:
1. 安装依赖
npm install --save vue vue-server-renderer express axios
其中,vue
和vue-server-renderer
是Vue SSR所必需的依赖。
2. 创建组件
假设我们创建了一个名为App.vue
的根组件。该组件中需要包含一些服务端渲染所需的特殊属性,如data
方法、asyncData
方法和template
属性等。这里不再赘述,可以查看Vue SSR官方文档。
3. 创建入口文件
在入口文件中,会将服务端bundle和客户端bundle合并生成一个文件。服务端 bundle 将在服务器端执行,客户端 bundle 将在浏览器中执行。例如,以下是一个 entry-server.js
文件:
import createApp from './app.js'
export default context => {
return new Promise(async (resolve, reject) => {
const { app, router, store } = createApp(context)
router.push(context.url)
router.onReady(() => {
const matchedComopnents = router.getMatchedComponents()
if (!matchedComopnents.length) {
return reject({ code: 404 })
}
Promise.all(matchedComopnents.map(Component => {
if (Component.asyncData) {
return Component.asyncData({
store,
route: router.currentRoute
})
}
})).then(() => {
context.state = store.state
resolve(app)
}).catch(reject)
}, reject)
})
}
4. 创建客户端入口文件
在客户端入口文件中,需要调用 createApp
方法来初始化 Vue 实例,并使用 hydrate
方法来将服务端生成的 HTML 进行激活,将 Vue 实例挂载到 DOM 中。以下是一个示例:
import Vue from 'vue'
import createApp from './app'
Vue.config.productionTip = false
const { app, router, store } = createApp()
if (window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__)
}
router.onReady(() => {
app.$mount('#app')
})
5. 创建服务端模板
在生成服务端HTML时,我们需要使用一个模板文件。该文件需要包含预先定义好的根元素,该元素将作为 Vue 实例挂载的目标。文件内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{{{ meta }}}
</head>
<body>
{{ APP }}
{{{ state }}}
{{{ style }}}
{{{script }}}
</body>
</html>
在模板文件中,我们使用双花括号和3个大括号来插入数据。其中,{{ }}
表示对应的变量需要进行HTML转码;而{{{ }}}
则表示对应的变量不需要进行HTML转码。
6. 服务器端设置
我们需要在服务器端设置路由响应,并根据路由响应生成HTML。以下是一个使用Express的示例:
import express from 'express'
import Vue from 'vue'
import serverRenderer from 'vue-server-renderer'
import fs from 'fs'
import path from 'path'
const app = express()
const serverBundlePath = '../dist/server.bundle.js'
const clientManifestPath = '../dist/client-manifest.json'
const serverBundle = require(serverBundlePath)
const clientManifest = require(clientManifestPath)
const template = fs.readFileSync(path.resolve(__dirname, '../dist/index.html'), 'utf-8')
const renderer = serverRenderer.createBundleRenderer(serverBundle, {
clientManifest,
template,
inject: false
})
server.get('*', (req, res) => {
const context = {
title: 'Vue SSR demo',
url: req.url
}
renderer.renderToString(context, (err, html) => {
if (err) {
res.statusCode = 500
res.end('Internal Server Error')
} else {
res.send(html)
}
})
})
server.listen(8080, () => {
console.log(`server stared at http://localhost:8080`)
})
这里,我们读取生成的服务端 bundle,客户端清单,模板以及一些其他配置,然后使用服务端渲染器来生成HTML响应。
以上是一个基于Express的Vue SSR的完整攻略。以下是两个示例分别介绍了客户端加载异步数据和使用Vuetify组件库:
示例1:加载异步数据
在组件中定义一个异步函数,通过使用服务端渲染器的 renderToString
自动调用该方法,获取异步数据,并将其赋值到服务端渲染上下文中。
asyncData ({ store, route }) {
return axios.get('http://some-api.example.com/data').then((res) => {
store.commit('setAsyncData', res.data)
})
}
其中,setAsyncData
为在store中定义的 mutation 函数。
示例2:使用Vuetify组件库
在Vue SSR中使用第三方组件库并不需要有什么特别的代码,只需要将组件库的代码适配到Vue SSR环境下即可。以下是基于Vuetify组件库的示例:
// main.js
import Vue from 'vue'
import createApp from './app'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
Vue.use(Vuetify)
const vuetify = new Vuetify()
const { app, router, store } = createApp()
router.onReady(() => {
app.$mount('#app')
})
具体的Vuetify组件使用方式可以查看Vuetify官方文档。
以上是Vue SSR中Bundle的使用攻略以及两个示例。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Vue SSR中的Bundle的具有使用 - Python技术站