1

我有一个标准的文件夹结构,有点像这样:

.
├── dist
|   ├── vendor.js
|   └── app.js              
|   └── index.html   
├── src
|   └── index.html
|   └── entry.js            // main app entry file
|   └── entry-client.js     // for client hydration
|   └── entry-server.js     // for server-side rendering
|   └── server.js
├── package.json

整个dist文件夹由 webpack 构建,包括index.html刚刚从文件夹中复制的src文件。当我想在开发环境中运行时,该文件index.html需要客户端水合才能工作。如果它们不存在,那么只有服务器端呈现的页面会通过。这样做的问题是,如果不在每次文件更改时完全重建文件夹,我就无法进行任何开发工作,这需要很长时间,而且是一种完全低效的开发方式。/dist/app.js/dist/vendor.jsdist

我的 webpack 客户端构建配置是这样的:

const webpack = require('webpack');
const merge = require('webpack-merge');
const MiniCssExtractPlugin  = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const utils = require('./utils') // just resolves directories/files paths

const baseConfig = require('./webpack.base.config');
const isProduction = process.env.NODE_ENV === 'production';

module.exports = merge(baseConfig, {
    entry: {
        app: utils.resolve('/src/entry-client.js')
    },
    output: {
        path: utils.resolve('/dist'),
        filename: '[name].js',                   // generates app.js in ./dist folder
        sourceMapFilename: '[name].js.map', 
    },
    resolve: {
        extensions: ['.js', '.vue'],
    },
    optimization: {
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
        splitChunks: {
            cacheGroups: {
                commons: {
                    test: /[\\/]node_modules[\\/]/,
                    name: "vendor",                 // generates vendor.js file in ./dist
                    chunks: "all",
                },
            },
        },
    },
    module: {
        rules: [
            {
                test: /\.css?$/,
                use: [
                  {
                    loader: MiniCssExtractPlugin.loader,
                    options: {
                        sourceMap: !isProduction,
                        // only enable hot in development
                        hmr: !isProduction,
                        // if hmr does not work, this is a forceful method.
                        reloadAll: true,
                    },
                  },
                  'css-loader',
                ]
              },

    plugins:
        (isProduction ?
        [
            new MiniCssExtractPlugin({
                filename: 'assets/css/site.css', 
            }),
        ] : [
            new MiniCssExtractPlugin({
                filename: 'assets/css/site.css',
                hmr: true,
            }),
            new webpack.HotModuleReplacementPlugin(),
        ]
    )
});

以上仅在我执行时运行npm run build:client。我的开发设置是这样的:

/**
 * Setup webpack-dev-middleware and webpack-hot-middleware.
 * Rebuild SSR bundle on src files change.
 * 
 * @param {Object} app Express application 
 * @param {Function} onServerBundleReady Callback
 */
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;

上面的配置永远不会在更改任何其他文件时setup-dev-server.js重建文件夹中的app.jsvendor.js文件,这意味着开发模式毫无意义。./dist我该如何解决这个问题,以便Home.vue对例如的任何更改都会触发重新创建,app.js因此vendor.js我的更新实际上可以工作?

4

0 回答 0