You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Babel/Webpack配置异常:构建测试报错及.env适配方案咨询

解决Babel+Webpack构建错误与Jest测试模块语法问题

错误原因分析

1. 构建错误:Error: Plugin/Preset files are not allowed to export objects, only functions.

  • 项目同时安装了Babel 7核心包(@babel/core、@babel/preset-env等)和Babel 6时代的旧预设包(babel-preset-es2015、babel-preset-react),旧包导出格式与Babel 7不兼容。
  • Webpack配置中重复定义Babel的presets/plugins,与根目录babel.config.json的配置冲突,导致加载了错误版本的预设。

2. 测试错误:SyntaxError: Cannot use import statement outside a module

  • Jest默认不支持直接解析ES模块语法,需通过Babel转译测试代码与源码。
  • 测试环境未正确加载Babel配置,且未处理.env文件的环境变量注入。

分步解决方案

1. 清理冲突依赖

移除Babel 6的旧预设包,保留Babel 7官方预设:

npm uninstall babel-preset-es2015 babel-preset-react

2. 简化Webpack的Babel配置

删除Webpack中重复的Babel选项,让babel-loader自动读取babel.config.json的配置,避免冲突。修改webpack.config.js的module.rules和target:

module: {
    rules: [
        // 合并js与jsx规则,无需分开配置
        {
            test: /\.(js|jsx)$/,
            exclude: /node_modules/,
            use: 'babel-loader'
        },
    ]
},
target: 'web', // 前端项目需设置为web,原node是后端项目用的

3. 优化Babel配置

调整babel.config.json,确保测试环境包含React预设(否则测试React组件会报错):

{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ],
    "@babel/preset-typescript"
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "useESModules": true,
        "regenerator": false
      }
    ]
  ],
  "env": {
    "test": {
      "presets": [
        ["@babel/preset-env", { "targets": { "node": "current" } }],
        "@babel/preset-react"
      ]
    }
  }
}

4. 配置Jest支持ES模块与.env文件

在package.json中添加Jest配置:

"jest": {
  "transform": {
    "^.+\\.(js|jsx|ts|tsx)$": "babel-jest"
  },
  "moduleNameMapper": {
    "\\.(css|scss|sass)$": "<rootDir>/__mocks__/styleMock.js",
    "\\.(png|jpg|jpeg|gif|svg)$": "<rootDir>/__mocks__/fileMock.js"
  },
  "setupFiles": [
    "dotenv/config"
  ],
  "testEnvironment": "jsdom"
}

创建__mocks__文件夹及对应mock文件:

  • __mocks__/styleMock.js:
module.exports = {};
  • __mocks__/fileMock.js:
module.exports = "test-file-stub";

5. 统一.env加载逻辑

  • Webpack通过dotenv-webpack插件加载.env,保持现有配置即可。
  • 测试环境通过Jest的setupFiles中的dotenv/config自动加载.env。

修改后的完整配置

webpack.config.js

const path = require('path')
const Dotenv = require('dotenv-webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    devtool: "source-map",
    mode: process.env.NODE_ENV,
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, './build'),
        filename: 'bundle.js',
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: 'babel-loader'
            },
        ]
    },
    resolve: {
        fallback: {
            fs: false,
        },
        alias: {
            config$: './configs/app-config.js',
            react: './vendor/react-master',
        },
        extensions: ['.js', '.jsx', '.ts', '.tsx'],
        modules: [
            'node_modules',
            'bower_components',
            'shared',
            '/shared/vendor/modules',
        ],
    },
    target: 'web',
    plugins: [
        new Dotenv({
            path: './.env',
            safe: true,
            allowEmptyValues: true,
            systemvars: true,
            silent: true,
            defaults: false,
        }),
        new HtmlWebpackPlugin({ inject: true, template: path.resolve('./public/index.html') }),
    ]
}

babel.config.json

{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ],
    "@babel/preset-typescript"
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "useESModules": true,
        "regenerator": false
      }
    ]
  ],
  "env": {
    "test": {
      "presets": [
        ["@babel/preset-env", { "targets": { "node": "current" } }],
        "@babel/preset-react"
      ]
    }
  }
}

package.json(关键修改部分)

{
  "scripts": {
    "start": "env-cmd -f .env webpack-dev-server --open",
    "build": "cross-env NODE_ENV=production env-cmd -f .env webpack",
    "test": "cross-env NODE_ENV=test jest",
    "eject": "react-scripts eject"
  },
  "dependencies": {
    "@jest/globals": "^29.4.2",
    "@react-three/drei": "^9.57.3",
    "@react-three/fiber": "^8.12.0",
    "@reduxjs/toolkit": "^1.9.2",
    "@testing-library/user-event": "^14.4.3",
    "@types/node": "^18.11.19",
    "@types/react": "^18.0.27",
    "@types/react-dom": "^18.0.10",
    "@types/react-redux": "^7.1.25",
    "autoprefixer": "10.4.5",
    "axios": "^1.3.2",
    "dotenv": "^16.0.3",
    "env-cmd": "^10.1.0",
    "eslint-config-ts-react-important-stuff": "^3.0.0",
    "fs": "^0.0.1-security",
    "html-webpack-plugin": "^5.5.0",
    "immer": "^9.0.19",
    "maplibre-gl": "^2.4.0",
    "node-sass": "^7.0.3",
    "os": "^0.1.2",
    "path": "^0.12.7",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-redux": "^7.0.0",
    "react-scripts": "^5.0.1",
    "redux": "^4.2.1",
    "redux-form": "^8.3.9",
    "redux-logger": "^3.0.6",
    "redux-mock-store": "^1.5.4",
    "redux-thunk": "^2.4.2",
    "sass": "^1.58.0",
    "three": "^0.149.0",
    "typescript": "^4.9.5",
    "web-vitals": "^3.1.1",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.7.3"
  },
  "devDependencies": {
    "@babel/core": "^7.20.12",
    "@babel/eslint-parser": "^7.19.1",
    "@babel/preset-env": "^7.20.2",
    "@babel/preset-react": "^7.18.6",
    "@babel/preset-typescript": "^7.18.6",
    "@cfaester/enzyme-adapter-react-18": "^0.6.0",
    "@svgr/webpack": "^6.5.1",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@types/jest": "^27.5.2",
    "@types/redux-logger": "^3.0.9",
    "@types/testing-library__jest-dom": "^5.14.5",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-preset-jest": "^29.4.2",
    "cross-env": "^7.0.3",
    "dotenv-webpack": "^8.0.1",
    "enzyme": "^3.11.0",
    "jest": "^27.5.1",
    "jest-cli": "^27.5.1",
    "react-test-renderer": "^18.2.0",
    "util": "^0.12.5"
  },
  "jest": {
    "transform": {
      "^.+\\.(js|jsx|ts|tsx)$": "babel-jest"
    },
    "moduleNameMapper": {
      "\\.(css|scss|sass)$": "<rootDir>/__mocks__/styleMock.js",
      "\\.(png|jpg|jpeg|gif|svg)$": "<rootDir>/__mocks__/fileMock.js"
    },
    "setupFiles": [
      "dotenv/config"
    ],
    "testEnvironment": "jsdom"
  }
}

内容的提问来源于stack exchange,提问作者Max KievSky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 07:37:03