Package exports and eslint-plugin-import

Posted 10 February 2025 · 1 min read

Tags:

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.


Get new posts by email

Subscribe to get new posts to your inbox, or use the RSS feed with your own feed reader.


Related posts · browse by tag

Mock server-sent events (SSE) with msw

Published · 2 min read

Mock Service Worker supports mocking SSE

Dynamically load remoteEntry.js files

Published · 2 min read

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

Exclude node_modules with Webpack

Published · 2 min read

Avoid bundling dependencies when building a library