我已经使用Vue CLI创建了一个Vue3应用程序,用Vuex和路由创建了我的应用程序.应用程序运行良好.
Note: I followed this useful doc for the Vuex with Vue3 100
Requirement现在,我想将我的Vue3应用程序更改为具有服务器端渲染支持(即SSR).
我观看了这段关于使用Vue3:https://www.youtube.com/watch?v=XJfaAkvLXyU创建SSR应用程序的精彩视频,我可以创建并运行视频中的简单应用程序.然而,当我try 将其应用到我的主Vue3应用程序时,我被卡住了.
我目前的难点是如何在服务器代码上指定路由和vuex.
My Code
客户端条目文件(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;
在express服务器文件(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.
Issues
在express server文件中,我无法在客户端条目文件中导入路由和vuex,因为它由于在模块外部导入而失败,因此在express server中,我无法执行以下操作:
const app = createSSRApp(App).use(store).use(router);
我try 将服务器条目文件(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);
Does anyone know how to do SSR in Vue 3 when your app is using Vuex and Router.
How i did this in Vue 2 is below and what i am trying to change over to Vue 3
此应用程序的Vue2版本包含以下代码
src/app.js使用指定的路由和存储创建Vue组件
客户端条目文件(src/Client/main.js)从应用程序获取应用程序.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)从应用程序获取应用程序.js,获取匹配的路由,该路由将对每个组件调用"serverPrefetch",以在Vuex存储中填充其数据,然后返回解析promise
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(/server.js)使用bundle呈现程序将应用程序呈现为字符串,以放入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}`);
});