systemjs / systemjs

Dynamic ES module loader
MIT License
12.93k stars 1.09k forks source link

What's the plan/status/roadmap? #1522

Closed mindplay-dk closed 7 years ago

mindplay-dk commented 7 years ago

I'm confused. (Frankly, I'm mindboggled.)

I have spent hours reading conflicting blog-posts, stack-overflow answers and various specifications, and I have no idea what's happening, where this project is going, or even what precisely this project is.

Okay, so the front page of your README says:

Built to the format ES6-specified loader API from ES6 Specification Draft Rev 27, Section 15

Well, that draft is over two years old.

There have been more than 10 updates to that specification since.

More recent versions of the specification don't even seem to have the part of the specification you're referencing?

The most recent update to that specification was the last of a series of four release candidates, but it's more than a year-and-a-half old - there was never a final release, so this looks to be dead in the water and never officially released?

The README continues:

and will be updated to the WhatWG loader API as soon as it can be considered stable for implementation.

Okay, so I'm looking at that.

It doesn't seem to specify anything called System.register(), so what is this? Is it supposed to supersede and replace the other specification? How will that affect what this package is or does, and will it even be the same thing at all once it gets updated to this specification?

I keep hearing AMD is a "receding" module format. But then I look at popular packages such as JQuery, and it doesn't even seems to support System.register() at all. I understand that this loader supports other package formats as well, so of course it will load JQuery - what I don't understand is, if this new System API is "the future" in terms of ES6 support on the client-side and so on, how come practically no major packages even support it yet?

I understand we'll need polyfills for all these other module formats (ugh) at least for a while, but I'd like to envision a future where, eventually, the System API is the standard for loaders, and we can finally use something clean and small like the es6-micro-loader and drop support for all these other dated module formats. That's the end game, right? I don't want to think that this is just yet another module format to add to the list, but will that happen, or why isn't it?

Why aren't even major packages like JQuery supporting it yet?

What's the status of these specifications and where is this project going?

