Я очень старался следовать этому Vue руководству по SSR , и в этом примере автор поместил свои маршруты Express в файл с именем server.js
. Просто для организационных целей я sh сохраню свои маршруты Express в файле router.express.js
в папке src/router
, а не в файле root server.js
.
это урезанная версия моего router.express.js
файла:
const vueServerRenderer = require('vue-server-renderer');
const setupDevServer = require('../../build/setup-dev-server'); //webpack dev config
const express = require('express');
const app = express();
const router = express.Router();
const createRenderer = (serverBundle) =>
vueServerRenderer.createBundleRenderer(serverBundle, {
runInNewContext: false,
template: fs.readFileSync(path.resolve(__dirname, '../index.html'), 'utf-8')
});
let renderer;
if (process.env.NODE_ENV === 'development') {
setupDevServer(app, (serverBundle) => {
renderer = createRenderer(serverBundle);
});
} else {
renderer = createRenderer(require('../../dist/vue-ssr-server-bundle.json'));
}
router.get('/', async function (req, res) {
const context = {
url: req.params['0'] || '/'
};
let html;
try {
html = await renderer.renderToString(context);
} catch (error) {
if (error.code === 404) {
return res.status(404).send('404 | Page Not Found');
}
return res.status(500).send('500 | Internal Server Error');
}
res.end(html);
});
module.exports = router;
Проблема в том, что мне также нужен код vue-server-renderer
, который должен быть в файле server.js
. Затем я сделал бы приложение require
файлом router.express.js
, чтобы маршруты Express работали так:
const vueServerRenderer = require('vue-server-renderer');
const setupDevServer = require('../../build/setup-dev-server'); //webpack dev config
const app = express();
const createRenderer = (serverBundle) =>
vueServerRenderer.createBundleRenderer(serverBundle, {
runInNewContext: false,
template: fs.readFileSync(path.resolve(__dirname, '../index.html'), 'utf-8')
});
let renderer;
if (process.env.NODE_ENV === 'development') {
setupDevServer(app, (serverBundle) => {
renderer = createRenderer(serverBundle);
});
} else {
renderer = createRenderer(require('../../dist/vue-ssr-server-bundle.json'));
}
app.use(require('./router/express.router.js'));
Всякий раз, когда я делаю это, я получаю сообщение об ошибке Webpack, в котором говорится, что
WebpackOptionsValidationError: Неверный объект конфигурации. Webpack был инициализирован с использованием объекта конфигурации, который не соответствует схеме API. - configuration.entry 'app' должно быть строкой.
Если я удаляю код vue-server-renderer
из server.js
, он работает нормально. Но причина наличия этого кода в server.js
заключается в том, что среда разработки работает правильно. В основном, если код не в server.js
, я не могу использовать горячую перезагрузку или что-то еще.
Если я избавлюсь от router.express.js
и вставлю весь этот код в server.js
, включая маршруты, то все будет отлично работать, в том числе и в моей среде разработки.
Почему я не могу (или скорее как я могу) хранить мои Express маршруты в отдельном файле и при этом работать с vue-server-renderer
?
Обновление: setup-dev-server.js
файл:
const setupDevServer = (app, onServerBundleReady) => {
const webpack = require('webpack');
const MFS = require('memory-fs');
const path = require('path');
const clientConfig = require('./webpack.client.config');
const serverConfig = require('./webpack.ssr.config');
// additional client entry for hot reload
clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app];
const clientCompiler = webpack(clientConfig);
// setup dev middleware
app.use(require('webpack-dev-middleware')(clientCompiler, {
publicPath: clientConfig.output.publicPath,
serverSideRender: true,
logLevel: 'silent',
}));
// setup hot middleware
app.use(require('webpack-hot-middleware')(clientCompiler));
// watch src files and rebuild SSR bundle
global.console.log('Building SSR bundle...');
const serverCompiler = webpack(serverConfig);
const mfs = new MFS();
serverCompiler.outputFileSystem = mfs;
serverCompiler.watch({}, (error, stats) => {
if (error) throw error;
global.console.log(
`${stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false,
})}\n\n`
);
if (stats.hasErrors()) {
console.error(stats.compilation.errors);
throw new Error(stats.compilation.errors);
}
// read bundle generated by vue-ssr-webpack-plugin
const bundle = JSON.parse(
mfs.readFileSync(path.join(clientConfig.output.path, 'vue-ssr-server-bundle.json'), 'utf-8')
);
onServerBundleReady(bundle);
});
};
module.exports = setupDevServer;