Right, it's basically just doing what an import aware server might do and the 
type-tree is a hierarchal version of the scope imports. The rest is just extra 
stuff. Probably the biggest difference though is that it lets me isolate 
prototypes. From what I gather it seems that import stores a live "ghosted" 
version of the prototype that it checks before making additional requests for 
the item. The scope basically gets a reference to this prototype. If you do 
things like add a property with reflect in one scope that property shows up 
everywhere. And since it modified the "ghost" it persists after the scope goes 
away. It's caused me some headaches especially when dealing with 
inheritance/extends and in workers.

Yeah, inspecting is in issue. I haven't found a way to inspect modules to see 
what they have in them. They're a strange beast. You can see their scope in the 
debugger and they look like an ES Object or IDL interface, but I don't know how 
to get a reference to them in code. But, they're new, so we'll see where they 
go. Maybe someday we'll have a `modules` collection we can interrogate. 

-----Original Message-----
From: #!/JoePea <[email protected]> 
Sent: Saturday, October 17, 2020 10:35 PM
To: Randy Buchholz <[email protected]>
Cc: [email protected]
Subject: Re: Are ES6 modules in browsers going to get loaded level-by-level?

That's neat, but it seems like the same work that a server would have to do 
with actual ES Module imports, right? And the "type tree"
equivalent is the modules that the JS engine stores as a map from import 
identifier to module scope instance. It seems that in the end, the `PUSH` 
approach should work with the same efficiency, right?

Seems the only thing that makes it difficult is checking the map. In your 
special case, with `inject`, you can physically check the global namespaces to 
see if the module is available. But with ES Modules, we can't check if some 
module has already been lodade by its identifier, can we? So we have to make 
the request, because that's the only way to check.

#!/JoePea

On Sat, Oct 17, 2020 at 1:28 PM Randy Buchholz <[email protected]> wrote:
>
> I think some form of bundling will always be necessary. I use classes and 
> took a name-spaced and typed approach to modules and classes, putting each 
> class in its own module in a file hierarchy (namespace). This is an 
> enterprise level LOB application with dozens of classes. Many classes are 
> used cross-domain, limiting static/design-time bundling approaches. Also, an 
> issue I encountered with static bundling is that classes aren't hoisted, so 
> there are ordering concerns/issues with class bundles.
>
>
>
> I have multiple workers as background services that use these. Each class 
> usually has a few imports for the classes it uses. Using normal imports, I 
> was soon generating 100's of requests for the files. Even with caching, there 
> is a lot of overhead. As classes are used more, this can become a real issue.
>
>
>
> I ended up with an approach where I added dependency metadata to each class 
> to support bundling. The metadata helps with the "what to send" issue. When I 
> need a class/type do an import for it. The server walks the dependencies, and 
> bundles the request class with the full tree of dependencies. When the client 
> receives the bundle it adds the new classes to a type library. It's designed 
> for enterprise use where you have more control of things and can enforce 
> standards.
>
>
>
> Class looks like this:
>
>
>
> // File Bar.cmjs
>
> ```
>
> //::Requires: Foo.Package.Class1 Foo.Package.Class2
>
> class Bar {
>
>     const a = new Class1(); // Actually usually the qualified 
> Foo.Package.Class1
>
>     ...
>
> }
>
> ```
>
> // File /Foo/Package/Class1.cmjs
>
> ```
>
> //::/Requires: Common.Util.Whatever
>
> class Class1{
>
>
>
> }
>
> ```
>
>
>
> The basic idea is that when the server gets a request it reads the "Requires" 
> and gets those files, recursively reading requires. I keep a list of all 
> files and the depth so I know if I already captured a required, and how to 
> order the results. Once I have all of the files I write them to a single 
> bundle. I don't need to parse the files (Requires is just a comment), but can 
> if I want more control. The bundled file looks like:
>
>
>
> ```
>
> class Whatever {...}
>
>
>
> class Class1 {...}
>
>
>
> class Class2 {...}
>
>
>
> class Bar {...}
>
> ```
>
>
>
> It's more complex, because of name collisions and import scoping. What I do 
> is process the bundle and promote the classes out of the scope.
>
> ```
>
> globalThis
>
>    .Foo
>
>       .Package
>
>          .Class1 = Class1; // (The "newable" class)
>
>          .Class2 = Class2;
>
>    .Common
>
>       .Util
>
>          .Whatever = Whatever;
>
> ```
>
>
>
> Now I can just do `new Foo.Package.Class1()` anywhere in the context, not 
> just in the import scope. On the client I use `inject` in many places instead 
> of `import` - inject('A.B.Class'); const x = new A.B.Class();`. This checks 
> for the type, and if it doesn't exist on the client it requests it from the 
> server.  The server creates a bundle for it and its dependencies. I add these 
> to the type-tree. My server isn't really import-aware, I just use middleware 
> to intercept the request. This is why I could use a way to identify "import 
> requests". I know when I’m doing an ”import” through injection, but with a 
> regular import I have to do some inspection of the fetch to know to initiate 
> the process.
>
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to