首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何让webpack只为特定的构建导入polyfills?

如何让webpack只为特定的构建导入polyfills?
EN

Stack Overflow用户
提问于 2020-11-01 16:44:26
回答 1查看 104关注 0票数 0

我刚刚设法让webpack创建了两个独立构建,一个用于es5,另一个用于es6。请看下面的配置文件:

代码语言:javascript
复制
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
        ]
      },
      {
      test: /\.m?js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env', {
              modules: false,
              useBuiltIns: 'entry',
              targets: {
                browsers: [
                  "IE 11"
                ],
              },
            }],
          ],
        },
      },
    }],
  },
});

const es6Config = merge(common, {
  mode: "production",
  output: {
    filename: "[name].[contentHash].bundle.es6.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
        ]
      },
      {
      test: /\.m?js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            ['@babel/preset-env', {
              modules: false,
              useBuiltIns: "usage",
              targets: {
                browsers: [
                  'Chrome >= 60',
                  'Safari >= 10.1',
                  'iOS >= 10.3',
                  'Firefox >= 54',
                  'Edge >= 15',
                ],
              },
            }],
          ],
        },
      },
    }],
  },
});

module.exports = [es5Config, es6Config];

现在的问题是,我希望webpack只为es5构建导入多边形填充。并且使用usebuilins设置为usage不会对任何东西进行多填充。

我可能用错了,也许是与node_modules包有关的东西??

所以我只是在主文件中导入多边形填充,如下所示:

代码语言:javascript
复制
import "core-js/stable";
import "regenerator-runtime/runtime";

如何才能使这些导入仅为es5版本添加?或者,如何包含从webpack导入的polyfills/polyfills?

还有一个额外的问题,如果有人知道,我如何正确地使用带有“用法”的usebuiltins?因为到目前为止,即使为我的主文件添加了polifylls,例如,我仍然在IE11中得到了符号错误。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-02 11:17:46

我想通了。下面是webpack的配置: common:

代码语言:javascript
复制
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"
          }
        }
      }
    ]
  }
};

产品:

代码语言:javascript
复制
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:

代码语言:javascript
复制
{
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "absoluteRuntime": true,
        "helpers": true,
        "regenerator": true,
        "useESModules": false
      }
    ]
  ]
}

因此,这与cdn polyfill相结合,只为IE11加载polifylls。它也有自己的构建。

这里唯一的问题是,结果输出将有独立的文件,并且es5构建的所有脚本中都应该有nomodule。同样对于es6,所有的都应该有模块。然后我必须去手动添加那些我可以很容易地制作一个自定义模板来处理的那些。

但是,polyfill的脚本被删除了,我仍然需要手动合并html文件。有人知道怎么处理这个问题吗?

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

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

代码语言:javascript
复制
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

2-为了合并生成的html,我最终使用了以下要点:https://gist.github.com/agoldis/21782f3b9395f78d28dce23e3b6ddd56

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64630077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档