Skip to content

bug: Ionic standalone components are not treeshakable #28483

Closed as not planned
Closed as not planned

Description

@hakimio

Prerequisites

Ionic Framework Version

v7.x

Current Behavior

Ionic standalone components are not treeshakable.

Expected Behavior

Ionic standalone components are treeshakable.

Steps to Reproduce

  1. Clone ionic-treeshaking-test repo
  2. Build the project and check the resulting "Initial Total"
  3. Optionally switch from esbuild to webpack bundler and check the build size again
  4. Change git branch to ionic-module and build the project again
  5. Compare build sizes you get in previous steps

Code Reproduction URL

https://github.com/hakimio/ionic-treeshaking-test

Ionic Info

Ionic:

   Ionic CLI                     : 7.1.1
   Ionic Framework               : @ionic/angular 7.5.3
   @angular-devkit/build-angular : 17.0.0-rc.4
   @angular-devkit/schematics    : 16.2.9
   @angular/cli                  : 17.0.0-rc.4
   @ionic/angular-toolkit        : 10.0.0

Capacitor:

   Capacitor CLI      : 5.5.1
   @capacitor/android : not installed
   @capacitor/core    : 5.5.1
   @capacitor/ios     : not installed

Utility:

   cordova-res : 0.15.3
   native-run  : 1.7.4

System:

   NodeJS : v18.17.1
   npm    : 10.2.3
   OS     : Windows 10

Build sizes

Webpack + Ionic Module

Initial Chunk Files                   | Names                              |  Raw Size | Estimated Transfer Size
main.a536c9608db8fe42.js              | main                               | 438.12 kB |               112.26 kB
polyfills.53dd1ba240d556a9.js         | polyfills                          |  33.09 kB |                10.68 kB
styles.12498b9a067190a0.css           | styles                             |  26.31 kB |                 4.14 kB
runtime.70fad7281072f3ce.js           | runtime                            |   4.50 kB |                 2.17 kB

                                      | Initial Total                      | 502.02 kB |               129.25 kB

esbuild + Ionic Standalone components

Initial Chunk Files   | Names                |   Raw Size | Estimated Transfer Size
chunk-QON5UNTZ.js     | -                    |    1.24 MB |               185.56 kB
polyfills-FCOTMFN3.js | polyfills            |   32.81 kB |                10.63 kB
chunk-HCAOIOEU.js     | -                    |   32.75 kB |                10.89 kB
styles-EBGUPLIJ.css   | styles               |   26.83 kB |                 4.14 kB
main-LNWMOTZP.js      | main                 |   17.68 kB |                 5.11 kB
chunk-W37MDJIX.js     | -                    |   11.04 kB |                 3.95 kB
chunk-ARD6CFHF.js     | -                    |    9.94 kB |                 2.56 kB
chunk-Z4V4M3ZT.js     | -                    |    5.69 kB |                 2.09 kB
chunk-ARLVSRXN.js     | -                    |    3.98 kB |                 1.48 kB
chunk-WQAL34I6.js     | -                    |    1.67 kB |               661 bytes
chunk-ZDO5NYW7.js     | -                    |    1.05 kB |               530 bytes
chunk-QPVVTFFW.js     | -                    | 1022 bytes |              1022 bytes
chunk-WFGC6I42.js     | -                    |  941 bytes |               941 bytes
chunk-7KGURMOZ.js     | -                    |  908 bytes |               908 bytes
chunk-FQ65QLOX.js     | -                    |  762 bytes |               762 bytes
chunk-A73CKFRS.js     | -                    |  686 bytes |               686 bytes
chunk-J6ICYO4L.js     | -                    |  557 bytes |               557 bytes
chunk-4U6PRYVA.js     | -                    |  126 bytes |               126 bytes
chunk-LF5XB4YN.js     | -                    |   99 bytes |                99 bytes

                      | Initial Total        |    1.39 MB |               232.57 kB

Webpack + Ionic Standalone components

Initial Chunk Files           | Names                              |  Raw Size | Estimated Transfer Size
main.fdf3206ac410ddc6.js      | main                               | 743.21 kB |               143.91 kB
polyfills.f8bea4ae787ca74b.js | polyfills                          |  33.09 kB |                10.67 kB
styles.12498b9a067190a0.css   | styles                             |  26.31 kB |                 4.14 kB
runtime.600e94669b643e4d.js   | runtime                            |   2.88 kB |                 1.38 kB

                              | Initial Total                      | 805.49 kB |               160.10 kB

