core-js is large in bundle (using 62kB)
Asked Answered
C

1

6

I'm reducing my js bundle size and stumbled upon core-js. It takes around 62kB which represents ~24% of the whole package.

enter image description here

I tried using @babel/preset-env, but wasn't able to shrink the size any further. Not sure if I'm using the "right" settings:

'@babel/preset-env',
  {
    targets: {
      browsers: ['>1%'],
    },
    useBuiltIns: 'usage',
    corejs: { version: 3, proposals: true },
  },

The full webpack.config.js

const path = require('path');
const webpack = require('webpack');
const dotenv = require('dotenv');
const copyWebpackPlugin = require('copy-webpack-plugin');
const bundleOutputDir = './dist';

/* eslint-disable import/no-extraneous-dependencies */
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

// const CompressionPlugin = require('compression-webpack-plugin');

module.exports = (env) => {
  // get project ID (environment)
  const projectID = process.env.PROJECT_ID;
  if (!projectID || projectID === undefined) {
    throw new Error('Need env variable PROJECT_ID');
  }

  const isDevEnvironment = !(projectID === 'production-project');
  const isDevBuild = !(env && env.prod);
  const analyzeBundle = env && env.analyze;

  // call dotenv and it will return an Object with a parsed key
  const dotEnv = isDevEnvironment ? dotenv.config({ path: './.env.development' }).parsed : dotenv.config().parsed;

  // reduce it to a nice object, the same as before
  const envKeys = Object.keys(dotEnv).reduce((prev, next) => {
    const updatedPrev = prev;
    updatedPrev[`process.env.${next}`] = JSON.stringify(dotEnv[next]);
    return updatedPrev;
  }, {});

  envKeys['process.env.PROJECT_ID'] = JSON.stringify(projectID);

  // need to remove quotes from env
  const publicURL = 'https:/mysite.com'

  const plugins = [new webpack.DefinePlugin(envKeys), new ForkTsCheckerWebpackPlugin()];
  if (isDevBuild) {
    // eslint-disable-next-line new-cap
    plugins.push(new webpack.SourceMapDevToolPlugin(), new copyWebpackPlugin([{ from: 'dev/' }]));
  } else {
    // Don't need to enable compressinon plugin as Firebase Hosting automatically zips the files for us
    // plugins.push(new CompressionPlugin());
  }

  if (analyzeBundle) {
    // eslint-disable-next-line global-require
    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
    plugins.push(new BundleAnalyzerPlugin());
  }

  const babelPlugins = [
    // syntax sugar found in React components
    '@babel/proposal-class-properties',
    '@babel/proposal-object-rest-spread',
    // transpile JSX/TSX to JS
    [
      '@babel/plugin-transform-react-jsx',
      {
        // we use Preact, which has `Preact.h` instead of `React.createElement`
        pragma: 'h',
        pragmaFrag: 'Fragment',
      },
    ],
    [
      'transform-react-remove-prop-types',
      {
        removeImport: !isDevBuild,
      },
    ],
  ];

  if (!isDevBuild) {
    babelPlugins.push(['transform-remove-console', { exclude: ['error', 'warn'] }]);
  }

  return [
    {
      entry: './src/index.ts',
      output: {
        filename: 'widget.js',
        path: path.resolve(bundleOutputDir),
        publicPath: isDevBuild ? '' : publicURL,
      },
      devServer: {
        host: '0.0.0.0', // your ip address
        port: 8080,
        disableHostCheck: true,
        contentBase: bundleOutputDir,
        open: 'google chrome',
      },
      plugins,
      optimization: {
        minimize: !isDevBuild,
        nodeEnv: 'production',
        mangleWasmImports: true,
        removeAvailableModules: true,
        usedExports: true,
        sideEffects: true,
        providedExports: true,
        concatenateModules: true,
      },
      mode: isDevBuild ? 'development' : 'production',
      module: {
        rules: [
          // packs PNG's discovered in url() into bundle
          {
            test: /\.(jpe?g|png|webp)$/i,
            use: [
              {
                loader: 'responsive-loader',
                options: {
                  // eslint-disable-next-line global-require
                  adapter: require('responsive-loader/sharp'),
                  // sizes: [160, 320, 640, 960, 1280],
                  name: '[path][name]-[width].[ext]',
                  sourceMap: isDevBuild,
                },
              },
            ],
          },
          { test: /\.svg/, use: ['@svgr/webpack'] },
          {
            test: /\.(css)$/i,
            use: [
              {
                loader: 'style-loader',
                options: {
                  injectType: 'singletonStyleTag',
                },
              },
              {
                // allows import CSS as modules
                loader: 'css-loader',
                options: {
                  modules: {
                    // css class names format
                    localIdentName: '[name]-[local]-[hash:base64:5]',
                  },
                  sourceMap: isDevBuild,
                },
              },
            ],
          },
          {
            test: /\.(scss)$/i,
            use: [
              {
                loader: 'style-loader',
                options: { injectType: 'singletonStyleTag' },
              },
              {
                // allows import CSS as modules
                loader: 'css-loader',
                options: {
                  modules: {
                    // css class names format
                    localIdentName: '[name]-[local]-[hash:base64:5]',
                  },
                  sourceMap: isDevBuild,
                },
              },
              {
                loader: 'sass-loader',
                options: {
                  sourceMap: isDevBuild,
                },
              },
            ],
          },
          // use babel-loader for TS and JS modeles,
          // starting v7 Babel babel-loader can transpile TS into JS,
          // so no need for ts-loader
          // note, that in dev we still use tsc for type checking
          {
            test: /\.(js|ts|tsx|jsx)$/,
            exclude: /node_modules/,
            use: [
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    [
                      '@babel/preset-env',
                      {
                        targets: {
                          browsers: ['>1%'],
                        },
                        useBuiltIns: 'usage',
                        corejs: { version: 3, proposals: true },
                      },
                    ],
                    [
                      // enable transpiling ts => js
                      '@babel/typescript',
                      // tell babel to compile JSX using into Preact
                      { jsxPragma: 'h' },
                    ],
                  ],
                  plugins: babelPlugins,
                },
              },
            ],
          },
        ],
      },
      resolve: {
        extensions: ['*', '.js', '.ts', '.tsx'],
        plugins: [new TsconfigPathsPlugin()],
        alias: {
          react: 'preact/compat',
          'react-dom': 'preact/compat',
          images: path.join(__dirname, 'images'),
          sharedimages: path.resolve(__dirname, '../../packages/shared/src/resources'),
        },
      },
    },
  ];
};

Christiansand answered 1/2, 2021 at 21:45 Comment(2)
Same issue here, with useBuiltIns: "usage", last 3 versions, not dead query and it takes 62kb gzipped, did you find the reason ?Connatural
Unfortunately, I haven't found a way to reduce the size yet.Christiansand
A
0

It looks like the targets property for @babel/preset-env is no longer used and instead the browserlist is recommended to include the list of supported browsers. https://babeljs.io/docs/en/babel-preset-env#browserslist-integration

Authoritative answered 31/12, 2021 at 5:51 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewWiring

© 2022 - 2024 — McMap. All rights reserved.