1.1.1 • Published 2 years ago

is-bundling-for-browser-or-node v1.1.1

Weekly downloads
-
License
MIT
Repository
-
Last release
2 years ago

Is bundling for browser or node (?)

Authoring isomorphic packages yourself can be tricky.

When you use a bundler (webpack, rollup, parcel, vite etc.) and import external modules, the bundler reads the package.json fields to figure out which file it should use.

If your bundler targets a node.js environment, it usually prefers the main field
If your bundler targets a browser environment, it usually prefers the browser field (see spec)

There's two scenarios where isomorphism in js becomes especially hairy:

  1. use other 3rd party isomorphic packages that are served at compile-time (not runtime), but you want to use the package on both server and client
  2. you want to offer different builds for each environment (browser, node) to avoid polyfilling the native functionality for both environments in the same bundle

One example is when using the cross-fetch lib. It's isomorphic at bundle time, not runtime.

Read more background here and specifically this one talks about node.js vs. browser packages

Usage

Just import the named exports. The magic happens when your bundler resolves this module itself.

NOTE! The check happens at bundle/build-time, NOT runtime.

import {
  isFor,
  isForNode,
  isForBrowser,
} from "is-bundling-for-browser-or-node";

// If your bundler targets a node.js environment
expect(isFor).toBe("node");
expect(isForNode).toBe(true);
expect(isForBrowser).toBe(false);

// If your bundler targets a browser environment
expect(isFor).toBe("browser");
expect(isForNode).toBe(false);
expect(isForBrowser).toBe(true);

Example with webpack

Here's a common appraoch to building an isomorphic packages where you provide a bundle for each target environment. Here, we force webpack to prefer different import strategies with the target property.

// webpack.config.js
export default [
  // node
  {
    entry: "./src/index.ts",
    target: "node",
    output: {
      path: path.resolve(__dirname, "dist"),
      filename: "myLib.node.js",
      library: {
        name: "myLib",
        type: "umd",
        export: "default",
      },
    },
    externals: [nodeExternals()],
  },
  // browser
  {
    entry: "./src/index.ts",
    target: "web",
    output: {
      path: path.resolve(__dirname, "dist"),
      filename: "myLib.browser.js",
      library: {
        name: "myLib",
        type: "umd",
        export: "default",
      },
    },
  },
];

If you for instance want to offer different default settings for each environment, you can use this package to do so without having to split up your source files into two (i.e. you can keep the same entry).

License

MIT License