Related: http://www.2ality.com/2015/07/es6-module-exports.html?m=1 On Tue, Dec 22, 2015 at 4:02 AM /#!/JoePea <j...@trusktr.io> wrote:
> In my case I was using Webpack+babel-loader. I guess that makes sense, > about the run-time dependencies. After solving the problem by wrapping > the module logic for A and B in functions then calling those functions > in main.js. I then encountered another problem: package C imports the > default from package B, and at initialization-time B is undefined in C > even though there's no circular dependency there. I was able to solve > that problem by wrapping init-time logic in a function and again > executing that in main.js. So, basically, moving all to calls in > main.js solved both of these problems. I can follow what you're saying > about the circular dep between A and B, but I'm not at all sure why B > would be undefined in C after having moved A and B logic to main.js, > leaving C logic still in the C module. > > On Mon, Dec 21, 2015 at 8:05 PM, Logan Smyth <loganfsm...@gmail.com> > wrote: > > To start, an object is definitely not what I'd expect. The core thing to > > remember with ES6 modules is that while imports are live bindings, you > still > > need to write your code in such a way that it has no run-time circular > > dependencies. > > > > In your specific examples, you are importing `A` first, which will begin > `B` > > loading. Since `A` has not finished executing yet, and B will be > attempting > > to access the the `A` import before the `A.js` file has begin executing. > I'm > > not 100% sure off the top of my head, but in a real ES6 environment, that > > would either result in the `A` import being `undefined`, or attempting to > > access it would throw a temporal dead zone error due to you accessing a > > variable before it has been initialized. > > > > If your `A.js` file comment "// modify the A object adding methods that > > reference B." adds those references without actually accessing `B` in any > > way, then the solution to your issue (in a real environment anyway) > would be > > to import `B.js` _first_ so that you do not have circular > > initialization-time dependencies. > > > > In this case, are you using Babel's ES6 module syntax transpiling, or > > Webpack with another transpiler? > > > > > > On Mon, Dec 21, 2015 at 7:25 PM, /#!/JoePea <j...@trusktr.io> wrote: > >> > >> I'm curious, what should happen when module A imports the default from > >> module B which imports the default from module A? Should the exported > >> A object exist inside of module B? > >> > >> Here's two modules A and B (simplified from some real code that I > >> have), which have a circular dependency: > >> > >> ```js > >> // A.js > >> import B from './B' > >> let A = window.globalThing > >> export default A > >> > >> // modify the A object adding methods that reference B. > >> ``` > >> > >> ```js > >> // B.js > >> import A from './A' > >> let B = new window.OtherThing > >> export default B > >> > >> console.log(A) // an empty object, {} > >> > >> // modify the B object which depends on A existing (not being some > >> temporary > >> // object like I get with Webpack) while the module is evaluated. > >> ``` > >> > >> When using Webpack, this code fails because the reference to A in B is > >> some empty object. If I import both A and B into main.js, then A is > >> defined as epected: > >> > >> ```js > >> // main.js > >> import A from './A' > >> import B from './B' > >> > >> console.log(A) // An object with a bunch of properties, as expected. > >> ``` > >> > >> I can fix my problem by exporting functions to do setup of A and B, > >> and running those functions in main.js, like this: > >> > >> ```js > >> // A.js > >> import B from './B' > >> let A = window.globalThing > >> export default A > >> > >> A.setup = () => { > >> // modify the A object adding methods that reference B. > >> } > >> ``` > >> > >> ```js > >> // B.js > >> import A from './A' > >> let B = new window.OtherThing > >> export default B > >> > >> console.log(A) // an empty object, {} > >> > >> B.setup = () => { > >> console.log(A) // the expected object!! Why? > >> > >> // modify the B object which depends on A existing (not being some > >> temporary > >> // object like I get with Webpack) while the module is evaluated. > >> } > >> ``` > >> > >> When using Webpack, this code fails because the reference to A in B is > >> just `{}`, some empty object. If I import both A and B into main.js, > >> then A is defined as epected: > >> > >> ```js > >> // main.js > >> import A from './A' > >> import B from './B' > >> > >> A.setup() > >> B.setup() > >> > >> // no more problems! > >> > >> console.log(A) // An object with a bunch of properties, as expected. > >> ``` > >> > >> So, if I run the setup for A and B in main.js instead of in the module > >> evaluation, everything works perfectly. > >> > >> This led me to wonder: What is the expected behavior of circular > >> dependencies in ES2015? Have you had this 'empty object' problem > >> before? Is that expected to happen, or might there be a bug in > >> Webpack? > >> > >> I guess the problem makes sense: How can the first method (running > >> relying on module evaluation for setting up A and B exports) work if > >> module B depends on the evaluation of module A which depends on the > >> evaluation of module B? > >> _______________________________________________ > >> es-discuss mailing list > >> es-discuss@mozilla.org > >> https://mail.mozilla.org/listinfo/es-discuss > > > > > _______________________________________________ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss