【问题标题】:How can I separate out Express routes from server.js?如何从 server.js 中分离出 Express 路由?
【发布时间】: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


    【解决方案1】:

    1) 在您的“router.express.js”文件中写入:module.exports = router; 在文件底部。

    2) 在“server.js”文件中写入:const router = require('./router/express.router.js'); 在文件的顶部。

    3) 现在你曾经拥有app.use(require('./router/express.router.js')); 将其替换为app.use(router);

    4) 在“server.js”的顶部写const vueSsrBundle = require('../../dist/vue-ssr-server-bundle.json')

    5) 最后替换renderer = createRenderer(require('../../dist/vue-ssr-server-bundle.json')renderer = createRenderer(vueSsrBundle)

    编辑您面临的问题是在这个line 上,可能与文件“app.js”或'client-entry-js'有关

    【讨论】:

    • 你能从名为“setup-dev-server”的文件中获取代码吗?如果该文件的 JSON 对象中有一个名为“app”的值,请检查它是否在引号中。检查我的回答点 5) 以获取更新。
    • 我刚刚更新了我的问题以包含setup-dev-server 的内容。我看不到带有我不认为的应用程序的 JSON 对象? webpack.client.config 将条目显示为像这样的应用程序 entry: { app: utils.resolve('/src/entry-client.js') },
    • 通过推理过程,问题是我不能在server.jsrouter.express.js 中都有setupDevServer(app, (serverBundle) => { renderer = createRenderer(serverBundle); }); } else { renderer = createRenderer(require('../dist/vue-ssr-server-bundle.json')); } 代码 - 它只能在server.js 中。那么我的router.express.js 路由中的html = await renderer.renderToString(context); 将如何工作?或者更确切地说,我怎样才能通过使用server.jsrenderer 而不是它自己的方式让它们工作?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    • 2014-07-18
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    相关资源
    最近更新 更多