【发布时间】:2020-07-23 16:22:30
【问题描述】:
我一直在密切关注Vue SSR guide,在该示例中,作者已将他的 Express 路由放在名为 server.js 的文件中。仅出于组织目的,我希望将我的 Express 路由保存在我的 src/router 文件夹中的 router.express.js 文件中,而不是 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:配置对象无效。网页包 已使用不匹配的配置对象初始化 API 架构。 - configuration.entry'app' 应该是一个字符串。
如果我从server.js 中删除vue-server-renderer 代码,那么它运行良好。但是在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;
【问题讨论】:
标签: node.js express vue.js server-side-rendering vue-ssr