Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to choose 'module' instead of 'main' file in package.json

I have created some npm modules and compile them to:

  • commonJS (using exports.default =) and
  • esm (using export default)

I set up my package.json like so:

main: "index.cjs.js",
module: "index.esm.js"

When I npm install the package and I simple import it like:

import myPackage from 'my-package'

It will automatically choose the main file, not the module.

My question:

Is there a way to import the module file instead when doing import myPackage from 'my-package' in a JavaScript file?

Why I choose the commonJS file for "main":

I noticed that using Node, importing an esm file is not possible because of export default, it has to be commonJS. I have some simple helper JS functions like this and this, and I would want them to be usable to the widest audience. That's why I chose cjs for the "main" path in package.json.

Why I define a separate "module" in package.json:

Lots of famous libraries like Vue.js are already doing this. See further information on this Stackoverflow thread:

What is the "module" package.json field for?

Why do I want to be able to import the "module" file instead of the "main" file:

There is currently a bug in Rollup where it will not properly show JSDoc comments when coding after having imported a cjs file, but it does work when importing a es file.

The workaround I want to avoid:

Just set "main" to the esm file in package.json, right? But then all users who are using my packages in Node apps will not be able to use it anymore...

→ I'm really confused about all this as well, but I think I did enough research to make sense of all it. That being said, if anyone knows a better approach or any other advice, please do tell me in the comments down below!!

like image 940
mesqueeb Avatar asked Sep 26 '18 04:09

mesqueeb


People also ask

How do I add a module to a package json?

To add dependencies and devDependencies to a package. json file from the command line, you can install them in the root directory of your package using the --save-prod flag for dependencies (the default behavior of npm install ) or the --save-dev flag for devDependencies.

Do you need a main in package json?

You only need a main parameter in your package. json if the entry point to your package differs from index. js in its root folder. For example, people often put the entry point to lib/index.

What is the module field in package json?

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.

What should be the main in package json?

The main property json is a direction to the entry point to the module that the package. json is describing. In a Node. js application, when the module is called via a require statement, the module's exports from the file named in the main property will be what's returned to the Node.


Video Answer


2 Answers

Just don't use extension for main file and have es6 and CommonJS version as two separate files with the same name and in the same directory, but with different extension, so:

index.js // transpiled CommonJS code for old nodejs
index.mjs // es6 module syntax

and in package.json:

{
  "main": "index"
}

If node is launched with --experimental-modules flag, it would use *.mjs file, otherwise *.js.

like image 163
Remek Ambroziak Avatar answered Oct 10 '22 09:10

Remek Ambroziak


Nodejs does not support "module" but does support the newer "exports" spec.

https://nodejs.org/api/packages.html#exports

https://github.com/nodejs/node/blob/v16.14.0/lib/internal/modules/esm/resolve.js#L910

  "exports": {
    "import": "./main-module.js",
    "require": "./main-require.cjs"
  },
like image 1
Jamie Pate Avatar answered Oct 10 '22 09:10

Jamie Pate