(I apologize for the rant. I'm sure this may be entirely the wrong place to ask. If so, I apologize, and can you please point me to the right place to ask? Or point me to the right, preferably official source for current, correct information about these matters?)

probins commented 7 years ago

take a look at 0.20 branch, which may clarify some things. The basic issue here is that the specs keep changing, and this project struggles to keep up. Current master branch is outdated. ATM it looks like browsers will be implementing <script type="module"> for static loading and import() for dynamic loading. I'm hopeful this can be implemented in 2017 - but then I said something similar a year ago (and the year before that). I don't think System is still planned.

I'm afraid it's just part of being cutting-edge that you have to put up with constant changes, especially with such a major new feature as module loaders.

probins commented 7 years ago

for System.register, see https://github.com/ModuleLoader/es-module-loader/blob/master/docs/system-register.md

asapach commented 7 years ago

I would add that System.register is not a distribution format. I would rather expect jQuery to ship their code as ES6 modules, so that you could build and bundle it the way you wish, including Rollup and Webpack. And of course you can convert it to System.register format using systemjs-builder if you want to load it dynamically.

mindplay-dk commented 7 years ago

Thanks for the reply.

What would you recommend personally?

Is there any reason to switch from requirejs to systemjs as the browser loader?

I mean, it doesn't look like we'll actually have any es-standard modules to load in the near future?

So maybe the only reason to switch would be so we're ready when they do arrive - so that our bootstrapping is already based on systemjs and doesn't need to be ported from requirejs at a later time. Or?

asapach commented 7 years ago

I personally use it because I write ES6 code and SystemJS fully supports ES module semantics. If you're happy with AMD and ES5, there's no need to switch just for the sake of future-proofing. Moreover I would not recommend using it as a loader in production, because it has a pretty significant performance impact. You should use SFX bundles instead.

probins commented 7 years ago

I was an early user of RequireJS but switched over to the loader polyfill in its early days, mainly because ES6 is the future whereas AMD isn't. I write all my code now in ES6, and convert to System.register for use with the register loader. I stick a System.register wrapper round 3rd-party code I use. I used to use SystemJS but no longer do so, and have written my own version of depCache for pre-loading dependencies with HTTP/2 so bundling is no longer necessary. Once browsers support module loading, the polyfill and System.register code can be dumped, but I think the change-over will probably be both lengthy and messy, as all the main browsers have to support it before apps can use in production, and converting all 3rd-party code won't happen overnight. Also, I think it likely that initial loader implementations won't be that efficient, but will be gradually tuned/improved over time.

I'll leave Guy to comment if he wants on how he sees SystemJS evolving.

ToddThomson commented 7 years ago

@mindplay-dk I've just converted a small test project that was using requirejs (and optimizer) to systemjs-builder. I use gulp for my build pipeline.

Here are my thoughts on why I decided to go with systemjs...

I switched to using Typescript over a year ago. I decided to use Typescript because it allowed me to write ES6 modules ( and provides all the ES6 features that I need ). Since Typescript provides ES6 to ES5 js transpilation I am able to write modern ES6 code which targets ES5 browsers of today. Typescript allows me to also target almost all ES5 module loader systems. Note that any transpiler of ES6 to ES5 would work just as well.

Since ES6 modules will be the future, I also decided a long while back to move to a modern "Universal" module loader. However, this step is not strictly required as really any module loader system can still be used as long as your transpiler supports the module format. It's taken me about a year to make the move from requirejs to systemjs. I chose systemjs rather than webpack or jspm as I don't really like "meta" tools due to their API weight ( personal thing ). I also chose systemjs since it has much of the requirejs configuration.

It took me about a half a day to build up my gulp build pipeline with systemjs. That reflects well on the systemjs builder API.

Here is a link to the Greeter app.

mindplay-dk commented 7 years ago

@ToddThomson this is way too much bootstrapping and build overhead for my taste.

What I'm aiming for is to basically use the TypeScript compiler, and nothing else. It's not ideal for that yet, but with --outFile and e.g. --module amd, I can get a single file for a module and all submodules - although this requires a client-side loader, that is overall much simpler than a full stack of bundlers, build tools and third-party integrations.

For one, it enables me to run tsc in --watch mode and test things in-browser with no real delay. I use npm with scripts as my "build tool", so I can skip e.g. minification while developing - that happens only once before a release.

Each to his own, but I am personally aiming for something much, much simpler - I don't want grunt or gulp or bundlers or a bunch of configuration while I'm developing. (and yes, I know it's possible to set up e.g grunt that way - but that's just even more configuration and bootstrapping...)

ToddThomson commented 7 years ago

@mindplay-dk My intention with the link above was just to show how I used the systemjs loader in a basic Typescript sample. I found switching from Requirejs (AMD) to Systemjs (Universal) to be straightforward.

There is nothing clear on whatever ( and whenever ) will arrives in terms of browser support of ES6 module loading, I switched to systemjs as I see it a stepping stone towards whatever will arrive in the future.

P.S. I only use the gulp build pipeline for final production code. Before that ( in development ) I just use VS ( or VS Code ).

togakangaroo commented 7 years ago

But....if the System object is going away what will happen to System.config?

I realize that its not standard but you must have something like that eventually right?

Afterall, how else would it know what the heck import 'jquery' means? I don't want to use a path with version-specific data everywhere!

probins commented 7 years ago

this is something that's still undefined in the current specs. The note under https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-module-system leaves open defining this for module scripts in the future. I would agree that there needs to be something along these lines, but quite what remains to be seen. SystemJS was/is based on a loader with hooks that could be configured, but the full loader spec got stuck in the sand and it's not clear ATM how much will be implemented and what configuration will be possible/needed.

backspaces commented 7 years ago

The real issue is whether or not modules/import/export will ever happen .. "It's Dead Jim".

I realize this is grouchy but look at all the pre-release work arounds: bundlers (rollup, webpack, ...), browserify, system.js etc. Very great work but why? Modules are es2015. It's now 2017. Really?

I'm not sure if the TC39 spec is just too ambitious or simply that the spec is split between two organizations: ECMA for syntax/semantics and Whatwg for loader. Chrome hopes to provide both node and browser loaders so maybe the split is silly?

The only ray of hope is the <script type=module ...> stunt for browsers .. it lets whatwg off the hook I guess and the browser engines will just ignore them and build their own loaders w/o concern over the dynamic loading api etc.

togakangaroo commented 7 years ago

How does type=module help at all though? There needs to be a way to configure the loader sub-system.

I mean for gods sake, are we going to update every file that references jQuery every time you up a jQuery version? That's insane! Or even say we accepted that as our fate. Without some sort of depcache-style ability, any project that uses modules will preform terribly since you cannot know what a module references without loading it first. We very quickly get back to cascades of loading that are somehow worse than what we had with http1.

I'm actually unclear of who's job it even is to specify how the loader works. I'm on half a dozen spec mailing lists all of which seem like the wrong place to discuss this.

On Sat, Dec 31, 2016 at 4:27 PM, Owen Densmore notifications@github.com wrote:

The real issue is whether or not modules/import/export will ever happen .. "It's Dead Jim".

I realize this is grouchy but look at all the pre-release work arounds: bundlers (rollup, webpack, ...), browserify, system.js etc. Very great work but why? Modules are es2015. It's now 2017. Really?

I'm not sure if the TC39 spec is just too ambitious or simply that the spec is split between two organizations: ECMA for syntax/semantics and Whatwg for loader. Chrome hopes to provide both node and browser loaders so maybe the split is silly?

The only ray of hope is the <script type=module ...> stunt for browsers .. it lets whatwg off the hook I guess and the browser engines will just ignore them and build their own loaders w/o concern over the dynamic loading api etc.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/systemjs/systemjs/issues/1522#issuecomment-269884088, or mute the thread https://github.com/notifications/unsubscribe-auth/AAECZmA4nREQJ9r300Aq0qlmBlEVwkzZks5rNta0gaJpZM4LKaPx .

probins commented 7 years ago

hey guys, how about some optimism for the new year? 😄

Module loading is most certainly not dead. Module scripts have been implemented in Edge (behind a flag) and Firefox ('chrome documents' only so far), and the ES2015 part of modules has been available in JavascriptCore for over a year now. I'm not sure what the exact status is for V8/Blink, but they have been working on it, and they are committed to implementing module scripts too. The last two TC39 meetings included substantial discussions of modules, including the issues involved with implementation in Node. I believe the meeting later this month will also do so. Dynamic import has moved pretty quickly to stage 3, which means it's considered complete and awaits feedback from implementors. This together with module scripts should cover the needs of most web apps. But I don't think that's the end of the story. Other things like mapping module names to paths/urls can be added later if everyone agrees they're needed.

I think TC39 acknowledges that ES2015 was too big - maybe why ES2016 was pretty trivial. But I wouldn't make too much of a 'split' between Ecma and Whatwg - members of the loader group also attend TC39, and the same person created the PR for module scripts and the dynamic import proposal, based on discussions in the loader group.

I too find it frustrating that it's taking a long time to define module loading, but OTOH this is a major change, not just to the language but to the whole way code is used on the web.

mindplay-dk commented 7 years ago

I realize this is grouchy but look at all the pre-release work arounds: bundlers (rollup, webpack, ...), browserify, system.js etc. Very great work but why? Modules are es2015. It's now 2017. Really?

@backspaces yeah, that's kind of my attitude - has been for some years now.

I too find it frustrating that it's taking a long time to define module loading, but OTOH this is a major change, not just to the language but to the whole way code is used on the web.

@probins it's also like 10 years too late, but yeah, I get what you're saying ;-)

Hey, can someone remind me again why we're struggling so hard with this in the first place? I mean, relative module IDs essentially get mapped to relative URLs, why aren't we just using URLs instead of module IDs in the first place?

Rather than relying on a configurable loader facility that resolves IDs to URLs, wouldn't it be much simpler to literally just import * as jquery from "http://cdn.whatever.com/jquery.js", e.g. using (absolute or relative) URLs directly, rather than going through this complex process of turning IDs into URLs - most of the time, the relative IDs etc. just map 1:1 with relative URLs from some base path (with a ".js" suffix) anyhow, right?

What's wrong with paths? What is the problem that module IDs are supposed to solve?

asapach commented 7 years ago

I think I saw a talk by @guybedford that answers your question: https://www.youtube.com/watch?v=cRSBi1EAOCo

mindplay-dk commented 7 years ago

@asapach thanks, that was helpful - it's the first time I've actually seen somebody demonstrate step-by-step how or why you get to this workflow. I think I might watch this a few times over to get all the subtleties.

At the end of it though, I kind of had the same question this guy had, and @guybedford gives basically the answer I was expecting - that this approach is interesting and might prepare you for the future, but doesn't really have any advantage over other approaches right now.

Which makes me think very seriously again about just using TypeScript, with a single compile-step, and forget all these other tools and complexity. Maybe rather than trying to anticipate the future, it's safer to just go with what is simple and well-known?

