Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • C create-react-app
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 1,547
    • Issues 1,547
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 417
    • Merge requests 417
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Meta
  • create-react-app
  • Issues
  • #13048
Closed
Open
Issue created Mar 06, 2023 by siarheiyelin@siarheiyelin

CommonJs modules aren't tree-shaked by default.

Describe the bug

"commonJs" dependencies aren't tree-shakeable with CRA out of the box.

Root cause:

The default settings of TerserPlugin in Webpack library includes "passes: 2" option. The entire Terser config looks like this:

new TerserPlugin({
	terserOptions: {
		compress: {
			passes: 2
		}
	}
})

It was added in scope of "commonJs" tree-shaking implementation: . As a result, any "commonJs" dependencies (which imported from "node_modules") are tree-shaked successfully using default settings of Webpack OOTB.

However, the Webpack config in Create React App doesn't include "passes" option (i.e. it's implicitly equal to 1). As a result, "commonJs" modules are not tree-shaked when code is built using CRA.

Environment

Version of CRA: create-react-app: 5.0.1 System: OS: Windows 10 10.0.19045 CPU: (8) x64 Intel(R) Core(TM) i7-10610U CPU @ 1.80GHz Binaries: Node: 18.13.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD npm: 8.19.3 - C:\Program Files\nodejs\npm.CMD

Steps to reproduce

Prerequisites: npx create-react-app treeshaking-issue-demo Steps:

  1. Install some deps.
npm i -D source-map-explorer
npm i -D @epam/uui-core@4.10.1-beta.1
  1. Go to "src/index.js" and add next couple of lines:
import { useForceUpdate } from '@epam/uui-core';
console.log(useForceUpdate);
  1. Build with default settings of CRA. And check bundle content.
npm run build
npx source-map-explorer 'build/**/*.js'
  1. Build with "passes: 2" Go directly to node_modules, edit next file: node_modules/react-scripts/config/webpack.config.js - add "passes": 2 option to the "terserOptions.compress". So that it looks like:
new TerserPlugin({
  terserOptions: {
	parse: {
	  // We want terser to parse ecma 8 code. However, we don't want it
	  // to apply any minification steps that turns valid ecma 5 code
	  // into invalid ecma 5 code. This is why the 'compress' and 'output'
	  // sections only apply transformations that are ecma 5 safe
	  // https://github.com/facebook/create-react-app/pull/4234
	  ecma: 8,
	},
	compress: {
	  passes: 2, /// <----- HERE

Build and check bundle content

npm run build
npx source-map-explorer 'build/**/*.js'
  1. Compare bundles from step 3 and step 4 If you compare bundle from step 3 and bundle from step 4, you could notice that only small part of "@epam/uui-core" library was actually added to the bundle if "passes: 2" option is specified.

image

Expected behavior

I would expect that default settings of CRA support tree shaking of "CommonJs" modules out of the box. More specifically: it makes sense to add "passes: 2" option mentioned above to the default Webpack config of CRA.

Actual behavior

"CommonJs" modules aren't tree shaked out of the box, and I have to use some tools (like CRACO https://craco.js.org/) in order to override default settings and add "passes": 2 option to the Terser plugin options.

Assignee
Assign to
Time tracking