首页 > 解决方案 > Webpack 意外行为 TypeError:无法读取未定义的属性“调用”

问题描述

最近我们将 webpack 更新到 v4,并很快注意到 webpack 在开发过程中出现了意外错误,这些错误在重建整个包后消失了。

我们的应用程序使用延迟加载和代码拆分构建,这可能会导致问题,但我在官方文档中找不到与此相关的任何内容。

这是我们得到的错误

react_devtools_backend.js:2273 TypeError: Cannot read property 'call' of undefined

在此处输入图像描述

我们的 webpack webpack.config.js文件。

const webpack = require('webpack');
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const AssetsPlugin = require('assets-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
// minification plugins
const TerserJSPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// image optimization plugins
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const imageminGifsicle = require("imagemin-gifsicle");
const imageminPngquant = require("imagemin-pngquant");
const imageminSvgo = require("imagemin-svgo");
const imageminMozjpeg = require('imagemin-mozjpeg');
const env = require('dotenv').config();

const isProd = process.env.NODE_ENV === 'production';
const isDev = !isProd;

const environment = {
    NODE_ENV: process.env.NODE_ENV || 'development',
    CONFIG: process.env.CONFIG || 'development',
    DEBUG: process.env.DEBUG || false,
};

const plugins = () => {
    let plugins = [
        new CleanWebpackPlugin(['build', 'cachedImages'], {
            root: path.resolve(__dirname, '../dist'),
            verbose: true,
            dry: false,
        }),
        new webpack.EnvironmentPlugin(Object.assign(environment, env.parsed)),
        new MiniCssExtractPlugin('[chunkhash:5].[name].[hash].css'),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            moment: 'moment',
            _: 'lodash',
        }),
        new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en)$/),
        new AssetsPlugin({
            filename: 'assets.json',
        }),
        new ImageminPlugin({
            cacheFolder: isDev ? path.resolve(__dirname, '../dist/cachedImages') : null,
            externalImages: {
                context: 'src',
                sources: glob.sync('src/assets/img/**/*.*'),
                destination: 'dist/img/',
                fileName: (filepath) => {
                    let name = filepath.split(/img(\/|\\)/).pop();
                    return name;
                },
            },
            plugins: [
                imageminGifsicle({
                    interlaced: false
                }),
                imageminMozjpeg({
                    progressive: true,
                    arithmetic: false
                }),
                imageminPngquant({
                    floyd: 0.5,
                    speed: 2
                }),
                imageminSvgo({
                    plugins: [
                        { removeTitle: true },
                        { convertPathData: false }
                    ]
                }),
            ],
        }),
    ];

    if (isProd) {
        plugins.push(
            new BundleAnalyzerPlugin({
                analyzerMode: 'static',
                reportFilename: path.resolve(__dirname, 'analysis.html'),
                generateStatsFile: false,
                logLevel: 'info',
            })
        );
    }

    return plugins;
};

const optimization = () => {
    let optimizations = {
        concatenateModules: true,
        splitChunks: {
            cacheGroups: {
                vendor: {
                    name: 'vendor',
                    test: /[\\/]node_modules[\\/](react|react-dom|lodash|moment)[\\/]/,
                    chunks: 'all',
                },
                commons: {
                    chunks: 'async',
                }
            }
        }
    };

    if (isProd) {
        optimizations.minimizer = [
            new TerserJSPlugin({
                terserOptions: {
                    compress: {
                        pure_funcs: ['console.log'],
                        drop_console: true,
                        drop_debugger: true
                    },
                    warnings: false
                },
                parallel: true
            }),
            new OptimizeCSSAssetsPlugin({})
        ];
    }

    return optimizations;
};

const fontLoaders = [
    {
        test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
        use: {
            loader: 'url?limit=10000&mimetype=application/font-woff',
        }
    },
    {
        test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
        use: {
            loader: 'url?limit=10000&mimetype=application/font-woff',
        }
    },
    {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        use: {
            loader: 'url?limit=10000&mimetype=application/octet-stream',
        }
    },
    {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: {
            loader: 'url?limit=10000&mimetype=image/svg+xml',
        }
    },
    {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        use: {
            loader: 'file',
        }
    }
];

const config = {
    mode: process.env.NODE_ENV,
    devtool: isDev ? 'source-map' : '',
    context: path.resolve(__dirname, '../src'),
    entry: {
        bundle: './app.jsx',
        embed: './embed.jsx',
        styles: './sass_new/main.scss',
        vendor: [
            'react',
            'react-dom',
            'redux',
            'redux-saga',
            'react-redux',
            'react-router',
            'react-tap-event-plugin',
            'lodash',
            'moment',
        ]
    },
    output: {
        publicPath: '/build/',
        filename: '[name].[hash].js',
        chunkFilename: '[name].[hash].js',
        path: path.resolve(__dirname, '../dist/build'),
    },
    resolve: {
        extensions: ['.js', '.jsx', '.json'],
        alias: {
            config: path.resolve(__dirname, '../config.js'),
            utils: path.resolve(__dirname, '../src/utils'),
            shared: path.resolve(__dirname, '../src/components/shared'),
            services: path.resolve(__dirname, '../src/services'),
            store: path.resolve(__dirname, '../src/store'),
            constants: path.resolve(__dirname, '../src/constants'),
            actions: path.resolve(__dirname, '../src/actions'),
            components: path.resolve(__dirname, '../src/components'),
        },
    },
    optimization: optimization(),
    plugins: plugins(),
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: [/node_modules/, /libs/],
                use: {
                    loader: path.join(__dirname, '../helpers/custom-loader.js'),
                    options: {
                        presets: ['@babel/preset-env', '@babel/preset-react'],
                        plugins: [
                            '@babel/plugin-proposal-object-rest-spread',
                            '@babel/plugin-proposal-class-properties',
                            '@babel/plugin-transform-destructuring',
                            '@babel/plugin-syntax-dynamic-import',
                            '@babel/plugin-transform-runtime',
                            'syntax-async-functions'
                        ]
                    }
                }
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader
                    },
                    'css-loader',
                    'sass-loader',
                ]
            },
            {
                test: /\.css$/,
                use: [
                    'css-loader'
                ]
            },
            {
                test: /\.(jpe?g|png|gif|svg)$/i,
                loader: "url-loader",
                options: {
                    name: "[path][name].[ext]"
                },
            },
            ...fontLoaders
        ]
    },
    watchOptions: {
        ignored: /node_modules/,
    },
};

module.exports = config;

我不知道如何解决这个问题,并且在收到此错误后重建整个应用程序需要花费大量时间。

标签: javascriptwebpackruntime-error

解决方案


推荐阅读