Different Main Entry Point in Package. Json for Node and Browser

Different Main Entry Point in Package. Json for Node and Browser

In isomorphic react app I have myModule which should behave differently on node and browser environments. I would like configure this split point in package.json for myModule:

package.json

{
  "private": true,
  "name": "myModule",
  "main": "./myModule.server.js",
  "browser": "./myModule.client.js"
}

file structure

├── myModule
│   ├── myModule.client.js
│   ├── myModule.server.js
│   └── package.json
│ 
├── browser.js
└── server.js

So when I use myModule in node I should get only myModule.server.js:

server.js

import myModule from './myModule';
myModule(); // invoke myModule.server.js

On the browser side should build bundle only with myModule.client.js:

browser.js

import myModule from './myModule';
myModule(); // invoke myModule.client.js

react-starter-kit uses this approach but I can't figure out where is this configuration defined.


Motivation

  1. package.json is good semantic point to do this kind of splitting.
  2. Client side bundle only contain myModule.client.js.

Known solution - not an answer for me

You can have this kind of file structure:

├── myModule
│    ├── myModule.client.js
│    ├── myModule.server.js
│    └── index.js           <-- difference
│ 
├── browser.js
└── server.js

And in index.js:

if (process.browser) { // this condition can be different but you get the point
    module.exports = require('./myModule.client');
} else {
    module.exports = require('./myModule.server');
}

The main problem with this is that client bundle contains a lot of heavy kB backend code.


Maya Lin-Takahashi
Author

Maya Lin-Takahashi

Maya is a hardware enthusiast who tests and reviews smart home devices, smartphones, wearables, and audio gear. She focuses on practical consumer value and build quality.