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



我正在开发一个基于 CMS 的网站,其中包含多个单独的页面,我使用在vendor.js文件之后加载的app.js文件将站点范围的功能加载到每个页面上使用通常的代码拆分策略。app.js是主入口文件,它使用动态导入来加载特定于页面的脚本。这是我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')
}

在这种情况下,"pages/register-for-a-class/main.js"文件页面使用 Vue 作为依赖项,但它是迄今为止站点上唯一需要它的页面。我宁愿不将 Vue 捆绑到vendor.js中,因为它只在这个页面上使用。我试图通过尝试以下内容将 Vue 本身作为动态导入包含在内:

// pages/register-for-a-class/main.js
import(/* webpackChunkName: "vue" */ 'vue').then(({ default: Vue }) => {
new Vue({
...
})
})

但这给了我在 webpack 捆绑中的一个错误,上面写着Module parse failed: 'import' and 'export' may only appear at the top level.所以我也尝试了这个:

// 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()
]
}

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

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: {
vendor1: ['vendor1', 'vendor2', 'vendor 3'], // all other vendor lists, package.json dependencies 
vendor2: ['vue'],
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: {
vendor1: {
name: 'vendor1',
test: 'vendor1',
enforce: true
},
vendor2: {
name: 'vendor2',
test: 'vendor2',
enforce: true
}
}
}
},
externals: {
jquery: 'jQuery'
},
plugins: [new VueLoaderPlugin()]
};

最新更新