Loadable-components: Uncaught TypeError: Cannot read property 'Symbol(loadable)' of undefined

Created on 21 Jul 2017  路  23Comments  路  Source: gregberge/loadable-components

Problem occurs while I work with server render and dynamic client code from webpack. Seems I have difference in module numbers when HMR recompile my client code.
Server rendering works throw babel-node and don't need webpack build.

/* eslint-env browser */
function loadComponents() {
  if (typeof window === 'undefined') {
    throw new Error('`loadComponents` must be called client-side: `window` is undefined');
  }

  var ids = window[_constants.COMPONENT_IDS] || [];
  return Promise.all(ids.map(function (id) {
    return componentTracker.get(id)[_constants.LOADABLE]().load(); // error here
  }));
}

HTML contains IDS
<script>window.__LOADABLE_COMPONENT_IDS__ = [6553];</script>

Thanks!

Most helpful comment

A disclamer about this in README.md could save some time and headaches

All 23 comments

Hello, can you please give me the full environment? 6553 is very huge number, I don't think you have 6553 code splitted modules!

I have only 4 chunks. I can't show you full code because I already switch it to my own solution.

Can you describe some parts of business logic?

  • server renders html after getLoadableState() which needed for loadableState.getScriptTag()
  • getScriptTag() return some components IDs
  • page loads, loadComponents() loads components with IDs from previous step. Why do we need that? I thought that BrowserRouter should load modules according to routing.

So, why we need loadComponents and components IDs when we have BrowserRouter

It is needed to prevent the page blink at load. We have to require all modules before starting to render application.

I think you have a problem of server-side module caching, that's why the id is 6553.

I render server side (in development) using babel-node without webpack. Maybe problem there. What do you think?

I am doing the same and I don't have any problem...

Have you solved your problem? I would be happy to see all the stack to understand the problem. Do you have Hangout?

I didn't solve it. I move to my own solution. It's more verbose but without loop over the components tree. I download component corresponding to current route.
Client and server render also without promise resolving. Several routing files allows to achieve that.

@max-mykhailenko not very scalable but it works ;)

I'm having this same issue. Any resolution to this?

Seems like componentTracker.get(id) is empty. Also the id seems to change every render, even on the same page, so maybe loadable state is out of sync somehow?

Yes probably, I need to investigate it more deeply. Do you have any example repo to reproduce it?

I also have it, so far I see that I have 16 bundles and it fails when it tries to get bundle with id 17 that doesn't exist.

Added:
When I change to only one dynamic bundle it tries to get bundle with id 1 and fails.
Seems like loadable() is called twice in some cases therefore track() is called twice and id becomes incorrect

I have to investigate it. I think the approach is too simple and weak. Approach taken by react-loadable is heavier but probably more resilient.

Possible solution could be also passing this id as an argument for loadable() and using this passed id not only for inner reference but also as generated bundle name (instead of 0.js, 1.js etc). Maybe it would be also an idea to investigate why loadable() is called this one additional time. Sorry didn't have time to dig deeper, have a lot of pressure on work and your library was a big help, thank you very much! :)

I discovered one more problem with Symbol(loadable) in index.js:115 in check instance.constructor[_constants.LOADABLE]. If you inspect instance in chrome dev tools you can find field Symbol(loadable) in the object, but if you try to access it - it returns undefined. The problem is reproducible only on production(webpack) build on server side.

Same issue here.
In my case the reason (I guess) is that I have used loadable in non-main chunk, so component tracker don't know about this component when loadComponents called.

So it seems like all loadable calls should happen in main chunk.

It is a known issue, unfortunately I would not be able to solve it without a Babel plugin or some additional code. Still thinking about a simple way to do it.

A disclamer about this in README.md could save some time and headaches

Would there be a easy way to disable code splitting on dev, based on some environment variable or webpack config? I don't mind not having code splitting during dev, it's more important that I don't have to kill the server to be able to refresh the page.

@FabioAntunes the next version of React Hot Loader will be compatible with Code Splitting. I think about a way to make it compatible with loadable-components with zero config.

This long issue is now solved in v1. I close this issue because it was relative to the previous version. Feel free to open an issue if you experience any problem with the new fresh v1 of loadable-components.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lauterry picture lauterry  路  6Comments

ksntcrq picture ksntcrq  路  7Comments

valorloff picture valorloff  路  3Comments

salzhrani picture salzhrani  路  3Comments

luishdz1010 picture luishdz1010  路  6Comments