Are ES6 modules in browsers going to get loaded level-by-level?

Augusto Moura augusto.borgesm at gmail.com
Fri Oct 23 02:31:15 UTC 2020


We could wirte a simpler parser just for the imports subset, given the
simpler isolated grammar I don't think is that hard with parser
combinators. Maybe it's a cool idea for a npm library that just points out
the dependencies of a single file and then recursively scan the rest. From
that is just hook some cache system to a node server and voi'la

I migh try it as a weekend toy project

Em qui, 22 de out de 2020 23:26, J Decker <d3ck0r at gmail.com> escreveu:

>
>
> On Thu, Oct 22, 2020 at 2:23 PM #!/JoePea <joe at trusktr.io> wrote:
>
>> >  It's caused me some headaches especially when dealing with
>> inheritance/extends and in workers.
>>
>> Like, extending from a `Module` object?
>>
>> > Maybe someday we'll have a `modules` collection we can interrogate.
>>
>> That may be nice, to query which modules have already been imported, etc.
>>
>> It would also be great if we could unload modules.
>>
>> ---
>>
>> Skypack is making news rounds as an ESM server: http://skypack.dev/
>>
>> It says it supports HTTP/2 and HTTP/3. But it isn't open source.
>>
>> Seems that there isn't any open source solution (otherwise I'm sure
>> people would be using that over bundling if it works out better, at
>> least alternatives to skypack would exist, f.e. well-know projects
>> like React, Angular, Vue, Svelte, etc, could all have their own ES
>> Module servers if it was viable).
>>
>> Seems that there hasn't been any free/open project to prove viability
>> yet, and the existing ones are closed source.
>>
>> Seems that even http://jspm.dev is closed source.
>>
>> Looks like at this point in time people are aiming to make money from
>> ESM servers, and there's no viable open source ESM server solution.
>>
>> Seems like it wouldn't be a LOT of work to take Acorn (
> https://www.npmjs.com/package/acorn ) and http server (
> https://www.npmjs.com/package/http ) and parse the pages loaded if
> (*.[cm]+js) (something)
>
> Though my observation is that when the browser gets the first page, async
> requests go out for more content even before it's actually interpreted/run
> the script; and the requests are streamed over one or more http(s)
> connections.  this screenshot https://pasteboard.co/JwUnbAD.png  of this
> demo http://d3x0r.github.io/Voxelarium.js/  shows the network load time;
> recently updated to imports and non-built scripts...    though I do see a
> gap where the html script loading ends and the imports in the scripts
> actually go... but that could also be the pause setting up the opengl
> surface... it's about 50ms.
>
> since 'import' is itself async I sort of expected a lot of overlap in the
> requests; there's only a single network wire, so there's not a LOT to be
> gained parallelizing things.
>
> If there was even some sort of manifest could make a background service
> worker (which itself doesn't support import
> https://bugs.chromium.org/p/chromium/issues/detail?id=680046 ) which can
> behave like a offline storage/cache so the server can dump requests to the
> client before it knows to ask for them... and then it doesn't have to ask
> the server for anything  at all later even; which sort of de-emphasizes all
> the work put into the server in the first place :)
>
> J
>
> #!/JoePea
>>
>> On Sun, Oct 18, 2020 at 8:50 AM Randy Buchholz <work at randybuchholz.com>
>> wrote:
>> >
>> > 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 <joe at trusktr.io>
>> > Sent: Saturday, October 17, 2020 10:35 PM
>> > To: Randy Buchholz <work at randybuchholz.com>
>> > Cc: es-discuss at mozilla.org
>> > 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 <work at randybuchholz.com>
>> 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
>> > > es-discuss at mozilla.org
>> > > https://mail.mozilla.org/listinfo/es-discuss
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20201022/8f42ea11/attachment.html>


More information about the es-discuss mailing list