Am I really going to be "more ready" by then, by plugging in a whole big complex toolchain now, that I won't actually need then? I mean, I've tried this stuff, I've seen what's (likely) coming - do I really benefit from struggling to code like we had these features now, versus just waiting for them to actually arrive?

I've been writing JS since the dawn of time, and the first language I was really serious about was Pascal - so I'm as impatient as anyone, I've been waiting for JS to "mature" for like 20 years now, and even though I think it might be close, I wonder if after this many years it would be wiser to just wait and see what actually happens? In the mean time, JS will continue to suck, like it has been for 20-something years, nothing new, nothing surprising. If that changes, well, great, but by the sound of it, no one really knows when (or even, with certainty, whether) that's going to change. Perhaps better to just sit tight?

backspaces commented 7 years ago

Nice observations all, and I'll watch the video soon.

One reason I care so much about modules is that I want absolutely minimal workflow. Write the code and run it w/ no build steps. Modules are my only build steps now so will vanish when we get <script type=module ...>

I realize that is extreme for many use cases but fortunately it fits mine well. I do have workflow (npm build scripts) for deploying and initializing a newly cloned repo and other chores. But my aim is no transpiling etc for the build. Write and run. Free At Last! : )

mindplay-dk commented 7 years ago

@backspaces yes, that's what I want - minimal workflow, ideally no build-steps, and no third and fourth party non-essential dependencies, at all.

I don't actually think that's "extreme" at all, I think it's completely rational - this is after all a scripting language, the main selling point for which were originally "write and run", right? Today, the tool-stack and build-process of the world's most popular scripting language has (potentially) far more steps, components and complexity than many compiled languages.

If we're being completely honest, today, we're getting the slow, complex workflow of compiled languages, and the low run-time performance and safety of a scripting language - so we're really getting the worst of both worlds. I hope this will start to change with HTTP/2 and JS modules.

backspaces commented 7 years ago

Yay! Now there are two of us! But seriously, for those of us in this thread, you may want to look at one of the several "use npm as your build tool" posts.

These are the first two I came across. https://www.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/ https://medium.freecodecamp.com/why-i-left-gulp-and-grunt-for-npm-scripts-3d6853dd22b8

togakangaroo commented 7 years ago

I feel like people don't understand why <script type=module ...> doesn't really work by itself. The underlying idea is a great double thumbs up and it totally works for sites with a couple hundred LOC of javascript. But these are the sites that are least likely to benefit from javascript modules.

So here's the issue and the reason I keep talking about depcache (which -hint hint- would be swell for SystemJs to prioritize a bit).

Let's say you have the following modules with dependencies

