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

如何从Webpack构建中移除.test.js文件?

问题描述

我在React项目中尝试移除所有.test.js文件,构建应用时出现如下错误:

Module parse failed: Unexpected token
可能需要合适的loader来处理该文件类型,目前没有配置任何loader来处理此文件。

如果我移除rules里的排除规则,仅保留exclude: /node_modules/,错误会消失,但BundleAnalyzerPlugin仍会显示.test.js文件,说明Webpack并未真正移除它们。

当前Webpack 5.x配置

module.exports = {
  devtool: false,
  mode: 'production',
  entry: {
    app: [path.join(config.srcDir, 'index.js')],
  },
  optimization: {
    moduleIds: 'named',
    chunkIds: 'named',
    minimize: true,
    nodeEnv: 'production',
    mangleWasmImports: true,
    removeEmptyChunks: false,
    mergeDuplicateChunks: false,
    flagIncludedChunks: true,
    minimizer: [`...`, 
    new CssMinimizerPlugin({
      minimizerOptions: {
        preset: [
          "default",
          {
            calc: false,
            discardComments: { removeAll: true },
          },
        ],
      },
    }),
    '...'],
    emitOnErrors: true,
    splitChunks: {
      chunks: 'all',
      minSize: 20000,
      minRemainingSize: 0,
      minChunks: 1,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      enforceSizeThreshold: 50000,
      cacheGroups: {
        defaultVendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          reuseExistingChunk: true,
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true,
        },
      },
    },
  },
  output: {
    filename: '[name].bundle.js',
    chunkFilename: '[name].chunk.js',
    path: config.distDir,
    publicPath: BASE_PATH,
  },
  resolve: {
    fallback: { "querystring": false },
    modules: ['node_modules', config.srcDir],
    alias: {
      path: require.resolve('path-browserify'),
      Components: path.resolve(__dirname, '../app/components'),
      Context: path.resolve(__dirname, '../app/context'),
      Images: path.resolve(__dirname, '../app/images'),
      Plugins: path.resolve(__dirname, '../plugins'),
      Redux: path.resolve(__dirname, '../app/redux'),
      Routes: path.resolve(__dirname, '../app/routes'),
      Styles: path.resolve(__dirname, '../app/styles'),
      Utils: path.resolve(__dirname, '../app/utils'),
    },
  },
  plugins: [
    new CircularDependencyPlugin({
      exclude: /a\.js|node_modules/,
      failOnError: true,
      allowAsyncCycles: false,
      cwd: process.cwd(),
    }),
    new HtmlWebpackPlugin({
      template: config.srcHtmlLayout,
      inject: 'body',
      title: 'AdminUI',
    }),
    new MiniCssExtractPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production'),
        BASE_PATH: JSON.stringify(BASE_PATH),
        API_BASE_URL: JSON.stringify(API_BASE_URL),
        CONFIG_API_BASE_URL: JSON.stringify(CONFIG_API_BASE_URL),
        SESSION_TIMEOUT_IN_MINUTES: JSON.stringify(SESSION_TIMEOUT_IN_MINUTES),
      },
    }),
    new PurgeCSSPlugin({ paths: glob.sync(`${PATHS.src}/**/*`,  { nodir: true }) }),
    new webpack.IgnorePlugin({
      resourceRegExp: /\.test\.js$/,
    }),
    new BundleAnalyzerPlugin(),
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [config.srcDir, config.pluginsDir],
        exclude: /(node_modules|\.test\.js$)/,
        use: 'babel-loader',
        sideEffects: false,
      },
      // Modular Styles
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "style-loader", "css-loader", "postcss-loader"]
      },
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              modules: true,
            },
          },
          { loader: 'postcss-loader' },
          'sass-loader',
        ],
        exclude: [path.resolve(config.srcDir, 'styles')],
        include: [config.srcDir],
      },
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: 'css-loader' },
          { loader: 'postcss-loader' },
          {
            loader: 'sass-loader',
            options: {},
          },
        ],
        include: [path.resolve(config.srcDir, 'styles')],
      },
      // Fonts
      {
        test: /\.(ttf|eot|woff|woff2)$/,
        loader: 'file-loader',
        options: {
          name: '/fonts/[name].[ext]',
          esModule: false,
        },
      },
      // Files
      {
        test: /\.(jpg|jpeg|png|gif|svg|ico)$/,
        loader: 'file-loader',
        options: {
          name: '/static/[name].[ext]',
          esModule: false,
        },
      },
    ],
  },
  devServer: {
    hot: false,
    //contentBase: config.distDir,
    compress: true,
    historyApiFallback: {
      index: BASE_PATH,
    },
    host: '0.0.0.0',
    port: 4100,
  },
}
解决方案

1. 修复IgnorePlugin配置(Webpack 5适配)

Webpack 5中IgnorePlugin需要明确限定匹配范围,避免无效匹配。修改配置为:

new webpack.IgnorePlugin({
  resourceRegExp: /\.test\.js$/,
  contextRegExp: new RegExp(`^${config.srcDir}|^${config.pluginsDir}`)
})

添加contextRegExp后,只会忽略源码和插件目录下的.test.js文件,确保规则精准生效。

2. 新增规则直接忽略测试文件

在module.rules最顶部添加一条规则,让Webpack直接跳过.test.js文件的解析:

module: {
  rules: [
    {
      test: /\.test\.js$/,
      use: 'null-loader'
    },
    // 原有JS loader规则
    {
      test: /\.js$/,
      include: [config.srcDir, config.pluginsDir],
      exclude: /node_modules/,
      use: 'babel-loader',
      sideEffects: false,
    },
    // ...其他规则
  ]
}

先安装依赖:

npm install null-loader --save-dev

null-loader会直接忽略匹配到的文件,不会触发任何解析流程。

3. 修正PurgeCSSPlugin的路径匹配

当前PurgeCSS会扫描所有文件包括测试文件,需要排除.test.js:

new PurgeCSSPlugin({ 
  paths: glob.sync(`${PATHS.src}/**/*`,  { 
    nodir: true,
    ignore: [`${PATHS.src}/**/*.test.js`]
  }) 
}),

4. 验证结果

重新执行构建,通过BundleAnalyzerPlugin确认.test.js文件不再出现在打包产物中,同时检查是否还有解析错误。


内容的提问来源于stack exchange,提问作者Chandler Bing

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 01:42:27