Package exports and eslint-plugin-import

Posted 10 February 2025


I was recently creating a new npm package with multiple entrypoints. Using Vite library mode I configured the entry points:

import { defineConfig } from "vite";

export default defineConfig({
  build: {
    lib: {
      entry: {
        "library": "src/index.ts",
        "some-import": "src/some-import.ts",
      },
      name: "library",
    },
  },
});

I then added the exports field to the package's package.json file:

{
  "name": "library",
  "main": "./dist/library.cjs",
  "module": "./dist/library.js",
  "types": "./dist/library.d.ts",
  "exports": {
    ".": {
      "types": "./dist/library.d.ts",
      "import": "./dist/library.js",
      "require": "./dist/library.cjs",
      "default": "./dist/library.cjs"
    },
    "./some-import": {
      "types": "./dist/some-import.d.ts",
      "import": "./dist/some-import.js",
      "require": "./dist/some-import.cjs",
      "default": "./dist/some-import.cjs"
    }
  }
}

I then tried using this package in another project, and although TypeScript was able to resolve the module I was seeing errors from eslint:

error  Unable to resolve path to module 'library/some-import'  import/no-unresolved

I found this eslint-plugin-import issue with recommendations to switch to eslint-import-resolver-typescript, but I didn't want to force other projects to change their configuration just to use this package.

I also saw that in this same project we were importing msw/browser without any complaints from eslint, so I decided to look at how msw was configured.

// No complaints from eslint!
import { setupWorker } from "msw/browser";

msw's root package.json matched my own, but there was also a browser directory in the root of the package with another package.json:

// node_modules/msw/browser/package.json
{
  "main": "../lib/browser/index.js",
  "module": "../lib/browser/index.mjs",
  "types": "../lib/browser/index.d.ts"
}

This was the key to getting this working, helping the resolver treat msw/browser as a separate package which resolved correctly. I added an extra package.json to my own library in library/some-import/package.json:

{
  "main": "../dist/some-import.cjs",
  "module": "../dist/some-import.js",
  "types": "../dist/some-import.d.ts"
}

And everything worked as expected! I hope this helps you if you're running into similar issues.


Related posts

Mock server-sent events (SSE) with msw

Published

Mock Service Worker supports mocking SSE

Dynamically load remoteEntry.js files

Published

Control loading Webpack Module Federation remoteEntry.js files to improve peformance

Exclude node_modules with Webpack

Published

Avoid bundling dependencies when building a library


Thanks for reading

I'm Alex O'Callaghan and this is my personal website where I write about software development and do my best to learn in public. I currently work at Mintel as a Principal Engineer working primarily with React, TypeScript & Python.

I've been leading one of our platform teams maintaining a collection of shared libraries, services and a micro-frontend architecture.

I'm from London and you can find me on a few different social media platforms: