繁体   English   中英

Babel 编译失败:.presets[1][0] 必须是字符串,object,function — 如何修复?

[英]Babel failed to compile: .presets[1][0] must be a string, object, function — how to fix?

我的项目基于 Create React App,但由于一些原因我不得不退出。 尽管如此,我还是尽力手动使其符合当前的 CRA 标准。 不过,我的最后一次更新并不顺利。 尝试运行“开始”命令时出现以下错误:

./apps/index.tsx
Error: [BABEL] ./apps/index.tsx: .presets[1][0] must be a string, object, function
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)

我已经手动将一些日志添加到./node_modules/@babel/core/lib/config/validation/option-assertions.js,它给了我以下信息:

LOG "assertPluginItem ERROR inside IF block:"

LOG "Item access(loc, 0)"
{
  type: 'access',
  name: 0,
  parent: {
    type: 'access',
    name: 1,
    parent: { type: 'option', name: 'presets', parent: [Object] }
  }
}

LOG "Item loc"
{
  type: 'access',
  name: 1,
  parent: {
    type: 'option',
    name: 'presets',
    parent: { type: 'root', source: 'preset' }
  }
}

LOG "Item value"
[ undefined, { development: true, runtime: 'automatic' } ]

LOG "pluginLoc"
{
  type: 'option',
  name: 'presets',
  parent: { type: 'root', source: 'preset' }
}

LOG "pluginValue"
[
  [ [Function], { useBuiltIns: 'entry', corejs: 3, exclude: [Array] } ],
  [ undefined, { development: true, runtime: 'automatic' } ],
  [ [Function] ]
]

显然,问题在于[ undefined, { development: true, runtime: 'automatic' } ]中的这个“未定义”,但基于传递给这个失败插件的选项,代码不在我的设置文件中,而是在某个内部通天塔。

我尝试将日志添加到 Babel 核心内的各种文件中,但没有成功,而且我不知道哪个插件失败以及为什么失败。 你有什么想法可以帮助我吗?

这是我的 webpack.config.js 的样子:

const path = require('path');
const webpack = require('webpack');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const getTheme = require('../theme');
const paths = require('../paths');
const getClientEnvironment = require('../env/getClientEnvironment');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');

const postcssNormalize = require('postcss-normalize');

const appPackageJson = require(paths.appPackageJson);

const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';

const webpackDevClientEntry = require.resolve('react-dev-utils/webpackHotDevClient');
const reactRefreshOverlayEntry = require.resolve('react-dev-utils/refreshOverlayInterop');

const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';


const cssRegex = /\.css$/;

const hasJsxRuntime = (() => {
    if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') {
        return false;
    }

    try {
        require.resolve('react/jsx-runtime');
        return true;
    }
    catch (e) {
        return false;
    }
})();

module.exports = function getConfig(appName, webpackEnv = 'development', isHotModuleReloadEnabled = true) {
    const isEnvDevelopment = webpackEnv === 'development';
    const isEnvProduction = webpackEnv === 'production';

    const isEnvProductionProfile =
        isEnvProduction && process.argv.includes('--profile');

    const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));

    const shouldUseReactRefresh = env.raw.FAST_REFRESH;


    const getStyleLoaders = (cssOptions, preProcessor) => {
        const loaders = [
            isEnvDevelopment && require.resolve('style-loader'),
            isEnvProduction && {
                loader: MiniCssExtractPlugin.loader,
                options: paths.publicUrlOrPath.startsWith('.')
                    ? { publicPath: '../../' }
                    : {},
            },
            {
                loader: require.resolve('css-loader'),
                options: cssOptions,
            },
            {
                loader: require.resolve('postcss-loader'),
                options: {
                    ident: 'postcss',
                    plugins: () => [
                        require('postcss-flexbugs-fixes'),
                        require('postcss-preset-env')({
                            autoprefixer: {
                                flexbox: 'no-2009',
                            },
                            stage: 3,
                        }),
                        postcssNormalize(),
                    ],
                    sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
                },
            },
        ].filter(Boolean);
        if (preProcessor) {
            loaders.push(
                {
                    loader: require.resolve('resolve-url-loader'),
                    options: {
                        sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment,
                        root: paths.appSrc,
                    },
                },
                {
                    loader: require.resolve(preProcessor),
                    options: {
                        sourceMap: true,
                        globalVars: getTheme(appName),
                    },
                },
            );
        }
        return loaders;
    };

    const alias = {
        ...paths.alias,
        app: paths.getAppPath(appName),
    };

    return {
        stats: 'verbose',
        name: appName,
        mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
        bail: isEnvProduction,
        devtool: isEnvProduction
            ? shouldUseSourceMap
                ? 'source-map'
                : false
            : isEnvDevelopment && 'cheap-module-source-map',
        entry:
            isEnvDevelopment && !shouldUseReactRefresh
                ? [
                    webpackDevClientEntry,
                    paths.appStyles,
                    paths.appIndexJs,
                ]
                : [
                    paths.appStyles,
                    paths.appIndexJs,
                ],
        output: {
            path: isEnvProduction ? paths.appBuild(appName) : undefined,
            pathinfo: isEnvDevelopment,
            filename: isEnvProduction
                ? 'static/js/[name].[contenthash:8].js'
                : isEnvDevelopment && 'static/js/bundle.js',
            futureEmitAssets: true,
            chunkFilename: isEnvProduction
                ? 'static/js/[name].[contenthash:8].chunk.js'
                : isEnvDevelopment && 'static/js/[name].chunk.js',
            publicPath: paths.publicUrlOrPath,
            devtoolModuleFilenameTemplate: isEnvProduction
                ? (info) =>
                    path
                        .relative(paths.appsPath, info.absoluteResourcePath)
                        .replace(/\\/g, '/')
                : isEnvDevelopment &&
                ((info) => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
            jsonpFunction: `webpackJsonp${appPackageJson.name}`,
            globalObject: 'this',
        },
        optimization: {
            minimize: isEnvProduction,
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        parse: {
                            ecma: 8,
                        },
                        compress: {
                            ecma: 5,
                            warnings: false,
                            comparisons: false,
                            inline: 2,
                        },
                        mangle: {
                            safari10: true,
                        },
                        keep_classnames: isEnvProductionProfile, // eslint-disable-line camelcase
                        keep_fnames: isEnvProductionProfile, // eslint-disable-line camelcase
                        output: {
                            ecma: 5,
                            comments: false,
                            ascii_only: true,
                        },
                    },
                    sourceMap: shouldUseSourceMap,
                }),
                new OptimizeCSSAssetsPlugin({
                    cssProcessorOptions: {
                        parser: safePostCssParser,
                        map: shouldUseSourceMap
                            ? {
                                inline: false,
                                annotation: true,
                            }
                            : false,
                    },
                    cssProcessorPluginOptions: {
                        preset: ['default', { minifyFontValues: { removeQuotes: false } }],
                    },
                }),
            ],
            splitChunks: {
                cacheGroups: {
                    app: {
                        test: /[\\/]apps[\\/]/,
                        name: 'app',
                        chunks: 'all',
                    },
                    shared: {
                        test: /[\\/]shared[\\/]/,
                        name: 'shared',
                        chunks: 'all',
                    },
                    libs: {
                        test: /[\\/]libs[\\/]/,
                        name: 'libs',
                        chunks: 'all',
                    },
                    vendors: {
                        test: /[\\/]node_modules[\\/]/,
                        name: 'vendors',
                        chunks: 'all',
                    },
                },
            },
            runtimeChunk: {
                name: (entrypoint) => `runtime-${entrypoint.name}`,
            },
        },
        resolve: {
            modules: [
                'node_modules',
                paths.nodeModules,
                paths.sharedSrc,
                paths.libSrc,
            ].concat(
                process.env.NODE_PATH.split(path.delimiter).filter(Boolean),
            ),
            extensions: ['.tsx', '.ts', '.js'],
            alias,
            plugins: [
                PnpWebpackPlugin,
            ],
        },
        resolveLoader: {
            plugins: [
                PnpWebpackPlugin.moduleLoader(module),
            ],
        },
        module: {
            strictExportPresence: true,
            rules: [
                { parser: { requireEnsure: false } },
                {
                    oneOf: [
                        {
                            test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
                            loader: require.resolve('url-loader'),
                            options: {
                                limit: 10000,
                                name: 'static/media/[name].[hash:8].[ext]',
                            },
                        },
                        {
                            test: /\.(js|mjs|jsx|ts|tsx)$/,
                            include: [
                                paths.appsPath,
                                paths.sharedSrc,
                                paths.libSrc,
                            ],
                            loader: require.resolve('babel-loader'),
                            options: {
                                customize: require.resolve(
                                    'babel-preset-react-app/webpack-overrides',
                                ),
                                presets: [
                                    [
                                        require.resolve('babel-preset-react-app'),
                                        {
                                            runtime: hasJsxRuntime ? 'automatic' : 'classic',
                                        },
                                    ],
                                ],
                                plugins: [
                                    ['add-module-exports'],
                                    ['@babel/plugin-transform-modules-commonjs'], // only until no more module.exports = *
                                    ['module-resolver', { extensions: ['.js', '.ts', '.tsx'], alias }],
                                    [require.resolve('babel-plugin-named-asset-import'), {
                                        loaderMap: {
                                            svg: {
                                                ReactComponent: '@svgr/webpack?-svgo,+titleProp,+ref![path]',
                                            },
                                        },
                                    }],
                                    isEnvDevelopment && shouldUseReactRefresh && require.resolve('react-refresh/babel'),
                                ].filter(Boolean),
                                cacheDirectory: true,
                                cacheCompression: false,
                                compact: isEnvProduction,
                            },
                        },
                        {
                            test: /\.(js|mjs)$/,
                            exclude: /@babel(?:\/|\\{1,2})runtime/,
                            loader: require.resolve('babel-loader'),
                            options: {
                                babelrc: false,
                                configFile: false,
                                compact: false,
                                presets: [
                                    [
                                        require.resolve('babel-preset-react-app/dependencies'),
                                        { helpers: true },
                                    ],
                                ],
                                cacheDirectory: true,
                                cacheCompression: false,

                                sourceMaps: shouldUseSourceMap,
                                inputSourceMap: shouldUseSourceMap,
                            },
                        },

                        {
                            test: cssRegex,
                            use: getStyleLoaders({
                                importLoaders: 1,
                                sourceMap: isEnvProduction
                                    ? shouldUseSourceMap
                                    : isEnvDevelopment,
                            }),
                            sideEffects: true,
                        },
                        {
                            test: /\.(less)$/,
                            use: [
                                isEnvDevelopment && require.resolve('style-loader'),
                                {
                                    loader: require.resolve('css-loader'),
                                    options: {
                                        importLoaders: 0,
                                        sourceMap: isEnvProduction
                                            ? shouldUseSourceMap
                                            : isEnvDevelopment,
                                    },
                                },
                                {
                                    loader: 'less-loader',
                                    options: {
                                        logLevel: 2,
                                        relativeUrls: true,
                                        globalVars: getTheme(appName),
                                        env: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
                                    },
                                },
                                require.resolve('import-glob-loader'),
                            ].filter(Boolean),
                            sideEffects: true,
                        },
                        {
                            loader: require.resolve('file-loader'),
                            exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
                            options: {
                                name: 'static/media/[name].[hash:8].[ext]',
                            },
                        },
                    ],
                },
            ],
        },
        plugins: [
            new HtmlWebpackPlugin(
                Object.assign(
                    {},
                    {
                        inject: true,
                        template: paths.appHtml,
                    },
                    isEnvProduction
                        ? {
                            minify: {
                                removeComments: true,
                                collapseWhitespace: true,
                                removeRedundantAttributes: true,
                                useShortDoctype: true,
                                removeEmptyAttributes: true,
                                removeStyleLinkTypeAttributes: true,
                                keepClosingSlash: true,
                                minifyJS: true,
                                minifyCSS: true,
                                minifyURLs: true,
                            },
                        }
                        : undefined,
                ),
            ),
            isEnvProduction &&
            shouldInlineRuntimeChunk &&
            new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
            new InterpolateHtmlPlugin(
                HtmlWebpackPlugin,
                Object.assign({ FAVICON: `favicon-${appName}.ico?v3` }, env.raw),
            ),
            new ModuleNotFoundPlugin(paths.rootDirectory, paths.yarnLockFile),
            new webpack.DefinePlugin(env.stringified),
            isEnvDevelopment && isHotModuleReloadEnabled && new webpack.HotModuleReplacementPlugin(),
            isEnvDevelopment &&
            shouldUseReactRefresh &&
            new ReactRefreshWebpackPlugin({
                overlay: {
                    entry: webpackDevClientEntry,
                    module: reactRefreshOverlayEntry,
                    sockIntegration: false,
                },
            }),
            isEnvDevelopment && new CaseSensitivePathsPlugin(),
            isEnvDevelopment &&
            new WatchMissingNodeModulesPlugin(paths.nodeModules),
            isEnvProduction &&
            new MiniCssExtractPlugin({
                filename: 'static/css/[name].[contenthash:8].css',
                chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
            }),
            new ManifestPlugin({
                fileName: 'asset-manifest.json',
                publicPath: paths.publicUrlOrPath,
                generate: (seed, files, entrypoints) => {
                    const manifestFiles = files.reduce((manifest, file) => {
                        manifest[file.name] = file.path; // eslint-disable-line immutable/no-mutation
                        return manifest;
                    }, seed);
                    const entrypointFiles = entrypoints.main.filter(
                        (fileName) => !fileName.endsWith('.map'),
                    );

                    return {
                        files: manifestFiles,
                        entrypoints: entrypointFiles,
                    };
                },
            }),
            new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
        ].filter(Boolean),
        node: {
            module: 'empty',
            dgram: 'empty',
            dns: 'mock',
            fs: 'empty',
            net: 'empty',
            tls: 'empty',
            child_process: 'empty',
        },
        performance: false,
    };
};

感谢 Logan Smyth,我能够解决这个问题。 如果其他人在这里遇到类似的问题,会发生以下情况:

在上面的 webpack 配置中,在 babel-loader 的模块规则中,我有babel-plugin-add-module-exports可以与我使用的旧依赖项实现一些互操作性。 升级所有依赖项后,此模块与内联require require("@babel/preset-env").defaultdefault属性被add-module-exports删除,导致它评估为undefined

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM