如何在不请求整个core-js程序包的情况下需要一些polyfill?

时间:2019-02-01 18:16:09

标签: reactjs babel webpack-4 polyfills

所以我第一次在这里问一个问题,很好。

我正在使用react.js和webpack 4配置构建一个网页,并且试图通过代码拆分动态地加载polyfill,以便可以支持旧的浏览器,例如ie11。

我一直在看this教程,以进行捆绑包拆分和代码拆分。 (向下滚动到标题“ polyfill”以有条件地加载polyfill)

这是我的设置:

webpack.config.js

const HtmlWebPackPlugin = require('html-webpack-plugin');
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const htmlPlugin = new HtmlWebPackPlugin({
  template: './src/index.html',
  filename: './index.html'
});

const cleanWebpack = new CleanWebpackPlugin(['dist']);


module.exports = {
  entry: ['core-js/modules/es6.promise', 'core-js/modules/es6.array.iterator', path.resolve(__dirname, './src/index.js')],
  output: {
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/'
  },
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: Infinity,
      minSize: 0,
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name(module) {
            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
            return `npm.${packageName.replace('@', '')}`;
          },
        },
      },
    },
  },
  module: {
    rules: [{
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.html$/,
        use: [{
          loader: 'html-loader',
          options: {
            minimize: true
          }
        }]
      },
      {
        test: /\.(css|scss)/,
        use: [{
            loader: 'style-loader'
          },
          {
            loader: 'css-loader',
            options: {
              modules: true,
              importLoaders: 1,
              localIdentName: '[name]_[local]_[hash:base64]',
              sourceMap: true,
              minimize: true
            }
          },
          {
            loader: 'sass-loader'
          }
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [{
          loader: 'file-loader?name=assets/[name].[hash].[ext]'
        }]
      },
      {
        test: /\.(png|jpg|svg)$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[path][name].[ext]'
          }
        }]
      }
    ]
  },
  devServer: {
    historyApiFallback: true
  },
  plugins: [cleanWebpack, htmlPlugin]
};

package.json

{
  "name": "new_portfolio",
  "version": "1.0.0",
  "description": "Daniel Dahlmans portfolio site 2019",
  "browserslist": [
    "> 1% in SE",
    " not op_mini all"
  ],
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --mode development --open",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.2.2",
    "@babel/plugin-proposal-class-properties": "^7.2.3",
    "@babel/plugin-proposal-object-rest-spread": "^7.2.0",
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "@babel/preset-env": "^7.2.3",
    "@babel/preset-react": "^7.0.0",
    "babel-eslint": "^10.0.1",
    "babel-loader": "^8.0.5",
    "clean-webpack-plugin": "^1.0.1",
    "core-js": "^2.6.3",
    "css-loader": "^0.28.11",
    "eslint": "^5.12.0",
    "eslint-plugin-react": "^7.12.4",
    "file-loader": "^1.1.11",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "node-sass": "^4.11.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.21.0",
    "webpack": "^4.28.4",
    "webpack-cli": "^3.2.1",
    "webpack-dev-server": "^3.1.14"
  },
  "dependencies": {
    "prop-types": "^15.6.2",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "react-router-dom": "^4.3.1",
    "typeface-work-sans": "0.0.54"
  }
}

.babelrc

{
  "presets": [
    ["@babel/preset-env",
      {
        "debug": true
      }
    ],
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/plugin-syntax-dynamic-import",
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/plugin-proposal-class-properties"
  ]
}

我制作了一个名为“ polyfills.js”的单独文件,在该文件中,我需要我需要的polyfill:

polyfills.js

require('core-js/es6/array');
require('core-js/es6/string');
require('core-js/es6/map');
require('core-js/es6/object');
require('core-js/es6/symbol');

如果不支持它们,我将有条件地将其导入。

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {
  BrowserRouter as Router
} from 'react-router-dom';
import App from './App';
import 'typeface-work-sans';


const render = () => {
    ReactDOM.render( < Router > < App / > < /Router>, document.getElementById('index'));
    };

    if (
      'Symbol' in window &&
      'Map' in window &&
      'startsWith' in String.prototype &&
      'endsWith' in String.prototype &&
      'includes' in String.prototype &&
      'includes' in Array.prototype &&
      'assign' in Object &&
      'entries' in Object &&
      'keys' in Object
    ) {
      render();
    } else {
      import ( /* webpackChunkName: "polyfills" */ './polyfills').then(() => {
        console.log('I am imported async');
        render();
      });
    }

一切正常,因此,如果我在ie11中运行本地主机,则请求polyfills.js,如果在chrome中,则不请求。

但是令我惊讶的是即使我只需要几个polyfill,我仍然看到浏览器仍在请求整个core-js包... 这会在所有浏览器中发生。

如何在不要求整个core-js软件包的情况下要求使用一些polyfill?

image - from terminal (when running devserver)

image - from networks tab in chrome

image - from elements tab in chrome

执行此操作的全部原因是减小main.js包的大小。

1 个答案:

答案 0 :(得分:0)

似乎需要单独的polyfill模块将导致捆束尺寸减小,但实际上并非如此。 在您的package.json中,将安装整个core-js软件包,并且由于core-js doesn't use ES2015 modules Webpack无法优化输出。

但是,可以创建仅包含所需模块的core-js版本。使用核 - JS的custom build tool以产生更小的束,并把它添加到你的代码,而不是整个核心-JS。