alexisvincent / systemjs-hot-reloader

reloads your modules as needed so that you can have satisfyingly fast feedback loop when developing your app
MIT License
228 stars 36 forks source link

Hot-Reloading `register` module format generated by babel #125

Closed Pavel910 closed 7 years ago

Pavel910 commented 7 years ago

Hi, I was trying to get hot-reloading to work with bundled assets, transpiled by babel in the build process and served to System.js in register @format.

I'm not sure if my problem is in how I handle System.js or the hot-reloading. @guybedford @capaj

Before I spend another week on it I was wondering if this could hypothetically work at all?

Just to mention: I did study the jspm-react example, it works and I fully understand how it works internally. Also, I do not use jspm at all, I created a built version of hot-reloader so I can include it as a single file into my project.

What I have at the moment:

So the question is - is it even theoretically possible to get the hot-reloader working using this workflow? I will change the hot-reloader.js for my needs if necessary I just need some input regarding the entire idea.

Thanks a lot!

alexisvincent commented 7 years ago

Hi Pavel,

It should definitely be possible to get hot reloading to work with this workflow.

Once the event emitter notifies your app of a change, what file does it say has changed? The bundle or the individual file? Can you clarify the exact files that are being loaded.

Pavel910 commented 7 years ago

Hi Alexis,

To simplify the whole structure I made it into 2 files: app.js and input.js. I load both of them via System.import before running my app so that the modules are available to System.js. Once these 2 files are loaded, I call another import by module name, My/App which is registered when app.js is imported.

At this point the app runs and everything is rendered fine. When I change the /build/input.js, the chokidar-socket-emitter says: File /build/input.js emitted: change. In the dev-tools I can see hot-reloader removing that file and a new request is being made to fetch /build/input.js. I'm thinking there is something missing here to bridge the gap between the script name being imported and the actual module being loaded since it has a custom name.

When I look at the System._loader entries, they look like this (I stripped the rest for cleaner output): http://mydomain.com/Components/Input http://mydomain.com/build/input.js

I think http://mydomain.com/build/input.js is created when I first import the bundle and http://mydomain.com/Components/Input is created when the app actually imports the dependency when executing code.

Oh and thanks for immediate response :) That was fast 👍

alexisvincent commented 7 years ago

Pleasure :)

Are you manually setting entries in the loader registry?

alexisvincent commented 7 years ago

If you give me access to a repo I might be able to provide better help. It seems as if you're doing some custom stuff. Difficult for me to see the context.

Pavel910 commented 7 years ago

No, i simply import the /build/input.js and that file contains this:

System.register('Components/Input', [], function (_export, _context) {
    // component code here
});

The module name is generated by babel's getModuleId function so I can organize modules more nicely.

Pavel910 commented 7 years ago

Let me make a clean repo with just the important stuff and I will share it with you. Thanks a lot for the effort.

alexisvincent commented 7 years ago

Yeah, the hot-reloader assumes you are mapping things via file names. If you are manually setting modules in the registry (via System.register), its not going to be able to determine which files to invalidate.

alexisvincent commented 7 years ago

Sure :) Make a repo and I'll see if theres something we can get going. Are you open to changing your file structure at all?

Pavel910 commented 7 years ago

Oh, I see what you mean by manually now. Ok that's a very valuable info, I will try to get a test case working with the info provided.

It's a big platform and we have our ES6 import statements organized nicely with these custom module names. Let me play with this input a bit more to see if I can somehow map the file path to the module name. If I'm still stuck I will make a repo and try to structure it as close as possible to our actual platform so you can see what's going on.

Thanks a lot, Alexis!

alexisvincent commented 7 years ago

Sure. Something that might help is using SystemJS's config option map. You can map something like Components to a dir components and just put your component files in there. Getting hmr working with custom mapping will require you manually listening for file changes and invalidating things yourself. (Not worth it IMO)

Pavel910 commented 7 years ago

@alexisvincent I got it to work with a couple of tweaks in hot-reloader.js just to prove the concept. There are other issues but it is related to my platform, so I can work with it from here.

I'm closing the issue and thanks a lot for your help and suggestions! 🍻

alexisvincent commented 7 years ago

Glad you got fixed :) Goodluck :)