Is the window.System object a required part of JavaScript ES6 - javascript

A while back I read that the System object is a required part of es6 modules, basically a new Object type with all the required semantics for module loading.
Is this a strict es6 requirement? It doesn't seem to be in the latest spec.

The global System object is not part of ES2015.
The module loading API, which includes System, was removed from the ES2015 spec in Draft 28, October 2014.
Module loading is now tracked by the separate WhatWG loader spec.
There is an implementation of the module loader API as specified in Draft 27 (including System) at https://github.com/ModuleLoader/es6-module-loader.

It seems that the API was dropped from ES2015, but will eventually be implemented.
I found this repository on GitHub, which talks a bit about the Module Loader API, but if you look at the issues, the first one is named "Programmatic module loader API Specification?". It includes a conversation on the subject.
The first comment says this:
The module loader API was actually removed from ES2015; it should
probably just be removed from this repo.
And this is also an interesting comment from there:
Worse, there's no way for import to even load modules, since it
doesn't have a loader to consult.
Eventually there will be a loader spec, but until then ES2015 just
specifies the syntax, and the syntax does nothing. (That is, the spec
contains points where it's like "consult the host environment to do
something useful here.")
The person who made both of the previous comments, links to these notes as a reference:
https://github.com/tc39/tc39-notes/blob/master/es6/2014-09/sept-25.md#loader-pipeline
Conclusion/Resolution
Loader pipeline goes into a separate spec: living document that deals
with integration

Related

Import/export type:module on package.json not working JS [duplicate]

I've been thinking around this question lot of days and i have decided to ask the experts.
How browsers will handle the new import/export syntax ? I mean: will the modules be loaded asynchronously ? Referencing only my main or entry file and browsers will lazy load the requiere modules.
Maybe am i missing or misunderstanding something about this new architecture ?
Thank you very much!
Regards.
This is standardized now and supported by all major modern browsers.
will the modules be loaded asynchronously?
Yes, with two options available; details below.
Referencing only my main or entry file and browsers will lazy load the requiere modules.
Not so much "lazy," but yes.
Enabling it
Details in the spec here and here (and possibly elsewhere).
To get this behavior, you specify that your script is a module by using type="module":
<script src="main.js" type="module"></script>
or for inline scripts
<script type="module">
// ...module code here
</script>
That means that the script is parsed and handled per the Module definition in the JavaScript specification instead of per the Script definition, which means it can have imports (and exports).
Imports are resolved relative to the script's URL (for modules loaded via a separate resource such as the main.js above, just like CSS) or relative to the document (for inline modules like the one above).
So for instance, if I have this in my document at http://example.com/index.html:
<script src="./handy/stuff/nifty.js" type="module"></script>
...and nifty.js contains
import Thingy from "./thingy.js";
...then the browser looks for http://example.com/handy/stuff/thingy.js, not http://example.com/thingy.js. Again, just like CSS imports.
Note that the ./ on that module specifier is required, just from "thingy.js" won't work. That's because bare specifiers are disallowed because they'll probably end up having a special meaning. (For instance, in Node.js, that's how you specify built-in modules, and modules installed in node_modules.) A module specifier must be a full URL, or a relative URL starting with /, ./, or ../.
Async
I said above that modules are loaded asynchronously, and there are two options available. This graphic from the spec says it best (see the spec for the latest copy of it):
As you can see, for type="module" scripts, if you don't put any special flag attributes on the script tag, all of the module's dependencies will be resolved and then the script will be run once parsing of the HTML is complete. If you include the async attribute, it may run sooner, before the HTML parsing is complete (for instance, if all the scripts are in cache). (defer is not valid for modules.)
According to this post in Mozilla's website, it's up to the implementation:
Because the system doesn’t specify how loading works, and because you can figure out all the dependencies ahead of time by looking at the import declarations in the source code, an implementation of ES6 is free to do all the work at compile time and bundle all your modules into a single file to ship them over the network!
This may change in the future, as it is still not fully standardized, but you can be sure that you will not need to add a script tag for every module.
Some module loaders today bundle all the files for you, but that's may not be the case when the future will be live, as it will not have an advantage in performance in HTTP2.
You can read the ES6 specification of import here.

What does a sub-path mean in the context of import statements?

