Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

esbuild: support for dynamic imports to load a lazy chunk #25492

Closed
jcompagner opened this issue Jul 5, 2023 · 8 comments
Closed

esbuild: support for dynamic imports to load a lazy chunk #25492

jcompagner opened this issue Jul 5, 2023 · 8 comments

Comments

@jcompagner
Copy link

jcompagner commented Jul 5, 2023

Command

build

Description

in our code we use this (but we have more constructs like this to load locale or language specific files)

 return new Promise<string>((resolve, reject) => {
            import(
                `@/../../node_modules/@angular/common/locales/${localeId}.mjs`).then(
                module => {
                    registerLocaleData(module.default, localeId);
                    resolve(localeId);
                },
                () => {
                    import(`@/../../node_modules/@angular/common/locales/${language.toLowerCase()}.mjs`).then(module => {
                        registerLocaleData(module.default, localeId.split('-')[0]);
                        resolve(language.toLowerCase());
                    }, reject);
                });
        });

but that doesn't seem to work in an esbuild.

is there another way? The none esbuild will generate for our product a huge number of files because of this (all the locale files that match that pattern)

Describe the solution you'd like

that the above import( string with variable) does work to load in specific lazy chunks

Describe alternatives you've considered

No response

@JeanMeche
Copy link
Member

What do you mean by it doesn't work ? What kind of issues do you have ?

@alan-agius4
Copy link
Collaborator

Dynamic imports with template literals is a Webpack specific feature which is not supported by esbuild. See: evanw/esbuild#56

Instead what you can do is to copy the locale data as assets and import those.

@alan-agius4 alan-agius4 closed this as not planned Won't fix, can't repro, duplicate, stale Jul 5, 2023
@jcompagner
Copy link
Author

jcompagner commented Jul 5, 2023

i will investigate a bit more but what is generated is way less:

esbuild:

Initial Chunk Files               | Names         |  Raw Size
chunk-AOGI3VZL.js                 | -             |   1.27 MB |
styles.css                        | styles        | 834.78 kB |
polyfills.js                      | polyfills     | 446.01 kB |
main.js                           | main          | 152.75 kB |
chunk-J47SHVCY.js                 | -             |   4.33 kB |
chunk-OURP4XV6.js                 | -             | 148 bytes |

                                  | Initial Total |   2.68 MB

Lazy Chunk Files                  | Names         |  Raw Size
chunk-AQQUMGC3.js                 | -             |   8.95 MB |
chunk-XFZYOI43.js                 | -             | 105.51 kB |
chunk-QJEUDAUI.js                 | -             |  54.24 kB |
servoydesigner.module-P6ORJIPI.js | -             |  36.85 kB |
lib-6YH67MBL.js                   | -             |  30.71 kB |
servoy.module-VG3PFEUB.js         | -             |  26.93 kB |
lib-PJWNJSOV.js                   | -             |  17.67 kB |
lib-N2JFDYMB.js                   | -             |   1.41 kB |
chunk-LEKTZCTL.js                 | -             | 674 bytes |

but a normal build generates:

Raw Size
vendor.js                                                                                               | vendor                         |
 2.57 MB |
styles.css                                                                                              | styles                         | 832.31 kB |
polyfills.js                                                                                            | polyfills                      | 632.92 kB |
runtime.js                                                                                              | runtime                        |  14.30 kB |
main.js                                                                                                 | main                           |
 8.64 kB |

                                                                                                        | Initial Total                  |
 4.02 MB

