Modules vs Scripts
Could someone help me understand why two goals for parsing JS is a good thing?
On Nov 16, 2013, at 3:32 AM, John Barton <johnjbarton at google.com> wrote:
Could someone help me understand why two goals for parsing JS is a good thing?
Hm, it sounds like you've assumed a conclusion already. Let me try to explain anyway.
Scripts are for synchronous loading and evaluation; modules are for asynchronous loading and evaluation. The former is not allowed to import, which triggers I/O. The latter is allowed to import. There was always going to have to be a syntactic split.
But there's more. I'll be explaining at this week's TC39 meeting some more details about the intended model for browser integration. In short, declarative code based on modules will use the <module> tag (or <script type="module">, which will mean the same thing and allows polyfilling today). This is better than <script async>, which was a hopeless idea. This also works beautifully for fulfilling the promise of 1JS: a new, better initial environment in which to run top-level application code without requiring versioning.
<module>
var x = 12; // local to this module, not exported on global object
import $ from "jquery"; // asynchronous dependency, NBD
'$' in this // nope, because all globals are scoped to this module
let y = 13; // yep, let works great because modules are strict
</module>
Same number of characters as <script>, better semantics, better global environment, better language.
If you're not excited about ES6 yet, get excited. :)
Does this imply <module src=""> ?
Works either way, inline or external. (Requiring src="" is one of the reasons why <script async> was a non-starter.)
<3 this, it matches my go-back-to-1995 dreams.
I like it. If there is a desire to stay closer to <script>
I could see <script module>
and <script module="">
Works either way, inline or external. (Requiring src="" is one of the reasons why <script async> was a non-starter.)
Is the value of src
a module ID or a path? How about when packages are used (for bundling)? Is there a way to combine module IDs and packages?
On Nov 17, 2013, at 11:59 AM, Axel Rauschmayer <axel at rauschma.de> wrote:
Is the value of
src
a module ID or a path? How about when packages are used (for bundling)? Is there a way to combine module IDs and packages?
For the most part the answer to these kinds of questions is that we support "all of the above," but I'd like to wait just a little bit longer before getting into details. Right now we've been focusing on providing a complete base (reflective) layer via the Loader API, which is what will be in ECMA-262; the rest is an HTML spec. (We are thinking through what pieces are necessary for the <module> tag to ensure we haven't missed anything in the Loader API.) I'm focused on getting ES6 out the door, but the next step after that is to start fleshing out the <module> spec.
That makes sense. So, for starters, I’m guessing one will set up the module loader via a <script> tag (e.g. to enable bundling).
Afterwards, the <module> tag will be used to load modules, via module IDs. Then “src” probably isn’t a good attribute name, “id” isn’t either (clashes with DOM terminology). “from” and “import” seem likely candidates. (Just for the sake of an initial rough story; I do understand that it doesn’t make sense to discuss details, yet.)
On Sun, Nov 17, 2013 at 2:23 PM, Matthew Robb <matthewwrobb at gmail.com> wrote:
I like it. If there is a desire to stay closer to <script> I could see <script module> and <script module="">
Has to be <script type=module> otherwise it would execute in legacy clients.
Correct me if I'm wrong David but module import/exports are not dynamic which allows tooling/IDEs to be more intelligent and programmers to easily understand what dependencies a module has/provides?
Yes, that's correct, if I guess correctly at what you mean by dynamic.
You can statically analyze the module text and enumerate the complete imports and exports of the module without having to execute the module. The execution of the module will not dynamically increase it's imports/exports.
For instance could you have a Math.random that decides if a dependency is required?
Yes, exactly.
Of course, running a module can load other modules using the Loaders API, but that doesn't add any new imports or exports to the module itself.
Just a user-experience report with traceur: the following code fails to compile in the repl.html and command line compiler:
import {WrapNewObjectTransformer} from './WrapNewObjectTransformer'; export function transcode(src, url) { var file = new SourceFile(url, src); var reporter = new ErrorReporter(); var tree = new Parser(reporter, file).parseProgram(true); return (new WrapNewObjectTransformer()).transformAny(tree); }
It fails on 'unexpected token export'. This was unexpected by me ;-)
However it does seem consistent with the grammar in harmony:modules. The |export| keyword is part of an ExportDeclaration which appears in a ModuleElement but not in a ScriptElement. The parser believes it is parsing a Script. So the only way to legally parse JS as a Module is as a side-effect of module loading?
I suppose that a Script is intended to be the root of the dependency tree, so the error message is trying to tell me "You are compiling an interior node of the dependency tree silly". But both Script and Module are things that JS devs will want to compile. Concretely I will want to be able to copy the contents of a JS file and paste it into a repl window to analyze it without having it die on syntax errors because it is a module.