PlasmoHQ / plasmo

🧩 The Browser Extension Framework
https://www.plasmo.com
MIT License
10.31k stars 358 forks source link

[BUG] Tree shaking not working, causing slow builds #997

Open Evaldas-B opened 3 months ago

Evaldas-B commented 3 months ago

What happened?

Installing and importing external libraries unreasonably increases build times and bundle size. Tree shaking is not taking effect.

Environment: WSL2 Plasmo version: 0.87.1 Node: v20.12.2

Steps to reproduce:

  1. Create new plasmo project pnpm create plasmo
  2. Run pnpm build for reference point. Build time is 1379ms✔ build size is 153kb✔
  3. Install a heavy library like pnpm install @tabler/icons-react
  4. Delete cache and build directories: rm -rf .plasmo build
  5. Import something from installed library in popup.tsx file:
    
    import { IconPlus } from "@tabler/icons-react"

export default function IndexPopup() { return }


6. Run build again `pnpm build` Build time is 33180ms❌ build size is 899kb❌

24-fold increase in build time and the entire library was included in the final build❗

Looking at `popup.js` build file it's clear that all the icons in the library have made it to the build only single one was used.

By the looks of it seems that parcel config is not correct causing the build times and bundle sizes to balloon.

Did the same experiment with `lodash-es`. Only 1 function is being used in `popup.tsx` but all lodash functions are making into the build file.

Here what is being added to build `popop.js` file.

```javascript
           */ var t = e("@parcel/transformer-js/src/esmodule-helpers.js")
          t.defineInteropFlag(n),
            t.export(n, "Icon123", () => i.default),
            t.export(n, "IconNumber123", () => i.default),
            t.export(n, "Icon360", () => l.default),
            t.export(n, "IconView360Arrow", () => l.default),
            t.export(n, "IconCodeAsterisk", () => p.default),
            ... Total extra 5391 lines of code
 var r = e("./icons/index.mjs"),
            c = e("./icons-list.mjs"),
            s = e("./icons/IconNumber123.mjs"),
            i = t.interopDefault(s),
            a = e("./icons/IconView360Arrow.mjs"),
            l = t.interopDefault(a),
            u = e("./icons/IconCodeAsterisk.mjs"),
           ... Total extra 10 582 lines of code
          "./icons/index.mjs": !1,
          "./icons-list.mjs": !1,
          "./icons/IconNumber123.mjs": !1,
          "./icons/IconView360Arrow.mjs": !1,
          "./icons/IconCodeAsterisk.mjs": !1,
          "./icons/IconRosetteDiscount.mjs": !1,
          "./icons/IconRosetteDiscountOff.mjs": !1,
           ... Total extra 5291 lines of code

So final bundle includes additional 21264 lines of code❗

Related to issue #664

Version

Latest

What OS are you seeing the problem on?

Linux, Other

What browsers are you seeing the problem on?

Microsoft Edge

Relevant log output

## Build without the library
> plasmo build "--verbose"

🟡 0      | Running command: build
🟣 Plasmo v0.87.1
🔴 The Browser Extension Framework
🔵 INFO   | Prepare to bundle the extension...
🟡 1      | Creating Manifest Factory...
🟡 2      | Ensure exists: /home/evaldas/build-perf-example/.plasmo
🟡 3      | /home/evaldas/build-perf-example/assets/icon.png found, creating resized icons
🟡 4      | Creating static templates for popup
🟡 5      | Creating static templates for options
🟡 6      | Creating static templates for newtab
🟡 7      | Creating static templates for devtools
🟡 8      | Creating static templates for sidepanel
🟡 9      | {
  messageHandlerList: [],
  externalMessageHandlerList: [],
  portHandlerList: []
}
🟡 10     | Hash changed, updating manifest
🔵 INFO   | Loaded environment variables from: []
🟡 0      | @plasmohq/parcel-transformer-manifest
🟡 1      | Adding icons
🟡 2      | Adding default_icon
🟡 3      | Adding default_popup
🟡 4      | + Finished transforming manifest
🟡 0      | @plasmohq/parcel-bundler
🟡 0      | @plasmohq/parcel-packager
🟡 0      | @plasmohq/parcel-optimizer-encapsulate popup.100f6462.js popup.[hash].js
🟡 0      | @plasmohq/optimizer-es:  popup.100f6462.js popup.[hash].js /home/evaldas/build-perf-example
🟡 1      | optimizer-es: use SWC for popup.[hash].js
🟢 DONE   | Finished in 1546ms!

## Build including the library
> plasmo build "--verbose"

🟡 0      | Running command: build
🟣 Plasmo v0.87.1
🔴 The Browser Extension Framework
🔵 INFO   | Prepare to bundle the extension...
🟡 1      | Creating Manifest Factory...
🟡 2      | Ensure exists: /home/evaldas/build-perf-example/.plasmo
🟡 3      | /home/evaldas/build-perf-example/assets/icon.png found, creating resized icons
🟡 4      | Creating static templates for popup
🟡 5      | Creating static templates for options
🟡 6      | Creating static templates for newtab
🟡 7      | Creating static templates for devtools
🟡 8      | Creating static templates for sidepanel
🟡 9      | {
  messageHandlerList: [],
  externalMessageHandlerList: [],
  portHandlerList: []
}
🟡 10     | Hash changed, updating manifest
🔵 INFO   | Loaded environment variables from: []
🟡 0      | @plasmohq/parcel-transformer-manifest
🟡 1      | Adding icons
🟡 2      | Adding default_icon
🟡 3      | Adding default_popup
🟡 4      | + Finished transforming manifest
🟡 0      | @plasmohq/parcel-bundler
🟡 0      | @plasmohq/parcel-packager
🟡 0      | @plasmohq/parcel-optimizer-encapsulate popup.100f6462.js popup.[hash].js
🟡 0      | @plasmohq/optimizer-es:  popup.100f6462.js popup.[hash].js /home/evaldas/build-perf-example
🟡 1      | optimizer-es: use SWC for popup.[hash].js
🟢 DONE   | Finished in 30099ms!

(OPTIONAL) Contribution

Code of Conduct

ayoung19 commented 3 weeks ago

Noticed the same thing when importing @tabler/icons-react as well. That library should be completely tree shakeable.

Evaldas-B commented 3 weeks ago

Noticed the same thing when importing @tabler/icons-react as well. That library should be completely tree shakeable.

It doesn't only happen with @tabler/icons-react, but since this library has a lot of components it effect build times drastically so its very noticeable. Same behavior with other libraries too.

ayoung19 commented 3 weeks ago

Were you able to find a workaround? I don't even mind the slow build for dev but if there is something I could hardcode to get it to minimize the production build that would be nice.

Evaldas-B commented 3 weeks ago

Were you able to find a workaround? I don't even mind the slow build for dev but if there is something I could hardcode to get it to minimize the production build that would be nice.

No, not really, what I've done is I've created a folder containing the Icons that I am using by manually copying and pasting them and importing icons from there, instead of installing the library. Works for now, but it's not going to be manageable for anything else than icons.