Activity

  1. self-assigned this
    on Nov 7, 2023
  2. liamdebeasi commented on Nov 7, 2023

    @liamdebeasi
    Contributor

    Thanks for following up here. I can reproduce the reported behavior with Webpack, but Ionic is working correctly here. I used https://www.npmjs.com/package/source-map-explorer to determine which components are being pulled into your build, and all of the components included are being used in your application. I did not identify any components being pulled into your build that were not being used in your application:

    image

    The Webpack + Ionic Module test you conducted is incomplete because it does not account for the lazy chunks that are pulled into the build, only the initial chunks. If you include the lazy chunks you'll see that the IonicModule bundle size is much larger than the Webpack + Standalone bundle size. I used the blank starter app in the example below, but the same concepts apply to your application:

    Standalone

    Initial Chunk Files           | Names             |  Raw Size | Estimated Transfer Size
    main.d5594a2760623012.js      | main              | 332.45 kB |                91.19 kB
    polyfills.06c05adc04920097.js | polyfills         |  33.16 kB |                10.72 kB
    styles.5e14a4afeec93aa2.css   | styles            |  26.21 kB |                 4.10 kB
    runtime.36a8f2b7985de7ae.js   | runtime           |   2.92 kB |                 1.42 kB
    
                                  | Initial Total     | 394.74 kB |               107.42 kB
    
    Lazy Chunk Files              | Names             |  Raw Size | Estimated Transfer Size
    594.6110149267714db0.js       | ios-transition-js |  10.20 kB |                 2.62 kB
    255.47eca8b531546ebc.js       | input-shims-js    |   4.92 kB |                 1.86 kB
    195.f213b6e63d9a44ac.js       | shadow-css-js     |   4.49 kB |                 1.92 kB
    595.977adb5f788382f5.js       | index9-js         |   1.87 kB |               823 bytes
    957.7b7ceefd2d86cff6.js       | home-home-page    |   1.41 kB |               681 bytes
    409.b59827dbdd4bb461.js       | keyboard2-js      |   1.25 kB |               578 bytes
    250.d2cca6f4e02c8384.js       | md-transition-js  |   1.04 kB |               485 bytes
    236.7408419668ab83a9.js       | swipe-back-js     | 730 bytes |               456 bytes
    common.543aad3159122aaf.js    | common            | 591 bytes |               321 bytes
    313.2235c013565f5f16.js       | status-tap-js     | 531 bytes |               310 bytes
    

    Module

    Initial Chunk Files                   | Names                   |  Raw Size | Estimated Transfer Size
    main.4892171a0bb2708c.js              | main                    | 379.88 kB |               101.12 kB
    polyfills.441dd4ca9dc0674f.js         | polyfills               |  33.16 kB |                10.70 kB
    styles.5e14a4afeec93aa2.css           | styles                  |  26.21 kB |                 4.10 kB
    runtime.bc10ee425d3122f5.js           | runtime                 |   4.50 kB |                 2.17 kB
    
                                          | Initial Total           | 443.75 kB |               118.08 kB
    
    Lazy Chunk Files                      | Names                   |  Raw Size | Estimated Transfer Size
    polyfills-core-js.93f56369317b7a8e.js | polyfills-core-js       |  91.83 kB |                27.76 kB
    5962.26a36d7c5dd42a5e.js              | -                       |  75.90 kB |                 8.43 kB
    7059.a03624e0e25e469e.js              | -                       |  71.91 kB |                12.73 kB
    3734.9196f324d7e3fba0.js              | -                       |  53.59 kB |                 5.85 kB
    4530.e1fb5e14f312e06e.js              | -                       |  49.42 kB |                 6.01 kB
    6754.3d2ddb0f6f26c8d1.js              | -                       |  42.48 kB |                 7.04 kB
    5860.d14fe139a7d3b98c.js              | -                       |  39.22 kB |                 8.36 kB
    6304.c4731ff30e6c65dc.js              | -                       |  35.92 kB |                 6.12 kB
    7666.680482ec20e64832.js              | -                       |  32.23 kB |                 5.85 kB
    8577.24c72092346333b6.js              | -                       |  26.90 kB |                 6.59 kB
    3672.648d8991401855e9.js              | -                       |  26.66 kB |                 4.83 kB
    1372.578a3e182236f09f.js              | -                       |  26.03 kB |                 5.09 kB
    3998.716c7df843db5565.js              | -                       |  25.25 kB |                 4.10 kB
    8866.e511343070169fd2.js              | -                       |  25.06 kB |                 4.04 kB
    7219.7b2a70b9bdb0b926.js              | -                       |  23.97 kB |                 4.72 kB
    185.218164636b1ff549.js               | -                       |  23.55 kB |                 5.71 kB
    8382.8ec86099873c5d35.js              | -                       |  22.91 kB |                 4.78 kB
    4090.565dc53e9b520a9b.js              | -                       |  22.35 kB |                 3.28 kB
    4087.c20379f95e7e8a45.js              | -                       |  21.92 kB |                 3.57 kB
    4458.2c241c62a0a4995b.js              | -                       |  21.57 kB |                 3.86 kB
    9882.7e1c0d280b7dfbf5.js              | -                       |  21.05 kB |                 3.82 kB
    8633.42ccdb2b6e502065.js              | -                       |  19.61 kB |                 3.69 kB
    5454.a5aa32778c61d1f5.js              | -                       |  19.10 kB |                 1.87 kB
    7635.07cd2c377262bead.js              | -                       |  18.98 kB |                 3.11 kB
    6642.f758d95cf057640d.js              | -                       |  18.21 kB |                 4.23 kB
    polyfills-dom.516ff539260f3e0d.js     | polyfills-dom           |  18.05 kB |                 5.03 kB
    common.0f990b8d608def44.js            | common                  |  17.98 kB |                 5.22 kB
    9857.58aa1e7e8f55ac26.js              | -                       |  13.54 kB |                 2.74 kB
    9302.051d13bc0d62e768.js              | -                       |  12.71 kB |                 4.14 kB
    8484.651e9934198892f2.js              | -                       |  11.99 kB |                 2.78 kB
    5675.3a91fb4bbe336640.js              | -                       |  11.83 kB |                 3.69 kB
    505.f5ba46f0043a691e.js               | -                       |  11.75 kB |                 2.25 kB
    4764.08765e46fc281de8.js              | -                       |  11.37 kB |                 3.84 kB
    3150.c2d8aac1232799cd.js              | -                       |  10.96 kB |                 2.10 kB
    9820.5f14657bd57a2b9c.js              | -                       |  10.83 kB |                 2.10 kB
    8594.6e8e4b8ff83f929b.js              | ios-transition-js       |  10.21 kB |                 2.62 kB
    3483.db182d404614c76c.js              | -                       |   9.28 kB |                 2.37 kB
    1315.77f2bbf7f791d2ff.js              | -                       |   8.54 kB |                 1.32 kB
    962.04956d1050772698.js               | ios-transition-js       |   8.14 kB |                 2.93 kB
    9992.7e1a149a6074182f.js              | -                       |   7.34 kB |                 2.16 kB
    6673.68c644335f5fcd26.js              | -                       |   6.92 kB |                 1.23 kB
    9588.d7ad392119829517.js              | -                       |   6.23 kB |                 1.53 kB
    433.4777f1a2847ebbed.js               | -                       |   6.09 kB |                 1.78 kB
    9352.22f330ce1a3974c2.js              | -                       |   5.63 kB |                 1.34 kB
    9793.8c0bea4005404a1e.js              | -                       |   5.49 kB |                 1.24 kB
    2975.31d7e507323b30c6.js              | -                       |   5.34 kB |                 1.86 kB
    8895.62c48967770c74c4.js              | input-shims-d0c93e5d-js |   4.92 kB |                 1.86 kB
    2841.16a9ca4f58ff6b97.js              | -                       |   3.84 kB |                 1.29 kB
    3544.4e88410b1a317292.js              | -                       |   3.82 kB |               982 bytes
    7465.6f9888d169ed189d.js              | -                       |   3.05 kB |               933 bytes
    8058.92bc3c5df214f8f0.js              | index-f0cc4e14-js       |   1.87 kB |               825 bytes
    6260.086faa43d8405a90.js              | home-home-module        |   1.76 kB |               751 bytes
    1745.eb610c10935535e5.js              | -                       |   1.71 kB |               678 bytes
    469.87749c99c5bf436c.js               | -                       |   1.50 kB |               509 bytes
    7250.dd7a58df6c68d73e.js              | md-transition-js        |   1.04 kB |               486 bytes
    8811.6297ceb2b06f67fc.js              | -                       |   1.00 kB |               572 bytes
    9611.4d80f605bc6acb92.js              | status-tap-4e96ecf3-js  | 529 bytes |               323 bytes
    

    In your application, the main.*.js chunk for standalone is indeed larger than the module main.*.js chunk. This is due to a difference in how the components are loaded. With the standalone build, the components you need are directly imported into your application. This approach allows for a smaller bundle size potentially at the expense of a larger initial chunk. With the module build, the components are lazily loaded as needed. This approach allows for a smaller initial chunk at the expense of increasing the entire build size.

    Ionic does not control how your application is bundled, but I can confirm that the unused Ionic components are being correctly removed from your application build.

    I am going to close this, but let me know if you have any questions.

  3. removed their assignment
    on Nov 7, 2023
  4. ionitron-bot commented on Dec 7, 2023

    @ionitron-bot

    Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

  5. locked and limited conversation to collaborators on Dec 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions