Как я могу отделить Express маршруты от сервера. js? - PullRequest
0 голосов
/ 10 апреля 2020

Я очень старался следовать этому 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;

1 Ответ

1 голос
/ 11 апреля 2020

1) Внутри вашего файла 'router. express. js' пишите: module.exports = router; внизу файла.

2) Внутри вашего сервера. js ' запись в файл: const router = require('./router/express.router.js'); в верхней части файла.

3) А теперь, где у вас было app.use(require('./router/express.router.js'));, замените это на app.use(router);

4) В верхней части ' сервер. js 'запись const vueSsrBundle = require('../../dist/vue-ssr-server-bundle.json')

5) Наконец замените renderer = createRenderer(require('../../dist/vue-ssr-server-bundle.json') на renderer = createRenderer(vueSsrBundle)

РЕДАКТИРОВАТЬ проблему, с которой вы сталкиваетесь в этой строке И вероятно, связано с файлом 'app. js' или 'client-entry- js'

...