【发布时间】:2023-12-08 16:01:02
【问题描述】:
我使用 Vue CLI 创建了一个 Vue3 应用程序,以使用 Vuex 和路由器创建我的应用程序。应用程序运行良好。
注意:我在 Vue3 https://blog.logrocket.com/using-vuex-4-with-vue-3/987654321@
要求现在我想更改我的 Vue3 应用程序以支持服务器端渲染(即 SSR)。
我观看了关于使用 Vue3 创建 SSR 应用程序的精彩视频:https://www.youtube.com/watch?v=XJfaAkvLXyU,我可以创建和运行视频中的简单应用程序。但是,当我尝试将它应用到我的主 Vue3 应用程序时,我被卡住了。
我目前的症结是如何在服务器代码上指定路由器和vuex。
我的代码
客户端入口文件(src/main.js)有以下内容
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
createApp(App).use(store).use(router).mount('#app');
服务器入口文件(src/main.server.js)目前有以下内容
import App from './App.vue';
export default App;
并且在它当前拥有的快速服务器文件 (src/server.js) 中
const path = require('path');
const express = require('express');
const { createSSRApp } = require('vue');
const { renderToString } = require('@vue/server-renderer');
...
...
server.get('*', async (req, res) => {
const app = createSSRApp(App);
const appContent = await renderToString(app);
我需要更改此代码,以便服务器端的应用程序像在客户端上一样使用路由器和 vuex。
问题
在快速服务器文件中,我无法像在客户端条目文件中那样导入路由器和 vuex,因为它由于在模块外部导入而失败,因此在快速服务器中我无法执行以下操作
const app = createSSRApp(App).use(store).use(router);
我尝试将服务器入口文件(src/main.server.js)更改为以下内容,但这也不起作用。
import App from './App.vue';
import router from './router';
import store from './store';
const { createSSRApp } = require('vue');
export default createSSRApp(App).use(store).use(router);
当您的应用使用 Vuex 和 Router 时,有谁知道如何在 Vue 3 中进行 SSR。
我是如何在 Vue 2 中做到这一点的,以及我想要转换到 Vue 3 的方式
我的这个应用程序的 Vue2 版本有以下代码
src/app.js 使用指定的路由和存储创建 Vue 组件
客户端入口文件 (src/client/main.js) 从 app.js 获取应用程序,使用 html 中序列化的数据预填充 Vuex 存储,在路由器准备好时挂载应用程序
import Vue from 'vue';
import { sync } from 'vuex-router-sync';
import App from './pages/App.vue';
import createStore from './vuex/store';
import createRouter from './pages/router';
export default function createApp() {
const store = createStore();
const router = createRouter();
sync(store, router);
const app = new Vue({
router,
store,
render: (h) => h(App),
});
return { app, router, store };
}
服务器入口文件 (src/server/main.js),从 app.js 获取应用程序,获取匹配的路由,该路由将在每个组件上调用“serverPrefetch”以将其数据填充到 Vuex 存储中,然后返回解决承诺
import createApp from '../app';
export default (context) => new Promise((resolve, reject) => {
const { app, router, store } = createApp();
router.push(context.url);
router.onReady(() => {
const matchedComponents = router.getMatchedComponents();
if (!matchedComponents.length) {
return reject(new Error('404'));
}
context.rendered = () => {
context.state = store.state;
};
return resolve(app);
}, reject);
});
Express 服务器 (/server.js) 使用捆绑渲染器将应用程序渲染为一个字符串以放入 html
const fs = require('fs');
const express = require('express');
const { createBundleRenderer } = require('vue-server-renderer');
const dotenv = require('dotenv');
dotenv.config();
const bundleRenderer = createBundleRenderer(
require('./dist/vue-ssr-server-bundle.json'),
{
template: fs.readFileSync('./index.html', 'utf-8'),
},
);
const server = express();
server.use(express.static('public'));
server.get('*', (req, res) => {
const context = {
url: req.url,
clientBundle: `client-bundle.js`,
};
bundleRenderer.renderToString(context, (err, html) => {
if (err) {
if (err.code === 404) {
res.status(404).end('Page not found');
} else {
res.status(500).end('Internal Server Error');
}
} else {
res.end(html);
}
});
});
const port = process.env.PORT || 3000
server.listen(port, () => {
console.log(`Listening on port ${port}`);
});
【问题讨论】: