Super slow HMR in meteor 3.0

Hi,

I observed that hot-module-replacement is super slow in my React+Mui6 demo project, once I update to 3.0.3. You can find my repo here https://github.com/bratelefant/simple-app. Simply run it via meteor run.

I currently downgraded to 2.16. Here, HMR takes less than a second. After a simple meteor update, HMR takes ~7 secs to display changes (eg. add a single character to Dummy.jsx) in the browser.

When I use METEOR_PROFILE=20 meteor run, I get approximately the same rebuild times as in 2.16 or even better.

Is this a know issue?

Here’s some profiling, this is from 2.16

(#8) Profiling: ProjectContext prepareProjectForBuild
| 
| ProjectContext prepareProjectForBuild............................45 ms (1)
| └─ _downloadMissingPackages......................................38 ms (1)
|    └─ Isopack.readMetadataFromDirectory                          23 ms (86)
| 
| Top leaves:
| 
| (#8) Total: 45 ms (ProjectContext prepareProjectForBuild)
| 
| (#9) Profiling: Rebuild App
| 
| Rebuild App...................................................1,704 ms (1)
| └─ bundler.bundle.............................................1,704 ms (1)
|    ├─ compiler.compile(the app).................................417 ms (1)
|    │  └─ compileUnibuild (the app)                              417 ms (4)
|    ├─ bundler.bundle..makeClientTarget........................1,250 ms (2)
|    │  └─ Target#make..........................................1,250 ms (2)
|    │     ├─ Target#_emitResources.............................1,059 ms (2)
|    │     │  ├─ PackageSourceBatch.computeJsOutputFilesMap.....1,022 ms (2)
|    │     │  │  └─ ImportScanner#scanImports for the app.........939 ms (2)
|    │     │  │     ├─ ImportScanner#resolve                      189 ms (82390)
|    │     │  │     ├─ ImportScanner#getAbsModuleId                50 ms (22984)
|    │     │  │     ├─ ImportScanner#realPath                     210 ms (22984)
|    │     │  │     ├─ ImportScanner#readFile                      47 ms (22984)
|    │     │  │     ├─ DefaultHandlers.js.........................106 ms (22984)
|    │     │  │     │  ├─ reifyCompileWithCache                    33 ms (22984)
|    │     │  │     │  └─ other DefaultHandlers.js                 74 ms
|    │     │  │     └─ other ImportScanner#scanImports for the app 321 ms
|    │     │  └─ PackageSourceBatch#getResources...................23 ms (135)
|    │     │     └─ PackageSourceBatch#_linkJS                     22 ms (135)
|    │     ├─ Target#minifyJs......................................83 ms (2)
|    │     │  └─ sha512                                            82 ms (137)
|    │     └─ sha512                                               82 ms (139)
|    └─ bundler writeTargetToPath..................................22 ms (2)
|       └─ ClientTarget#write                                      22 ms (2)
| 
| Top leaves:
| other ImportScanner#scanImports for the app................321 ms (2)
| ImportScanner#realPath.....................................213 ms (23518)
| sha512.....................................................164 ms (290)
| 
| (#9) Total: 1,704 ms (Rebuild App)

This is from 3.0.3

| (#6) Profiling: ProjectContext prepareProjectForBuild
| 
| ProjectContext prepareProjectForBuild                             1 ms (1)
| 
| Top leaves:
| 
| (#6) Total: 1 ms (ProjectContext prepareProjectForBuild)
| 
| (#7) Profiling: Rebuild App
| 
| Rebuild App                                                      11 ms (1)
| Isopack#getUnibuildAtArch                                         5 ms (5998)
| Isopack#ensurePluginsInitialized                                  0 ms (399)
| PackageSource#_findSources for os                                 2 ms (1)
| files.realpath                                                    0 ms (4)
| files.readdirWithTypes                                            0 ms (4)
| optimistic readFile                                               0 ms (1)
| safeWatcher.watch                                                 0 ms (1)
| compileUnibuild (the app)                                         0 ms (3)
| PackageSource#_findSources for web.browser                        1 ms (1)
| PackageSource#_findSources for web.browser.legacy                 1 ms (1)
| PackageSource#_findSources for web.cordova                        1 ms (1)
| compiler.lint(the app)                                            0 ms (1)
| bundler.bundle..makeClientTarget                                  0 ms (2)
| Target#_runCompilerPlugins                                        0 ms (2)
| plugin ecmascript                                                 1 ms (2)
| plugin typescript                                                 6 ms (2)
| plugin static-html                                                1 ms (2)
| plugin meteor                                                     0 ms (2)
| Target#_emitResources                                             1 ms (2)
| sha1                                                             14 ms (1891)
| files.stat                                                        1 ms (94)
| ImportScanner#getAbsModuleId                                     51 ms (24204)
| ImportScanner#realPath                                          220 ms (24204)
| ImportScanner#scanImports for modules                             0 ms (2)
| ImportScanner#findImportedModuleIdentifiers                      15 ms (23752)
| jsAnalyze.parse                                                  86 ms (178)
| findImportedModuleIdentifiersVisitor                              5 ms (178)
| ImportScanner#resolve                                           203 ms (84320)
| ImportScanner#readFile                                           47 ms (23528)
| DefaultHandlers.js                                               62 ms (23526)
| reifyCompileWithCache                                            32 ms (23046)
| ImportScanner#scanImports for es5-shim                            0 ms (2)
| ImportScanner#scanImports for modern-browsers                     0 ms (2)
| ImportScanner#scanImports for promise                             0 ms (2)
| ImportScanner#scanImports for ecmascript-runtime-client           0 ms (2)
| ImportScanner#scanImports for hot-module-replacement              0 ms (2)
| ImportScanner#scanImports for react-fast-refresh                  0 ms (2)
| ImportScanner#scanImports for babel-runtime                       0 ms (2)
| ImportScanner#scanImports for fetch                               0 ms (2)
| ImportScanner#scanImports for dynamic-import                      0 ms (2)
| ImportScanner#scanImports for base64                              0 ms (2)
| Babel.compile                                                     7 ms (168)
| ImportScanner#scanImports for ejson                               0 ms (2)
| ImportScanner#scanImports for diff-sequence                       0 ms (2)
| ImportScanner#scanImports for geojson-utils                       0 ms (2)
| ImportScanner#scanImports for id-map                              0 ms (2)
| ImportScanner#scanImports for random                              0 ms (2)
| ImportScanner#scanImports for mongo-id                            0 ms (2)
| ImportScanner#scanImports for ordered-dict                        0 ms (2)
| ImportScanner#scanImports for tracker                             0 ms (2)
| ImportScanner#scanImports for minimongo                           0 ms (2)
| ImportScanner#scanImports for check                               0 ms (2)
| ImportScanner#scanImports for retry                               0 ms (2)
| ImportScanner#scanImports for callback-hook                       0 ms (2)
| ImportScanner#scanImports for ddp-common                          0 ms (2)
| ImportScanner#scanImports for reload                              0 ms (2)
| ImportScanner#scanImports for socket-stream-client                0 ms (2)
| ImportScanner#scanImports for ddp-client                          0 ms (2)
| ImportScanner#scanImports for allow-deny                          0 ms (2)
| ImportScanner#scanImports for mongo-dev-server                    0 ms (2)
| ImportScanner#scanImports for logging                             0 ms (2)
| ImportScanner#scanImports for mongo                               0 ms (2)
| ImportScanner#scanImports for minifier-css                        0 ms (2)
| ImportScanner#scanImports for react-meteor-data                   0 ms (2)
| ImportScanner#scanImports for dev-error-overlay                   0 ms (2)
| ImportScanner#scanImports for ddp-rate-limiter                    0 ms (2)
| ImportScanner#scanImports for url                                 0 ms (2)
| ImportScanner#scanImports for accounts-base                       0 ms (2)
| ImportScanner#scanImports for accounts-password                   0 ms (2)
| ImportScanner#scanImports for oauth                               0 ms (2)
| ImportScanner#scanImports for accounts-oauth                      0 ms (2)
| ImportScanner#scanImports for service-configuration               0 ms (2)
| ImportScanner#scanImports for oauth2                              0 ms (2)
| ImportScanner#scanImports for github-oauth                        0 ms (2)
| ImportScanner#scanImports for accounts-github                     0 ms (2)
| ImportScanner#scanImports for webapp                              0 ms (2)
| ImportScanner#scanImports for autoupdate                          0 ms (2)
| ImportScanner#scanImports for the app                             0 ms (2)
| files.readFile                                                    2 ms (4)
| ImportScanner#scanMissingModules for the app                      0 ms (4)
| DefaultHandlers.json                                              0 ms (2)
| ImportScanner#scanMissingModules for modules                      0 ms (2)
| ImportScanner#scanMissingModules for ejson                        0 ms (2)
| ImportScanner#scanMissingModules for random                       0 ms (2)
| ImportScanner#scanMissingModules for callback-hook                0 ms (2)
| ImportScanner#scanMissingModules for mongo-id                     0 ms (2)
| ImportScanner#scanMissingModules for ddp-common                   0 ms (2)
| ImportScanner#scanMissingModules for socket-stream-client         0 ms (2)
| ImportScanner#scanMissingModules for minimongo                    0 ms (2)
| ImportScanner#scanMissingModules for logging                      0 ms (2)
| ImportScanner#scanMissingModules for react-meteor-data            0 ms (2)
| ImportScanner#scanMissingModules for retry                        0 ms (2)
| PackageSourceBatch._watchOutputFiles                             18 ms (2)
| PackageSourceBatch#getResources                                  14 ms (137)
| linker File#getPrelinkedOutput                                    0 ms (2)
| Target#minifyJs..................................................37 ms (2)
| └─ sha512                                                        36 ms (139)
| ClientTarget#minifyCss                                            0 ms (2)
| createCacheKey                                                    0 ms (2)
| watchAndHashDeps                                                  0 ms (1)
| Target#rewriteSourceMaps                                          0 ms (2)
| sha512                                                           36 ms (153)
| bundler writeTargetToPath                                         0 ms (2)
| ClientTarget#write                                                0 ms (2)
| bundler writeFile                                                 0 ms (153)
| Builder#_ensureDirectory                                          0 ms (153)
| Builder#write                                                     3 ms (70)
| files.writeFile                                                   0 ms (2)
| files.rename                                                      0 ms (2)
| Builder#complete                                                  0 ms (2)
| 
| Top leaves:
| 
| (#7) Total: 887 ms (Rebuild App)
1 Like

I can confirm this for all my Meteor 3 + React + MUI projects.

Sorry, I cannot give a solution, but this just reminded me of my car that provided good emission results only when being tested for emission :rofl:

1 Like

Meteor 3.0.3 + React 18 + MUI 5. It took ~7 seconds.

The Rebuild App step took only 500 - 700ms on my machine. But the time delay from above step took 4 - 5 seconds.

| (#6) Total: 0 ms (ProjectContext prepareProjectForBuild)
| 
| (#7) Profiling: Rebuild App

It took 4 - 5 SECONDS to jump from #6 to #7.

2 Likes

(post deleted by author)

One common performance issue with the MUI library in Meteor is that @mui/icons-material is quite heavy. Importing it eagerly from the index makes the bundles and related processes larger, especially without using specific paths, a Babel import transformation plugin, or modern bundler tree shaking.

In your code I saw a line of code importing eagerly:

Try using import ListAltIcon from "@mui/icons-material/ListAlt instead, and see if the problem persist. Additionally, consider removing dependencies from the project one by one, then re-run it to identify which one is causing the issue.

If the problem continues, we’ll need to investigate it as part of our performance work. I’ve made some notes on this. Thanks for setting up the environment. We’ll follow up once we have more information.

1 Like

with --verbose --no-release-check options, I got this between #6 and #7:

Local package version is up-to-date: accounts-base@3.0.2
Local package version is up-to-date: accounts-password@3.0.2
Local package version is up-to-date: aldeed:collection2@4.0.3
Local package version is up-to-date: aldeed:simple-schema@1.13.1
Local package version is up-to-date: allow-deny@2.0.0
Local package version is up-to-date: autoupdate@2.0.0
Local package version is up-to-date: babel-compiler@7.11.0
Local package version is up-to-date: babel-runtime@1.5.2
Local package version is up-to-date: base64@1.0.13
Local package version is up-to-date: binary-heap@1.0.12
Local package version is up-to-date: blaze-tools@2.0.0
Local package version is up-to-date: boilerplate-generator@2.0.0
Local package version is up-to-date: caching-compiler@2.0.0
Local package version is up-to-date: caching-html-compiler@2.0.0
Local package version is up-to-date: callback-hook@1.6.0
Local package version is up-to-date: check@1.4.2
Local package version is up-to-date: core-runtime@1.0.0
Local package version is up-to-date: ddp@1.4.2
Local package version is up-to-date: ddp-client@3.0.1
Local package version is up-to-date: ddp-common@1.4.4
Local package version is up-to-date: ddp-rate-limiter@1.2.2
Local package version is up-to-date: ddp-server@3.0.1
Local package version is up-to-date: diff-sequence@1.1.3
Local package version is up-to-date: dynamic-import@0.7.4
Local package version is up-to-date: ecmascript@0.16.9
Local package version is up-to-date: ecmascript-runtime@0.8.2
Local package version is up-to-date: ecmascript-runtime-client@0.12.2
Local package version is up-to-date: ecmascript-runtime-server@0.11.1
Local package version is up-to-date: ejson@1.1.4
Local package version is up-to-date: email@3.1.0
Local package version is up-to-date: es5-shim@4.8.1
Local package version is up-to-date: facts-base@1.0.2
Local package version is up-to-date: fetch@0.1.5
Local package version is up-to-date: geojson-utils@1.0.12
Local package version is up-to-date: hot-code-push@1.0.5
Local package version is up-to-date: hot-module-replacement@0.5.4
Local package version is up-to-date: html-tools@2.0.0
Local package version is up-to-date: htmljs@2.0.1
Local package version is up-to-date: id-map@1.2.0
Local package version is up-to-date: inter-process-messaging@0.1.2
Local package version is up-to-date: launch-screen@2.0.1
Local package version is up-to-date: localstorage@1.2.1
Local package version is up-to-date: logging@1.3.5
Local package version is up-to-date: meteor@2.0.1
Local package version is up-to-date: meteor-base@1.5.2
Local package version is up-to-date: meteortesting:browser-tests@1.7.0
Local package version is up-to-date: meteortesting:mocha@3.2.0
Local package version is up-to-date: meteortesting:mocha-core@8.3.1-beta300.0
Local package version is up-to-date: minhna:connection-status-react@0.3.1
Local package version is up-to-date: minifier-css@2.0.0
Local package version is up-to-date: minifier-js@3.0.0
Local package version is up-to-date: minimongo@2.0.1
Local package version is up-to-date: mobile-experience@1.1.2
Local package version is up-to-date: mobile-status-bar@1.1.1
Local package version is up-to-date: modern-browsers@0.1.11
Local package version is up-to-date: modules@0.20.1
Local package version is up-to-date: modules-runtime@0.13.2
Local package version is up-to-date: modules-runtime-hot@0.14.3
Local package version is up-to-date: mongo@2.0.2
Local package version is up-to-date: mongo-decimal@0.1.4
Local package version is up-to-date: mongo-dev-server@1.1.1
Local package version is up-to-date: mongo-id@1.0.9
Local package version is up-to-date: npm-mongo@4.17.4
Local package version is up-to-date: ordered-dict@1.2.0
Local package version is up-to-date: promise@1.0.0
Local package version is up-to-date: raix:eventemitter@1.0.0
Local package version is up-to-date: random@1.2.2
Local package version is up-to-date: rate-limit@1.1.2
Local package version is up-to-date: react-fast-refresh@0.2.9
Local package version is up-to-date: react-meteor-data@3.0.2
Local package version is up-to-date: reactive-var@1.0.13
Local package version is up-to-date: reload@1.3.2
Local package version is up-to-date: retry@1.1.1
Local package version is up-to-date: routepolicy@1.1.2
Local package version is up-to-date: server-render@0.4.2
Local package version is up-to-date: sha@1.0.10
Local package version is up-to-date: shell-server@0.6.0
Local package version is up-to-date: socket-stream-client@0.5.3
Local package version is up-to-date: spacebars-compiler@2.0.0
Local package version is up-to-date: standard-minifier-css@1.9.3
Local package version is up-to-date: standard-minifier-js@3.0.0
Local package version is up-to-date: static-html@1.3.3
Local package version is up-to-date: templating-tools@2.0.0
Local package version is up-to-date: tmeasday:check-npm-versions@0.3.2
Local package version is up-to-date: tracker@1.3.4
Local package version is up-to-date: typescript@5.4.3
Local package version is up-to-date: underscore@1.6.4
Local package version is up-to-date: url@1.3.3
Local package version is up-to-date: webapp@2.0.2
Local package version is up-to-date: webapp-hashing@1.1.2
Local package version is up-to-date: zodern:types@1.0.13
Doing HTTP request:  POST
https://www.meteor.com/oauth2/authorize?state=151a2***&response_type=code&client_id=LdpZEt7ubqXAfkDJ2&redirect_uri=https%3A%2F%2Factivity.meteor.com%2F_oauth%2Fmeteor-developer%3Fclose
Doing HTTP request:  GET
https://activity.meteor.com/_oauth/meteor-developer?close=&state=151a2***&code=Q8pqpR2fs6Jf3hDyB&only_credential_secret_for_test=1

I’m not sure if --no-release-check works.
And if we could disable some HTTP requests, it would improve few seconds.

I simply add this to my /etc/hosts file, now it took only 3 seconds (vs 7 seconds before) to display changes.

# test meteor build
127.0.0.1       www.meteor.com  activity.meteor.com

Do you use the app mentioned in the author’s message for this issue, or one of your own?

Based on your tests, does this seem like a network issue? Does it happen with all your projects or just with this one using “Meteor 3.0.3 + React 18 + MUI 5”?

Since this post suggests it’s related to MUI, I thought it was more of a build issue than a network problem. Anyway, my suggestion above is worth to try.

The part I mentioned above is just about meteor-tool package. Not the network issue.
If I add

recordPackageUsage: false,

after this line: meteor/tools/cli/commands.js at devel · meteor/meteor · GitHub
It will look like this:

        cordovaRunner: cordovaRunner,
        recordPackageUsage: false,
        onBuilt: function () {

It will skip those http requests.

Hi, already changed the imports to those recommended by mui, couldn’t observe any changes though.

If you grep scan your project, can you find any usages of import * ?
Just a small check in case it’s mass importing all of MUI.

I can confirm this had the same effect on my project. 4-5 seconds now instead of 7-8 before the change.

Same here. I made sure everything is imported default and not name-imported. This is a continuous check from the start of the projects in order to ensure bundles remain as small as possible.

1 Like

Don‘t import like that, and i guess this can‘t be the cause of this, as in 2.16 the issue doesn‘t exist with the same codebase.

Yes, that’s exactly the point where the extra wait time comes from, I also observed that. #6 and #7 themselves are as quick as on 2.16

Same issue here. I hope the team is trying fix this. Development takes so much time now…

Could you please detail your stack?! Meteor 3, React 18?! MUI?

Meteor 3.0.3, react 17, mui 5

We have started slow process to unmeteorize our project, this will take at least a year with our small team