Suppose I have a statement like this:
import * as bar from 'foo/bar';
I have a few questions:
What does the /bar bit mean?
Is there a sepcific (google-able) term for this?
Does this provide efficiency gains (reducing module bloat)?
How can I bundle a common-js module (ideally with Rollup) on NPM and support this syntax?
Breaking it down:
Firstly to provide context to your first and second question, let's go a bit further and break down all the parts of that statement:
import * as quux from 'foo/bar';
Note: The first bar instance in your example has been intentionally changed to quux to disambiguate the following points.
Collectively it is referred to as an Import Statement, or more specifically; an Import Declaration as defined in the ECMA-262 Imports Syntax Specification.
The import part is referred to as the Import Keyword.
The * as quux part is referred to as a NameSpace Import.
The asterisk * indicates that all exported bindings in bar will be imported to a newly created namespace object called quux. The resultant effect is that the quux object will hold all the exported members from bar.
The quux part of that is referred to as the Imported Binding and, as previously mentioned, it's used as the name for the newly created namespace object.
The from 'foo/bar' part is referred to as the From Clause.
The foo/bar part is a String Literal and is referred to as the Module Specifier... it's simply a filepath.
Answers to your specific questions:
What does the /bar bit mean?
It's part of the Module Specifier which is part of the From Clause. It is simply a reference to the name of the file whose exported member(s) will be imported from. In this example its exported member(s) will be imported into a new namespace object called quux.
With regards to what is that actual "part" called; ECMA-262 doesn't provide a specific reference/name for it, however, I refer to that part as the filename; (i.e. the filename in the filepath of the module to import).
As far as I know, /bar may or may not need to include a file extension (i.e. /bar.js). Again there's nothing in the ECMA-262 Imports Syntax that enforces this. ECMAScript only defines the syntax for modules and not the specific mechanism(s) for loading them. So the requirement for with or without a .js suffix may vary per implementation. For example:
In Apple's latest Safari browser built upon WebKit which runs on iOS the inclusion of the .js suffix is necessary.
In Modules docs for Node v8.10.0 they do include the .js file extension for imported files in their examples. Note: As ES6 Modules currently have a Stability Index 2 this could change.
Is there a specific (google-able) term for this?
Not per se, as ECMA hasn't named it specifically. You could try googling some of the terminology/nomenclature that I've previously mentioned.
Does this provide efficiency gains (reducing module bloat)?
I'm not sure I fully understand what you mean by "module bloat". However, If you mean will it result in less modules in application code? I think not, it's more likely result in an increased usage of modules.
Efficiency gains will be had from there being native ES6 Module support. Native support by it's very nature can bring speed/performance increases. Other benefits of ES6 Modules are:
ES6 Modules are statically analyzable which allows dead/unused code elimination via a process named Tree Shaking. More info here and here . So, if that's what you mean by the term "module bloat" - then yes; unused/dead code will be removed by tools that perform Tree Shaking.
Caveat; I'm not 100% certain whether tools that perform Tree Shaking are capable of removing dead code when using the wildcard/asterisk (*) in a NameSpace Import. It MAY be necessary to import specific member(s) that you'll use instead, i.e.
import { foo, bar, quux } from './foo/bar.js';
It's an official ECMAScript standard.
The example that you gave included a NameSpace Import, so there's another benefit - it will help to avoid namespace collisions.
More benefits are mentioned here.
How can I bundle a common-js module (ideally with Rollup) on NPM and support this syntax?
Rollup works with a plugin named #rollup/plugin-commonjs which will convert CommonJS modules to ES6, so they can be included in a Rollup bundle.

Difference between System.import() and import()?

In webpack 1 docs is statement that in webpack 2 will use System.import() for dynamic require:
Luckily, there is a JavaScript API “loader” specification being
written to handle the dynamic use case: System.load (or
System.import). This API will be the native equivalent to the above
require variations.
And during that time all around the web was examples of using this System.import().
Before releasing webpack 2, authors decide to change System.import() to import():
add import() as Code Splitting construct. It should be used instead of
System.import when possible. System.import will be deprecated in
webpack 2 release (removed in webpack 3) as it's behavior is incorrect
according to the spec.
This import() is based on tc39/proposal-dynamic-import specification, and you can read more why they made this change here.
Can someone explain difference between System.import() and import()?
Despite different name, usage looks the same:
import(modulePath)
.then(module => module.default())
.catch(/* ... */);
System.import(modulePath)
.then(module => module.default())
.catch(/* ... */);
But in weback 2 doc is: "System.import() behavior is incorrect according to the spec" - so it suggest that there is difference between System.import() and import().
Here's what you're looking for: tc39 Proposal for Import
An actual function
Drafts of the Loader ideas collection have at various times had actual functions (not just function-like syntactic forms) named System.import() or System.loader.import() or similar, which accomplish the same use cases.
The biggest problem here, as previously noted by the spec's editors, is how to interpret the specifier argument to these functions. Since these are just functions, which are the same across the entire Realm and do not vary per script or module, the function must interpret its argument the same no matter from where it is called. (Unless something truly weird like stack inspection is implemented.) So likely this runs into similar problems as the document base URL issue for the importModule function above, where relative module specifiers become a bug farm and mismatch any nearby import declarations.

How will browsers handle ES6 import/export syntax

I've been thinking around this question lot of days and i have decided to ask the experts.
How browsers will handle the new import/export syntax ? I mean: will the modules be loaded asynchronously ? Referencing only my main or entry file and browsers will lazy load the requiere modules.
Maybe am i missing or misunderstanding something about this new architecture ?
Thank you very much!
Regards.
This is standardized now and supported by all major modern browsers.
will the modules be loaded asynchronously?
Yes, with two options available; details below.
Referencing only my main or entry file and browsers will lazy load the requiere modules.
Not so much "lazy," but yes.
Enabling it
Details in the spec here and here (and possibly elsewhere).
To get this behavior, you specify that your script is a module by using type="module":
<script src="main.js" type="module"></script>
or for inline scripts
<script type="module">
// ...module code here
</script>
That means that the script is parsed and handled per the Module definition in the JavaScript specification instead of per the Script definition, which means it can have imports (and exports).
Imports are resolved relative to the script's URL (for modules loaded via a separate resource such as the main.js above, just like CSS) or relative to the document (for inline modules like the one above).
So for instance, if I have this in my document at http://example.com/index.html:
<script src="./handy/stuff/nifty.js" type="module"></script>
...and nifty.js contains
import Thingy from "./thingy.js";
...then the browser looks for http://example.com/handy/stuff/thingy.js, not http://example.com/thingy.js. Again, just like CSS imports.
Note that the ./ on that module specifier is required, just from "thingy.js" won't work. That's because bare specifiers are disallowed because they'll probably end up having a special meaning. (For instance, in Node.js, that's how you specify built-in modules, and modules installed in node_modules.) A module specifier must be a full URL, or a relative URL starting with /, ./, or ../.
Async
I said above that modules are loaded asynchronously, and there are two options available. This graphic from the spec says it best (see the spec for the latest copy of it):
As you can see, for type="module" scripts, if you don't put any special flag attributes on the script tag, all of the module's dependencies will be resolved and then the script will be run once parsing of the HTML is complete. If you include the async attribute, it may run sooner, before the HTML parsing is complete (for instance, if all the scripts are in cache). (defer is not valid for modules.)
According to this post in Mozilla's website, it's up to the implementation:
Because the system doesn’t specify how loading works, and because you can figure out all the dependencies ahead of time by looking at the import declarations in the source code, an implementation of ES6 is free to do all the work at compile time and bundle all your modules into a single file to ship them over the network!
This may change in the future, as it is still not fully standardized, but you can be sure that you will not need to add a script tag for every module.
Some module loaders today bundle all the files for you, but that's may not be the case when the future will be live, as it will not have an advantage in performance in HTTP2.
You can read the ES6 specification of import here.

What does the "!" character do in nodejs module names?

I've started using the intern library to write functional tests in js, and I realized that I couldn't understand this syntax:
var assert = require('intern/chai!assert');
var registerSuite = require('intern!object');
What is the purpose of the ! character in the argument of the require() method?
Short answer
It identifies a resource that is part of a plugin.
The structure of the identifier is: [plugin]![resource].
Long answer
In the documentation, you can find that:
Intern is built on top of a standard amd loader, which means that its modules are also normally written in the AMD module format.
That's why and how the require function is actually injected, so it's clear that you are not using the require module provided along with Node.JS.
It states also that:
[AMD format] Allows modules and other assets to be asynchronously or conditionally resolved by writing simple loader plugins
If you follow the link provided with the documentation when it cites the loaders, you find that:
Loader plugins extend an AMD implementation by allowing loading of resources that are not traditional JavaScript dependencies.
In particular, you can find that a dependency has the following form:
[Plugin Module ID]![resource ID]
It goes without saying that the default implementation of the loader you get by using intern adheres to the above mentioned standard.
That said, it follows that, if we consider:
intern/chai!assert
You can read it as inter/chai as plugin module and assert as actually required resource.
The purpose of the ! character in the argument of the require() method is to satisfy the requirements of the syntax used to identify a resource that is itself part of a plugin.
I got this answer for you extracted from this similiar question and very well explained by explunit:
The exclamation point syntax is reserved for plugins. Typically there would be something else following the exclamation point which indicates the resource that the plugin would load, e.g. text!myTemplate.html, but in the case of domReady! the plugin exists just as a way to wait until DOM loaded before invoking your callback function, so nothing needs to follow the exclamation point.

Categories

Resources