main
   import './userProvider'
   import './userDisplay'

userProvider
  import './fetch'

userDisplay
  import 'moment'

Now the old school way would be 5 script tags which would set up some globals which would be referenced from each file. When the html page loads, 5 simultaneous html requests would be sent. As soon as the first request were done we could start parsing and executing files and the code would begin to run as soon as the main.js file was loaded and parsed.

What happens if we do <script type=module src="./main.js">?

If you think about the timing, then you will realize that in the module version you are waiting as much as three times longer for your app to start up. And the entire point of modules is that you can break things out into small modules as applications grow. So what happens when we break out userDisplay to add more imports? What happens if have have yet other imports? What happens when we pull in a js-modules compatible 3rd-party library like lodash that has its own cascade of imports? We're going to get applications which take forever to load and http/2 does not save us.

So then everyone goes back to bundling, and then you're back to friggin' browserify and webpack and http/2 being a pointless historical byproduct.

Not supporting something like depcache is simply not a viable solution. We should all be up in arms about this.

asapach commented 7 years ago

@togakangaroo, you're missing something: http/2 is not only about multiplexing, there's also server push which can solve your scenario if used correctly. When you download the html page server can push all the related resources, including the whole module dependency tree. This is speculation at this point unfortunately, because no server currently supports this, but they are all talking about it.

togakangaroo commented 7 years ago

@asapach thats cool and you're right, I did not know about this.

Although I'm not sure it matters much.

The server then would need to know the dependency tree. Which means the server would either have to know how to parse javascript files or .... crap, we're back to a build step again.

And still, like you said, all highly theoretical and not even close to supported.

asapach commented 7 years ago

One of the approaches I've seen mentioned is that an http/2 server/proxy/cdn can learn on the fly and populate their own dependency cache based on previous sessions, i.e. if these two files have been requested together, there might be a dependency between them, and they could be pushed next time. So it's not as bad as you paint it. But yes, if you want the best results, you need dep cache populated ahead of time.

probins commented 7 years ago

server push knows nothing of the browser cache though, so potentially wastes time and bandwidth pushing code that the browser already has. In my view, it's the app's responsibility to define what should be preloaded, and there are existing tools that can draw up a dependency tree. I raised this issue on the loader repo, and agree that <link rel="preload"> looks like a good way to specify important dependencies to be preloaded. This is supported by SystemJS 0.20, though to date Chrome is the only browser that's implemented it. You could create the links manually, or you could have a service worker create them dynamically every time an import is executed. A service worker could also map module names to urls, though it might be simpler to run a server process before each release.

probins commented 7 years ago

the ES2015 part of modules has been available in JavascriptCore for over a year now.

just noticed that a Webkit ticket for module scripts was recently created too

probins commented 7 years ago

support for module scripts in latest Safari TP. Webkit status now shows modules as 'Done'. 🍾

V8 also now "fully supports modules".

Things are moving on ...

guybedford commented 7 years ago

For those interested in minimal spec workflows - https://github.com/guybedford/isomorphic-browser-modules.

probins commented 7 years ago

nice one; I like the idea of using this to determine whether it's a module :-) Why are you using SystemJS rather than simple register polyfill? SystemJS adds support for mapping and depCache, but these won't be used by ES-supporting browsers. I'm thinking though that if for example depCache were available as a separate module, ES-supporting browsers could load it upfront and add preload links dynamically (though in Safari's case this won't help as it doesn't seem to support either preload or prefetch).

I notice too that Safari TP also now supports global.

guybedford commented 7 years ago

@probins yes that loader could equally well have been used. SystemJS will only actually be able to run alongside ES browsers when we have movement on browser resolvers.

guybedford commented 7 years ago

See http://guybedford.com/systemjs-alignment for the latest update here.

probins commented 7 years ago

I'm not sure what the exact status is for V8/Blink

looks like Chromium's aiming for implementation in v58 https://bugs.chromium.org/p/chromium/issues/detail?id=594639#c15