代码之家  ›  专栏  ›  技术社区  ›  Zain763

NextJS webpack:已使用与API架构不匹配的生成器对象初始化资产模块插件

  •  0
  • Zain763  · 技术社区  · 2 年前

    我正在使用NextJS和 next.config ,我正在使用一些自定义的webpack配置。

    我的 next.config.js 文件如下:

    const { i18n } = require('./next-i18next.config')
    const TerserPlugin = require("terser-webpack-plugin");
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
    
    const nextConfig = {
      reactStrictMode: false,
      distDir: 'dist',
      i18n,
      images: {
        domains: ['aws-link', 'my-site'],
      },
    }
    
    module.exports = {
      webpack: function(config, {isServer}) {
        if (config.mode === 'production' && config.name === 'client') {
          if (!isServer && process.env.ANALYZE === 'true') {
            const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
            config.plugins.push(
              new BundleAnalyzerPlugin({
                analyzerMode: 'static',
                reportFilename: './analyze/client.html',
                generateStatsFile: true
              })
            );
          }
    
          // 'filename' is specific to 'asset/resource' type only, but incompatible with 'asset/inline',
          // see https://webpack.js.org/guides/asset-modules/#custom-output-filename.
          // Here we rename generator['asset'] into generator['asset/resource'] to avoid conflicts with inline assets.
          // if (config.module.generator?.asset?.filename) {
          //   if (!config.module.generator['asset/resource']) {
          //     config.module.generator['asset/resource'] = config.module.generator.asset
          //   }
          //   delete config.module.generator.asset
          // }
    
          config.plugins.push(
            new MiniCssExtractPlugin()
          )
    
          config.module.rules.push({
            test: /\.css$/i,
            use: [MiniCssExtractPlugin.loader, "css-loader"],
            parser: { dataUrlCondition: { maxSize: 50000 } },
          })
    
          config.module.rules.push({ test: /\.(woff|ttf|otf|eot|woff2)$/i, type: "asset/resource", generator: {
            outputPath: 'public/',
            publicPath: 'public/'
          } });
    
          config.module.rules.push({ test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/i, type: "asset/resource", generator: {
            outputPath: 'public/', // this is the new option set
            publicPath: 'public/'
          }});
    
      //     config.module.rules.push({
      //       test: /\.(png|jpg|webp|gif|svg|mp4|webm|ico|mp3)$/,
      //       type: 'asset',
      //       parser: { dataUrlCondition: { maxSize: 150000 } },
      // })
    
          config.optimization = {
            minimize: true,
            minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
            splitChunks: {
              chunks: 'async',
              minSize: 20000,
              minChunks: 1,
              maxAsyncRequests: 30,
              maxInitialRequests: 30,
              enforceSizeThreshold: 50000,
              cacheGroups: {
                defaultVendors: {
                  test: /[\\/]node_modules[\\/]/,
                  priority: -10,
                  reuseExistingChunk: true
                },
                default: {
                  minChunks: 2,
                  priority: -20,
                  reuseExistingChunk: true
                }
              }
            }
          };
    
        } 
    
        return config;
      },
      ...nextConfig
    }
    
    // module.exports = {
      
    //   ...nextConfig,
    // }
    

    但是,我得到了一个错误:

    未能编译。

    ./node_modules/antd/dist/antd.css
    Module not found: Invalid generator object. Asset Modules Plugin has been initialized using a generator object that does not match the API schema.
     - generator has an unknown property 'filename'. These properties are valid:
       object { dataUrl? }
       -> Generator options for asset/inline modules.
    

    我试图从github的回答中遵循这个解决方案:

    if (config.module.generator?.asset?.filename) {
            if (!config.module.generator['asset/resource']) {
              config.module.generator['asset/resource'] = config.module.generator.asset
            }
            delete config.module.generator.asset
          }
    

    但是,这只是打乱了我所有的导入,没有加载css。我真的很感谢这里的帮助,因为我浪费了一整天的时间寻找解决方案。

    顺便说一下,这是我的文件夹结构:

    页码/

    公众/

     --fonts/
    
     --gif/
    
     --png/
    
     --svg/
    

    这就是我在组件中使用这些图像的方式:

    import arrow from '../../public/svg/select-arrow.svg'

    所有这些都很好,直到我决定把它添加到我的 next.config.js :

    config.module.rules.push({
            test: /\.css$/i,
            use: [MiniCssExtractPlugin.loader, "css-loader"],
            parser: { dataUrlCondition: { maxSize: 50000 } },
          })
    

    P.S.:我几乎试过了这里的所有解决方案,但它们不能解决我的问题,所以请不要把它标记为重复。

    0 回复  |  直到 2 年前
        1
  •  -1
  •   Statistics Tutorial    2 年前

    错误消息指示 generator webpack配置中的对象:它包含未知属性 filename 。根据 webpack documentation 这个 发电机 对于资产模块,仅识别 dataUrl 所有物

    若要解决此错误,请更新 发电机 的配置 asset/resource 键入以删除 文件名 所有物此外,确保 parser rules

    以下是更正后的配置:

    config.module.rules.push({
      test: /\.(woff|ttf|otf|eot|woff2)$/i, 
      type: "asset/resource", 
      generator: {
        outputPath: 'public/',
        publicPath: 'public/'
      } 
    });
    
    config.module.rules.push({ 
      test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/i, 
      type: "asset/resource", 
      generator: {
        outputPath: 'public/', // this is the new option set
        publicPath: 'public/'
      }
    });
    

    对于CSS规则,请确保解析器不在规则配置中:

    config.module.rules.push({
      test: /\.css$/i,
      use: [MiniCssExtractPlugin.loader, "css-loader"]
    });
    

    如果你想为资产应用dataUrlCondition,你可以这样做:

    config.module.rules.push({ 
      test: /\.(?:ico|gif|png|jpg|jpeg|webp)$/i, 
      type: "asset/resource", 
      parser: { dataUrlCondition: { maxSize: 50000 } },
      generator: {
        outputPath: 'public/', // this is the new option set
        publicPath: 'public/'
      }
    });
    

    进行这些更改后,请尝试再次运行Next.js应用程序,查看错误是否已解决。