benjamn / install

Minimal JavaScript module loader
https://benjamn.github.io/install/
MIT License
61 stars 24 forks source link

[bug?] Import is not defined until later, after imports to entrypoint are complete. #4

Closed trusktr closed 8 years ago

trusktr commented 8 years ago

This is a weird problem, as I'm having the exact same results with Webpack. Maybe it's a problem with the ES2015 spec that both install and webpack happen to have implemented?

(I'm using install indirectly as part of Meteor 1.3 modules)

Basically, I have a module that looks something like this: http://trusktr.io:7777/oqirakineq

On line 15,

console.log(' @@@ Warehouses in Worlds?', Warehouses)

the output is strangely undefined. On line 98,

                console.log(' @@@ Warehouses in Worlds.createDefault?', Warehouses._name)

the output is as expected, and that line lives within a function that is eventually executed via function calls in the entrypoint of the app (so not due to module evaluation).

The strange thing is that I have this problem with both Webpack (via my rocket:module package) and with Meteor 1.3 using the modules package.

Any thoughts on what might cause an import to be initially undefined?

benjamn commented 8 years ago

This behavior is normal, though I agree it's surprising that the value of the Warehouses variable changes without any apparent assignments.

Further explanation: though the semantics of import and export help with resolving circular dependencies, they don't completely hide them. Instead, the values of the imported variables get updated as the source module exports them, so they will usually be defined by the time you use them, provided the circular dependency was resolvable. If there is a circular dependency, the imported variables generally will not be defined immediately after the import statement.

trusktr commented 8 years ago

Cool. Thanks for the explanation. I also had to dig for some other info that helped me understand. The ugly thing about it is that I now have something like this in my code:

import Warehouses          from './Warehouses'
import Things from './Things'

export function setupCollections() {

    // XXX Order matters here!
    Things.setupCollection()
    Warehouses.setupCollection()

}

where the bodies of each collection module are moved into their respective setupCollection methods.