如何为每个动态导入的模块创建供应商捆绑包?

时间:2018-10-18 15:38:15

标签: javascript webpack-4 code-splitting dynamic-import

我正在一个具有多个单独页面的基于CMS的网站上工作,并且我将使用一个app.js文件加载后的vendor.js文件将站点范围的功能加载到每个页面上, code splitting策略。 app.js是主条目文件,它使用dynamic imports来加载特定于页面的脚本。这是我的app.js中的一个示例:

/**
 * "Register for a class" page
 */
if (document.body.classList.contains("page-id-4136")) {
    import(/* webpackChunkName: "register-for-a-class" */ './pages/register-for-a-class/main')
}

在这种情况下,“页面/类的注册/main.js”文件页面使用Vue作为依赖项,但这是该站点上迄今为止唯一需要它的页面。当Vue仅在此页面上使用时,我不希望将其捆绑到vendor.js中。我尝试通过尝试以下操作将Vue本身包括为动态导入:

// pages/register-for-a-class/main.js

import(/* webpackChunkName: "vue" */ 'vue').then(({ default: Vue }) => {
  new Vue({
    ...
  })
})

但是,这给了我一个Module parse failed: 'import' and 'export' may only appear at the top level的Webpack捆绑错误。所以我也尝试了这个:

// app.js

/**
 * "Register for a class" page
 */
if (document.body.classList.contains("page-id-4136")) {
    import(/* webpackChunkName: "vue" */ 'vue').then(({ default: Vue }) => {
        import(/* webpackChunkName: "register-for-a-class" */ './pages/register-for-a-class/main')
    })
}

一切顺利并不会改变任何事情。没有创建“ vue.bundle.js”文件,自然地,加载页面会产生Vue is not defined错误。

所以这就是我真正要问的问题。绝对妙不可言的是,如果我可以自动将pages/register-for-a-class/main.js仅调用正常的静态导入(例如import Vue from 'vue')并让webpack生成register-for-a-class.bundle.js文件和相应的register-for-a-class-vendor.bundle.js并自动动态导入该供应商捆绑包。可能吗?

这是我当前的webpack.common.js文件(我正在使用webpack-merge):

const path = require('path')
const webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const devMode = process.env.NODE_ENV === 'development'

module.exports = {
    entry: {
        app: './assets/src/app.js'
    },
    resolve: {
        alias: {
            '~': path.resolve(__dirname, 'assets/src')
        }
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader
                    },
                    'css-loader',
                    'postcss-loader',
                    'sass-loader'
                ]
            },
            {
                test: /\.css$/,
                use: [
                    'vue-style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.(woff2?|ttf|eot|svg)$/,
                use: ['url-loader']
            }
        ]
    },
    optimization: {
        runtimeChunk: 'single',
        splitChunks: {
            cacheGroups: {
                commons: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendor',
                    chunks: 'all'
                }
            }
        }
    },
    externals: {
        jquery: 'jQuery'
    },
    plugins: [
        new VueLoaderPlugin()
    ]
}

1 个答案:

答案 0 :(得分:0)

我将推荐以下分割方法。希望这会有所帮助:)

ng serve