簡體   English   中英

未捕獲的類型錯誤:__webpack_require__.r 不是函數

[英]Uncaught TypeError: __webpack_require__.r is not a function

我有一個多條目應用程序,其中在一個網頁中加載了多個條目。 在這里,我收到以下錯誤“未捕獲的類型錯誤: webpack_require .r不是函數”。 我分析了 webpack 構建輸出並得出以下結論。

條目 A 和 B 都需要模塊 C。 A 和 B 的輸出都加載在一頁中。 對於條目 B,webpack 為 C 創建了一個單獨的塊,其中還包含一些其他模塊。 但是對於 B,webpack 將 C 包含在與 B 的輸出相同的文件中。 當從 B 調用模塊 C 時,它使用單獨的塊文件而不是 B 的輸出文件中包含的模塊。

現在的問題是來自單獨塊的模塊 C 正在調用

__webpack_require__.r(__webpack_exports__);

而包含在 B 的輸出文件中的模塊 C 沒有。 在 B webpack 的上下文中,不知何故沒有定義 r。

我在這里看到 2 個問題。

  1. 為什么 webpack 使用來自單獨塊的模塊 C 而不是文件 B 的輸出?
  2. 為什么 r 沒有在文件 B 的輸出中定義?

根據 webpack 的評論,r 是“在導出時定義 __esModule”。 我能否以某種方式強制為給定條目定義 r,因為這可能會解決此錯誤?

我正在使用 webpack 5.28.0

const AssetsPlugin = require('assets-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { VueLoaderPlugin } = require('vue-loader');
const webpack = require('webpack');
const path = require('path');
const packageJson = require("./package.json");

module.exports = {
    entry: {
        'account': './src/apps/account/account.js',
        'admin-dashboard': './src/apps/admin/dashboard.js',
        'admin-statistics': './src/apps/admin/statistics.js',
        'conflicts': './src/apps/conflicts.js',
        'create-useraccount': './src/apps/account/free/create-useraccount.js',
        'confirm-temporary-useraccount': './src/apps/account/free/confirm-temporary-useraccount.js',
        'confirm-useraccount': './src/apps/account/free/confirm-useraccount.js',
        'login': './src/apps/account/login.js',
        'project-issues': './src/apps/project-issues.js',
        'project': './src/apps/project.js',
        'my-settings': './src/apps/my-settings.js',
        'my-space': './src/apps/my-space.js',
        'model': './src/apps/model.js',
        'ifc-property-lists': './src/apps/ifc-property-lists.js',
        'settings': './src/apps/settings.js'
    },
    output: {
        assetModuleFilename: "[name].[contenthash][ext][query]",
        chunkFilename: "[name].[contenthash].js",
        filename: "[name].[contenthash].js",
        publicPath: '/webapp/dist/',
        clean: true
    },
    optimization: {
        minimize: true,
        minimizer: [
            `...`,
            new CssMinimizerPlugin(),
        ],
        splitChunks: {
            chunks: 'all'
        },
        usedExports: true
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: require.resolve("jquery"),
                loader: "expose-loader",
                options: {
                    exposes: [{
                        globalName: "$",
                        override: true
                    }, {
                        globalName: "jQuery",
                        override: true
                    }]
                }
            }, {
                test: /\.vue$/,
                loader: 'vue-loader'
            }, {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader'
                    }, {
                        loader: 'resolve-url-loader',
                        options: {
                            removeCR: true
                        }
                    }, {
                        loader: 'less-loader'
                    }
                ]
            }, {
                test: /\.(sa|sc|c)ss$/,
                use: [
                    MiniCssExtractPlugin.loader, {
                        loader: 'css-loader'
                    }, {
                        loader: 'resolve-url-loader',
                        options: {
                            removeCR: true
                        }
                    }, {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: true,
                            sassOptions: {
                                includePaths: [
                                    path.resolve(__dirname, "./node_modules/@syncfusion")
                                ]
                            }
                        }
                    }]
            }, {
                test: /\.js$/,
                exclude: [/assets/, /node_modules\\(?!@bimcollab)/],
                loader: 'babel-loader'
            }, {
                test: /\.(png|jpg|gif|woff(2)?)$/,
                type: 'asset'
            }]
    },
    plugins: [
        new AssetsPlugin({ // Creates 'webpack-assets.json' file with all asset paths
            prettyPrint: true,
            entrypoints: true
        }),
        new BundleAnalyzerPlugin({
            analyzerMode: "static",
            openAnalyzer: false
        }),
        new VueLoaderPlugin(),
        new MiniCssExtractPlugin({
            chunkFilename: "[name].[contenthash].css",
            filename: "[name].[contenthash].css"
        }),
        new webpack.DefinePlugin({
            "process.env": JSON.stringify(process.env)
        })
    ],
    resolve: {
        alias: {
            '@src': path.resolve(__dirname, 'src/'),
            '@assets': path.resolve(__dirname, 'assets/'),
        }
    }
};

console.log(packageJson.version);

我找到了解決這個問題的方法。 如前所述,這里真正的問題是,對於入口 B,webpack 將模塊 C 的代碼放入 B 的輸出文件中,而在運行時,它試圖從其單獨的塊文件(由 webpack 為入口 A 創建的)訪問模塊 C )。

現在,如果我強制 webpack 始終將模塊 C 放入一個單獨的塊中,它就解決了問題。 在這種情況下,webpack 只為模塊 C 創建一個文件,因此在運行時它將始終使用單個正確的文件。 為此,我使用了 cacheGroups。 在下面的例子中,問題出在 BootstrapVue 中,但我也看到其他模塊也出現了同樣的問題。

splitChunks: {
   chunks: 'all',
   cacheGroups: {
      bootstrapVue: {
         test: /[\\/]node_modules[\\/]bootstrap-vue[\\/]/,
         name: 'bootstrap-vue',
      },
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM