2

我正在尝试使用 webpack 设置自己的快速服务器以使用热模块替换和服务器端渲染。webpack-hot-server-middleware除了集成需要一个带有参数的快速中间件功能外,一切似乎都有效(res, req, next)- 但我无法弄清楚如何正确实现它。

这是我到目前为止的配置:

webpack.config.js

const webpack = require('webpack');
const path = require('path');

const config = [{
    name: 'client',
    entry: [
        'webpack-hot-middleware/client',
        './src/js/entry_client.js'
    ],
    output: {
        path: path.resolve(__dirname, 'dist/js/'),
        filename: 'app.js'
    },
    module: {
        rules: [{
            test: /\.vue$/,
            loader: 'vue-loader'
        }, {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader'
        }]
    },
    resolve: {
        alias: {
            vue$: 'vue/dist/vue.runtime.js'
        }
    }
}, {
    name: 'server',
    target: 'node',
    entry: './src/js/entry_server.js',
    output: {
        path: path.resolve(__dirname, 'dist/js/'),
        filename: 'app.server.js',
        libraryTarget: 'commonjs2'
    },
    externals: require('webpack-node-externals')(),
    module: {
        rules: [{
            test: /\.vue$/,
            loader: 'vue-loader'
        }]
    },
    resolve: {
        alias: {
            vue$: 'vue/dist/vue.runtime.js',
        }
    }
}];

if (process.env.NODE_ENV !== 'production') {
    config[0].plugins = [new webpack.HotModuleReplacementPlugin()];
}

module.exports = config;

entry_client.js

import {createApp} from './app';

const {app, router} = createApp();
router.onReady(() => {
    app.$mount('#app');
});

entry_server.js

import {createApp} from './app';

export default context => {
    return new Promise((resolve, reject) => {
        const {app, router} = createApp();

        router.push(context.url);
        router.onReady(() => {
            if (!router.getMatchedComponents().length) return reject({code: 404});
            resolve(app);
        }, reject);
    });
};

应用程序.js

import Vue from 'vue';
import App from '../vue/app.vue';
import {createRouter} from './router';

export function createApp() {
    const router = createRouter();

    const app = new Vue({
        router,
        render: h => h(App)
    });

    return {app, router};
}

路由器.js

import Vue from 'vue';
import Router from 'vue-router';
import Home from '../vue/home.vue';
import About from '../vue/about.vue';

Vue.use(Router);

export function createRouter() {
    return new Router({
        mode: 'history',
        routes: [{
            path: '/',
            component: Home
        }, {
            path: '/about',
            component: About
        }]
    });
}

服务器.js

const express = require('express');
const fs = require('fs');
const path = require('path');
const bundle = require('./dist/js/app.server');
const renderer = require('vue-server-renderer').createRenderer({
    template: fs.readFileSync('./src/html/index.html', 'utf-8')
});

const server = express();

// add vue HMR middleware
if (process.env.NODE_ENV !== 'production') {
    const webpack = require('webpack');
    const compiler = webpack(require('./webpack.config'));

    server.use(require('webpack-dev-middleware')(compiler, {
        noInfo: true,
        serverSideRender: true
    }));
    server.use(require('webpack-hot-middleware')(compiler.compilers.find(compiler => compiler.name === 'client')));
//  server.use(require('webpack-hot-server-middleware')(compiler));
} else {
    // static file serving
    server.use(require('serve-favicon')(path.join(__dirname, 'src/png/favicon-32x32.png')));
    server.use(express.static(path.join(__dirname, 'dist/'), {index: false}));
}

server.get('*', (req, res) => {
    bundle.default({url: req.url}).then(app => {
        renderer.renderToString(app, {
            title: 'Some title',
            description: 'Some description'
        }, (err, html) => {
            if (err) {
                console.error('Error in renderToString:', err);
                return res.status(500).send('Internal Server Error');
            }
            res.send(html);
        });
    }, err => {
        if (err.code === 404) return res.status(404).send('Page not found');
        console.error(err);
        return res.status(500).send('Internal Server Error');
    });
});

server.listen(4040);
4

0 回答 0