Lazy Chunk Files                                                                                        | Names                          |  Raw Size
default-src_ngclient_allcomponents_module_ts-src_ngclient_allservices_service_ts-src_servoyco-f6c863.js | designer-servoydesigner-module |  11.89 MB |
src_designer_servoydesigner_module_ts.js                                                                | designer-servoydesigner-module |  70.78 kB |
src_ngclient_servoy_module_ts.js                                                                        | ngclient-servoy-module         |  63.11 kB |
node_modules_uppy_webcam_lib_index_js.js                                                                | uppy-webcam                    |  46.60 kB |
node_modules_uppy_screen-capture_lib_index_js.js                                                        | uppy-screen-capture            |  28.42 kB |
node_modules_uppy_locales_lib_uk_UA_js.js                                                               | -                              |  13.79 kB |
node_modules_uppy_locales_lib_hi_IN_js.js                                                               | -                              |  13.72 kB |
node_modules_uppy_locales_lib_th_TH_js.js                                                               | -                              |  11.54 kB |
<  a lot of files snipped  >
node_modules_angular_common_locales_ar-IQ_mjs.js                                                        | -                              |
 3.96 kB |
node_modules_angular_common_locales_dz_mjs.js                                                           | -                              |
 3.95 kB |
node_modules_angular_common_locales_fi_mjs.js                                                           | -                              |
 3.95 kB |
node_modules_angular_common_locales_ccp-IN_mjs.js                                                       | -                              |
 3.91 kB |
node_modules_angular_common_locales_ccp_mjs.js                                                          | -                              |
 3.88 kB |
node_modules_angular_common_locales_bo-IN_mjs.js                                                        | -                              |
 3.81 kB |
node_modules_angular_common_locales_bo_mjs.js                                                           | -                              |
 3.78 kB |
node_modules_angular_common_locales_sq-MK_mjs.js                                                        | -                              |
 3.74 kB |
node_modules_angular_common_locales_sq-XK_mjs.js                                                        | -                              |
 3.72 kB |
node_modules_angular_common_locales_sq_mjs.js                                                           | -                              |
 3.71 kB |
node_modules_angular_common_locales_si_mjs.js                                                           | -                              |
 3.65 kB |
node_modules_angular_common_locales_be-tarask_mjs.js                                                    | -                              |
<  a lot of files snipped  >

so you can see from angular_commons every locale has 1 js file also included in the output
that we then dynamically load it again

We have no idea what users are using our product, we can't hard code that at all so all the language/locale stuff is loaded when needed for the locale/language the user is in

thats stuff of angular itself from "common" but also "uppy", "numbro"

so with an esbuild i don't see all those files generated, so my assumption is that they really don't work and i also get an error that points to that direction

i get:

Unhandled Promise rejection: Could not set Locale because angular locale could not be loaded. ; Zone: <root> ; Task: Promise.then ; Value: Could not set Locale because angular locale could not be loaded

exactly from the stack of the above code, so those 2 imports are both failing and i get that error.

@clydin
Copy link
Member

clydin commented Jul 5, 2023

This is a known issue. For additional information please see the developer preview guide found here: https://angular.io/guide/esbuild#runtime-evaluated-dynamic-import-expressions

@jcompagner
Copy link
Author

Dynamic imports with template literals is a Webpack specific feature which is not supported by esbuild. See: evanw/esbuild#56

Instead what you can do is to copy the locale data as assets and import those.

hmm so i need to copy it all my self in all the dynamic imports we have throughout our code (which is quite a few places)
and make sure that those are all copied to a location and then don't import like:

import(`@/../../node_modules/@angular/common/locales/${localeId}.mjs`)

but if i copied it with assets to the root like "locales" folder

import(`locales/${localeId}.mjs`)

that is quite a change for us..

@jcompagner
Copy link
Author

jcompagner commented Jul 5, 2023

This is a known issue. For additional information please see the developer preview guide found here: https://angular.io/guide/esbuild#runtime-evaluated-dynamic-import-expressions

ai, thats even worse.. because you can't also use expressions?
(even if i would copy it manually?)
Then we have to wait for esbuild to support that and use the current builder for that time
Because using it statically is not an option for us, that is hardcoding thousands of lines (1271 to be specific)

@clydin
Copy link
Member

clydin commented Jul 5, 2023

From the guide:

Dynamic import expressions that do not contain static values will be kept in their original form and not processed at build time.

Imports kept in their original form can contain whatever JavaScript allows.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Aug 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants