aurelia / hot-module-reload

Core functionality for Aurelia's hot-module-reolad (HMR) capabilities, which is shared by all loaders and tools.
MIT License
25 stars 8 forks source link

Aurelia's design vs HMR [conversation] #11

Open niieani opened 7 years ago

niieani commented 7 years ago

:point_up: February 17, 2017 11:31 PM

HMR needs a bit more work but the reasons it's so hard are more architectural currently I need to traverse soo many places in order to find the instances and replace them (in the HMR code)

I think this is something to think about for Aurelia 2.0: how to structure the code so that the instances of things like VM aren't stored directly, but perhaps as getters to a centralized store it would also be good if we had access to the whole tree of DI Containers, to traverse both up and down in depth but I get that Aurelia wasn't designed with HMR in mind, so it's an afterthought now we'd need some fundamental changes to make it robust

Bazyli Brzóska @niieani 23:36 now the HMR code is traversing as many places as I can to find with matching exports and their instances and trying to either replace them or swap their prototype for the new one https://github.com/aurelia/hot-module-reload/blob/master/src/view-model-traverse-controller.ts all this logic:

with Views it's even harder, since there isn't a centralized place where we can iterate the whole "Aurelia" tree (as opposed to the DOM tree) so currently I'm just finding the Views to hot-reload like this: DOM.querySelectorAll('.au-target') https://github.com/aurelia/hot-module-reload/blob/9fc2398e4c8abe1453ead5866cd078245f95e574/src/aurelia-hot-module-reload.ts#L15 and then accessing their .au properties that (sometimes) contain .view and .scope and then traversing that for .controller, .viewFactory and router slots

Jedd Ahyoung @jedd-ahyoung 23:41 so you're saying there should be something like a ViewRegistry or something? maybe a weakmap that can be iterated?

Bazyli Brzóska @niieani 23:41 the problem is a weakmap can't be iterated I've already looked into it

Jedd Ahyoung @jedd-ahyoung 23:41 thought it could be.....guess i'm wrong. maybe maps can and weakmaps can't, hmm

Bazyli Brzóska @niieani 23:42 there currently isn't any construct in JS that allows you to create an interable WeakSet / WeakMap

jods @jods4 23:42 I think that was by design.

Bazyli Brzóska @niieani 23:42 it would be possible (cause it make sense, the garbage collector would just remove the item from the set during GC) anyway, we'd just need to add the hook in the appropriate place

Jedd Ahyoung @jedd-ahyoung 23:43 hmm. seems like you'd need some type of tree structure in memory with refs to the views, but you'd need to be able to invalidate them easily. that could be done without a weakmap, i suppose, using generic js hash objects - quick lookup as well

Bazyli Brzóska @niieani 23:43 when the View is created, a reference would have to be added somewhere and then when it is destroyed, we'd remove that reference I've tried experimenting with the ViewHooks but we don't have enough of them to make this possible i.e. no way to consistently remove the Views from such a map

Jedd Ahyoung @jedd-ahyoung 23:45 yeah, this basically has nothing to do with the component lifecycle, right? the lifecycle of a view isn't tied to how it's stored within aurelia due to caching

Bazyli Brzóska @niieani 23:46 yes but we do have a hook for after a view was created, for example we'd also need to store ViewModels the same way, in a central registry

Jedd Ahyoung @jedd-ahyoung 23:47 not sure how the view cache works....i imagine it's built to lookup in constant time, but maybe it'd be possible to built it as a tree structure of sorts for traversal purposes?

Bazyli Brzóska @niieani 23:47 that is, instances of the ViewModels

Jedd Ahyoung @jedd-ahyoung 23:48 the real problem with views is that i don't think that you could actually do anything unless the view was cached due to aurelia conventions and differing view strategies

Bazyli Brzóska @niieani 23:48 while references to module exports should be getters that point to the module in the loader cache

Jedd Ahyoung @jedd-ahyoung 23:48 not sure but i think the only thing you really could do was invalidate the cache and reload yeah, for the viewmodels maybe you actually could use an aurelia loader that's built specifically for webpack and module loading

Bazyli Brzóska @niieani 23:49 The thing is with HMR I can remove a View and recreate it it's not a problem I only need to track where the View is, what's it's parent is and where in the DOM it is (if visible)

Jedd Ahyoung @jedd-ahyoung 23:49 you could keep the viewmodel registry there, in the loader instance

Bazyli Brzóska @niieani 23:50 the rest is bindingContext and overrideContext, which we can keep between reloads so when you swap out a .html, it recompiles the template, removes the old View, removes all the references to it (that I can find), makes a new View with the new template and replaces the references to match the new View

Jedd Ahyoung @jedd-ahyoung 23:52 makes sense, yeah might it be possible to swap out the viewlocator and do it there?

Bazyli Brzóska @niieani 23:53 don't know I didn't dig that deep

nmocruz commented 7 years ago

It´s seems complicated to implement this. I trying to help, but is not easy. I was avoiding webpack until seeing so many people adopting it. I still dislike it, bundling things in dev is an extra problem in the process, and I don't thing that it deliver a good debug experience in the browser. It can be faster on the first load with handreds of files/request, but to reload/import components from the server when code change is not better then other loader like systemjs.

I dont know so much about the problem, maybe it can be stupid what I will say. But to me it must have a simple way to archive a reasoble solution. Like, a web component changed must be pluged in same node and re-activated.

danielmeza commented 7 years ago

@nmocruz the is a open issue at https://github.com/alexisvincent/systemjs-hot-reloader/issues/102 or the system.js hmr Aaurelia implementation.