为了账号安全,请及时绑定邮箱和手机立即绑定

如何使 webpack 仅针对特定构建导入 polyfill?

如何使 webpack 仅针对特定构建导入 polyfill?

叮当猫咪 2023-06-29 21:17:09
我刚刚设法让 webpack 创建两个单独的构建,一个用于 es5,另一个用于 es6。请参阅下面的配置文件:const path = require("path");const common = require("./webpack.common");const merge = require("webpack-merge");const CleanWebpackPlugin = require("clean-webpack-plugin");const MiniCssExtractPlugin = require("mini-css-extract-plugin");const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");const TerserPlugin = require("terser-webpack-plugin");var HtmlWebpackPlugin = require("html-webpack-plugin");const es5Config = merge(common,{  mode: "production",  output: {    filename: "[name].[contentHash].bundle.es5.js",    path: path.resolve(__dirname, "dist")  },  optimization: {    minimizer: [      new OptimizeCssAssetsPlugin(),      new TerserPlugin(),      new HtmlWebpackPlugin({        template: "./src/template.html",        minify: {          removeAttributeQuotes: true,          collapseWhitespace: true,          removeComments: true        }      }),    ]  },  plugins: [    new MiniCssExtractPlugin({ filename: "[name].[contentHash].css" }),      new CleanWebpackPlugin(),    ],  module: {    rules: [      {        test: /\.scss$/,        use: [          MiniCssExtractPlugin.loader, //3. Extract css into files          "css-loader", //2. Turns css into commonjs          "sass-loader" //1. Turns sass into css        ]      },module.exports = [es5Config, es6Config];现在的问题是我希望 webpack 仅为 es5 构建导入 polyfill。并使用usebuilins设置为usage并不能填充任何内容。我是否可能使用错误,也许与 node_modules 包相关?所以我只是在主文件中导入 polyfill,例如:import "core-js/stable";import "regenerator-runtime/runtime";如何使这些导入仅添加到 es5 构建中?或者我如何包含来自 webpack 的 polyfills/imports?还有一个额外的问题,如果有人知道,我如何正确使用带有“usage”的usebuiltins?因为到目前为止,即使我认为 polifylls 已添加到我的主文件中,例如,我仍然会在 IE11 中收到符号错误。
查看完整描述

1 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

我想到了。这是 webpack 配置:常见:


const path = require("path");


module.exports = {

  entry: {

    main: "./src/index.js",

    vendor: "./src/vendor.js"

  },

  module: {

    rules: [

      {

        test: /\.html$/,

        use: ["html-loader"]

      },

      {

        test: /\.(svg|png|jpg|gif)$/,

        use: {

          loader: "file-loader",

          options: {

            name: "[name].[hash].[ext]",

            outputPath: "imgs"

          }

        }

      }

    ]

  }

};

产品:


const path = require("path");


const common = require("./webpack.common");

const merge = require("webpack-merge");

const CleanWebpackPlugin = require("clean-webpack-plugin");

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");

const TerserPlugin = require("terser-webpack-plugin");

var HtmlWebpackPlugin = require("html-webpack-plugin");

const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");


const es5Config = merge(common,{

  mode: "production",

  output: {

    filename: "[name].[contentHash].bundle.es5.js",

    path: path.resolve(__dirname, "dist")

  },

  optimization: {

    runtimeChunk: 'single',

    splitChunks: {

      chunks: 'all',

      maxInitialRequests: Infinity,

      minSize: 0,

      cacheGroups: {

        vendor: {

          test: /[\\/]node_modules[\\/]/,

          name: (module) => {

            // get the name. E.g. node_modules/packageName/not/this/part.js

            // or node_modules/packageName

            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];

            // npm package names are URL-safe, but some servers don't like @ symbols

            return `npm.${packageName.replace('@', '')}`;

          },

        },

      },

    },

    minimizer: [

      new OptimizeCssAssetsPlugin(),

      new TerserPlugin(),

      new HtmlWebpackPlugin({

        filename: 'main.aspx',

        template: "./src/main.html",

        // minify: {

        //   removeAttributeQuotes: true,

        //   collapseWhitespace: true,

        //   removeComments: true

        // }

      }),

    ]

  },

  plugins: [

    new MiniCssExtractPlugin({ filename: "[name].[contentHash].css" }),

    new CleanWebpackPlugin(),

    new BundleAnalyzerPlugin(),

    ],


  module: {

    rules: [

      {

        test: /\.scss$/,

        use: [

          MiniCssExtractPlugin.loader, //3. Extract css into files

          "css-loader", //2. Turns css into commonjs

          "sass-loader" //1. Turns sass into css

        ]

      },

      {

      test: /\.m?js$/,

      exclude: /node_modules/,

      //exclude: /node_modules\/(?!(\@pnp)\/).*/, 

      use: {

        loader: 'babel-loader',

        options: {

          //configFile : './es5.babel.config.json',

          presets: [

            ['@babel/preset-env', {

              modules: false,

              useBuiltIns: false,

              targets: {

                browsers: [

                  "IE 11"

                ],

              },

            }],

          ],

        },

      },

    }],

  },

});


const es6Config = merge(common, {

  mode: "production",

  output: {

    filename: "[name].[contentHash].bundle.es6.js",

    path: path.resolve(__dirname, "dist")

  },

  optimization: {

    runtimeChunk: 'single',

    splitChunks: {

      chunks: 'all',

      maxInitialRequests: Infinity,

      minSize: 0,

      cacheGroups: {

        vendor: {

          test: /[\\/]node_modules[\\/]/,

          name: (module) => {

            // get the name. E.g. node_modules/packageName/not/this/part.js

            // or node_modules/packageName

            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];

            // npm package names are URL-safe, but some servers don't like @ symbols

            return `npm.${packageName.replace('@', '')}`;

          },

        },

      },

    },

    minimizer: [

      new OptimizeCssAssetsPlugin(),

      new TerserPlugin(),

      new HtmlWebpackPlugin({

        filename: 'main_es6.html',

        template: "./src/main.html",

        // minify: {

        //   removeAttributeQuotes: true,

        //   collapseWhitespace: true,

        //   removeComments: true

        // }

      }),

    ]

  },

  plugins: [


    new MiniCssExtractPlugin({ filename: "[name].[contentHash].css" }),

    new CleanWebpackPlugin(),

    ],

  module: {

    rules: [

      {

        test: /\.scss$/,

        use: [

          MiniCssExtractPlugin.loader, //3. Extract css into files

          "css-loader", //2. Turns css into commonjs

          "sass-loader" //1. Turns sass into css

        ]

      },

  ],

  },

});

module.exports = [ es5Config, es6Config];

babel.config.json:


{

  "plugins": [

    [

      "@babel/plugin-transform-runtime",

      {

        "absoluteRuntime": true,

        "helpers": true,

        "regenerator": true,

        "useESModules": false

      }

    ]

  ]

}

因此,与 cdn polyfill 相结合,可以仅加载适用于 IE11 的 polifylls。它也有自己的构建。


这里唯一的问题是,生成的输出将具有单独的文件,并且 es5 构建的所有脚本中应该没有模块。另外对于 es6 都应该有模块。然后我必须手动添加那些我可以轻松制作自定义模板来处理的内容。


但随后,polyfill 的脚本被删除,我仍然需要手动合并 html 文件。有人知道如何处理吗?


编辑: 1 - 对于属性,您可以使用 HtmlWebpackPlugin hooks () 或 ScriptExtHtmlWebpackPlugin 将属性放置在标签中。


在这里找到一些带有钩子的代码:


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



class es5TagTransformerHook {

  apply (compiler) {

    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {

  

      HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(

        'es5TagTransformerHook', stacktraces

        async (data, cb) => {

          // Manipulate the content

          // data.html += 'The Magic Footer'

          // Tell webpack to move on

          data.bodyTags.forEach(t=>t.tagName === 'script'?t.attributes.nomodule = true:null)


          cb(null, data)

        }

      )

      

    })

  }

}


module.exports = es5TagTransformerHook

查看完整回答
反对 回复 2023-06-29
  • 1 回答
  • 0 关注
  • 111 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信