I've seen some npm packages (vue for example) have a module field in their package.json.
But module is not included in the package.json documentation - is this a convention of some kind? Is there documentation for this somewhere?
Update: April 2022
The module field is not officially defined by Node.js and support is not planned. Instead, the Node.js community settled on package exports which they believe is more versatile.
For practical reasons JavaScript bundlers will continue to support the module field. The esbuild docs explain when to use module as well as related fields main and browser.
Original Answer
Is "module" an official npm property or is this a convention of some kind?
It's a proposal, but likely to be supported due to de facto usage.
Is there documentation for this somewhere?
There is, in fact, and it can be found right here and later removed here.
What's it for?
ES6 Module Interoperability in Node. Additional discussion can be found here and here. And here's a blog post from Rich Harris talking more about it.
This is used by bundler tools for ESM (ECMAScript Module) detection. The Rollup documentation says it pretty well:
If your package.json file also has a module field, ES6-aware tools
like Rollup and webpack 2 will import the ES6 module version directly.
This article on Rollup 1.0 says it another way:
The main field makes sure that Node users using require will be served the UMD version. The module field is not an official npm feature but a common convention among bundlers to designate how to import an ESM version of our library.
Further discussion of pkg.module is on the Rollup Github Wiki and the webpack Docs.
Related
Is it possible for an npm package to offer both ES5 and ES6 versions? I know that it's possible to target different module systems, i.e. link CommonJS via package.main and ESM via package.module.
It seems like a big inefficiency when you have a project that targets ES6 but have to load libs which are compiled to ES5, but were actually written in ES6 or later.
I'm asking as a package creator.
I'm getting my hands dirty with Babel for the 1st time to convert Jest tests from ES6 syntax to commonJS; this will likely involve using the #babel/plugin-transform-modules-commonjs babel plugin which I'm trying to install in my Next.js project. Looking at this part of Babel's configuration docs, I see the term package pop up a lot.
Are package hierarchies a Babel convention, Node-defined feature, or part of base JavaScript itself? What exactly defines a package in this context, and where is there documentation for them? Is babel-jest a stable alternative to this problem?
Babel uses a package.json file to resolve module dependencies. A package is a collection of files which can be imported using the require() function. You can read more about packages in the Node.js documentation on packages.
There is no standard way to define a package hierarchy, but Babel does have some conventions for how to organize your files. You can read more about that in the Babel documentation on organizing your code. Babel-jest is a stable alternative to converting Jest tests from ES6 syntax to commonJS. It provides support for using babel-plugin-transform-modules-commonjs to convert your modules to CommonJS.
Specifically, in the context of the Babel documentation you mentioned, the word "package" refers to your application itself (which is also considered a package) as well as other applications contained within the same repository (in case you have a monorepo containing many applications).
I've been looking all over the Internet without a clear answer for this.
Currently Node.js uses only CommonJS syntax to load modules, and if you really want to use the standard ECMAScript 2015 modules syntax, you either have to transpile it beforehand or use an external module loader at runtime.
Currently I'm not too positive to use either of those two methods, are the Node.js maintainers even planning to support ECMAScript 2015 modules or not? I haven't found an hint at all about this.
At the moment Node.js 6.x claims to support 96% of the ECMAScript 2015 features, but there isn't any reference to modules (Node.js ECMAScript 2015 support link).
Do you know if Node.js will support these modules out of the box, in the near future?
Node.js 13.2.0 & Above
Node.js 13.2.0 now supports ES Modules without a flag 🎉. However, the implementation is still marked as experimental so use in production with caution.
To enable ECMAScript module (ESM) support in 13.2.0, add the following to your package.json:
{
"type": "module"
}
All .js, .mjs (or files without an extension) will be treated as ESM.
There are a number of different options other than entire package.json opt-in, all of which are detailed in the documentation for 13.2.0.
Node.js 13.1.0 & Below
Those still using older versions of Node may want to try the [esm][3] module loader, which is a production-ready implementation of the ES Modules Specificaiton for Node.js:
node -r esm main.js
Detailed Updates...
23 April 2019
A PR recently landed to change the way ECMAScript modules are detected:
https://github.com/nodejs/node/pull/26745
It's still behind the --experimental-modules flag, but there are major changes in the way modules can be loaded:
package.type which can be either module or commonjs
type: "commonjs":
.js is parsed as CommonJS
the default for an entry point without an extension is CommonJS
type: "module":
.js is parsed as an ECMAScript module
does not support loading JSON or a native module by default
the default for an entry point without an extension is ECMAScript module
--type=[mode] to let you set the type on entry point. Will override package.type for entry point.
A new file extension .cjs.
this is specifically to support importing CommonJS in the module mode.
this is only in the ECMAScript module loader, the CommonJS loader remains untouched, but the extension will work in the old loader if you use the full file path.
--es-module-specifier-resolution=[type]
options are explicit (default) and node
by default our loader will not allow for optional extensions in the import, the path for a module must include the extension if there is one
by default our loader will not allow for importing directories that have an index file
developers can use --es-module-specifier-resolution=node to enable the CommonJS specifier resolution algorithm
This is not a “feature”, but rather an implementation for experimentation. It is expected to change before the flag is removed
--experimental-json-loader
the only way to import JSON when "type": "module"
when enable all import 'thing.json' will go through the experimental loader independent of mode
based on whatwg/html#4315
You can use package.main to set an entry point for a module
the file extensions used in main will be resolved based on the type of the module
17 January 2019
Node.js 11.6.0 still lists ES Modules as experimental, behind a flag.
13 September 2017
Node.js 8.5.0 has been released with support for mjs files behind a flag:
node --experimental-modules index.mjs
The plan for this is to remove the flag for the v10.0 LTS release.
--Outdated Information. Kept here for historical purposes--
8 September 2017
The Node.js master branch has been updated with initial support for ESM modules:
https://github.com/nodejs/node/commit/c8a389e19f172edbada83f59944cad7cc802d9d5
This should be available in the latest nightly (this can be installed via nvm to run alongside your existing install):
https://nodejs.org/download/nightly/
And enabled behind the --experimental-modules flag:
package.json
{
"name": "testing-mjs",
"version": "1.0.0",
"description": "",
"main": "index.mjs" <-- Set this to be an mjs file
}
Then run:
node --experimental-modules .
February 2017:
An Update on ES6 Modules in Node.js
The Node.js guys have decided that the least bad solution is to use the .mjs file extension. The takeaway from this is:
In other words, given two files foo.js and bar.mjs , using import * from 'foo' will treat foo.js as CommonJS while import * from 'bar'
will treat bar.mjs as an ES6 Module
And as for timelines...
At the current point in time, there are still a number of
specification and implementation issues that need to happen on the ES6
and Virtual Machine side of things before Node.js can even begin
working up a supportable implementation of ES6 modules. Work is in
progress but it is going to take some time — We’re currently looking
at around a year at least.
October 2016:
One of the developers on Node.js recently attended a TC-39 meeting and wrote up a superb article on the blockers to implementing for Node.js:
Node.js, TC-39, and Modules
The basic take-away from that is:
ECMAScript modules are statically analyzed, and CommonJS are evaluated
CommonJS modules allow for monkey-patching exports, and ECMAScript modules currently do not
It's difficult to detect what is an ECMAScript module and what is CommonJS without some form of user input, but they are trying.
*.mjs seems the most likely solution, unless they can accurately detect an ECMAScript module without user-input
-- Original Answer --
This has been a hot potato for quite some time. The bottom line is that yes, Node.js will eventually support the ES2015 syntax for importing/exporting modules - most likely when the specification for loading modules is finalized and agreed upon.
Here is a good overview of what's holding Node.js up. Essentially, they need to make sure that the new specification works for Node.js which is primarily conditional, synchronous loading and also HTML which is primarily asynchronous.
Nobody knows for sure right now, but I imagine Node.js will support import/export for static loading, in addition to the new System.import for dynamic loading - while still keeping require for legacy code.
Here's a few proposals on how Node might achieve this:
In defense of .js
.mjs modules
I am trying to upgrade my Aurelia project from a beta version to the March version.
One of the errors I am getting is:
Cannot find name 'Request'.
Googling this brings up this issue on GitHub: https://github.com/aurelia/fetch-client/issues/65
This issue says that the "fix" is to install the typescript definitions for whatwg-fetch. When I do install those typescript definitions, the error goes away.
But does that mean I need whatwg-fetch too? (Looking in my node_modules folder, whatwg-fetch is not installed.)
aurelia-fetch-client wraps the Fetch API. wahtwg-fetch is a Fetch polyfill, so it wouldn't make sense for the fetch client to depend on the polyfill. Furthermore, which polyfill you will use changed depending on which module loader you are using.
JSPM/SystemJS based apps use the fetch polyfill from GitHub, while most other module loaders use whatwg-fetch.
So yes, you will need to install whatwg-fetch, but there's a good reason for why the aurelia-fetch-client doesn't have a dependency on it.
I'm wondering if there's at least some community consensus on how to write reusable Angular2 code in TypeScript. I tried to summarise what I found out and what I'd like to know in context of Angular2.
Module/App directory structure and file names
In the official tutorial I see they put all code into app directory and all dependencies like node_modules or typings are in the parent directory.
Lowercase file names, .component.ts suffix for components and .service.ts for services. They put all files to the same directory which is going to be a huge mess?
One class/interface/enum per file. For classes, functions, interfaces and other names its probably best to stick to Coding guidelines for TypeScript by Microsoft?
Modules
Should modules compile and bundle themselves using postinstall npm hook? Or is it better to provide bundled version directly on git like most JavaScript libraries do?
Should I stick to system type of modules by default when I'm expecting that my module's going to be used only by browser or is it better to always use UMD?
Is there any reason to use CommonJS or AMD instead of system?
Using 3rd party modules
Should I expect that other developers will embed my modules with <script> tags or they'll load it using System.import()?
If my modules has dependencies on other JavaScript libraries, is it better to provide a bundled version of my whole module with all dependencies or just define them in package.json?
There's the Angular 2 Style Guide (https://github.com/mgechev/angular2-style-guide), as featured in Angular2 News:
The purpose of the following style guide is to present a set of best practices and style guidelines for the development of Angular 2 applications. If you are looking for an opinionated style guide for syntax, conventions...
Angular 1 had a community accepted style guide written by John Papa. There will be something similar created for Angular 2 in fact you can see the start of this coming together with the Tour of Heroes examples in place at angular.io