vitest-dev / vitest-dev/vitest

[ES Module but shipped in a CommonJS package] Lib importing another ESM-only library

Open
#6,875 10 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

pending triage
Dominant language
TypeScript
Stars
17.1k
Forks
2k
Avg merge
1d 22h
Merged PRs (30d)
94

Description

Describe the bug

I was creating a library with unbuild using rollup and generating dist/*.cjs and dist/*.mjs files.
As I didn't want to import directly from lib/dist, I created the following package.json:

  "type": "module",
  "exports": {
    ".": {
      "require": "./dist/index.cjs",
      "node": "./dist/index.cjs",
      "import": "./dist/index.mjs",
      "types": "./dist/index.d.ts"
    },
    "./*": {
      "require": "./dist/*/index.cjs",
      "node": "./dist/*/index.cjs",
      "import": "./dist/*/index.mjs",
      "types": "./dist/*/index.d.ts"
    }
  },
  "files": [
    "dist"
  ],

This lib depends on another lib, esm-only.

esm-only is packaged as ESM but with .js extension and I can't control how this library bundled

My App project uses lib. When I ran vitest on my App project, I got this error:

 FAIL  src/lib.test.ts [ src/lib.test.ts ]
SyntaxError: Unexpected token 'export'
 ❯ ../lib/dist/utils/index.cjs:3:15
      1| 'use strict';
      2| 
      3| const utils = require('esm-only/dist/utils');
       |               ^
      4| 
      5| const multiply = (a, b) => {

Module node-packages/esm-only/dist/utils/index.js:1 seems to be an ES Module but shipped in a CommonJS package. To fix this issue, change the file extension to .mjs or add "type": "module" in your package.json.

The only thing I was able to make it work was to change lib/package.json to:

  "type": "module",
  "main": "dist/index.cjs",
  "module": "dist/index.mjs",
  "types": "dist/index.d.ts",
  "files": [
    "dist"
  ],

And then change src/lib.test.ts to:

import { multiply } from "lib/dist/utils";

But as you can see, I have lib/dist/utils, I want to be able to import lib/utils instead.

Another option is to change lib/build.config.ts to use mkdist:

import { defineBuildConfig } from "unbuild";

export default defineBuildConfig({
  entries: [
    {
      builder: "mkdist",
      input: "src/",
      distDir: "dist",
      ext: "js",
      format: "esm",
    },
  ],
  outDir: "dist",
  declaration: true,
});

And my lib/package.json to:

 "type": "module",
  "exports": {
    ".": {
      "require": "./dist/index.js",
      "node": "./dist/index.js",
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    },
    "./*": {
      "require": "./dist/*/index.js",
      "node": "./dist/*/index.js",
      "import": "./dist/*/index.js",
      "types": "./dist/*/index.d.ts"
    }
  },
  "files": [
    "dist"
  ],

Finally, this ONLY DOESN'T work on Vitest. On Vite I can normally run both in dev and production mode.

Related issues:

Reproduction

I created this repository to reproduce the issue I was having in another project: https://github.com/varugasu/node-packages

  • Go to esm-only, then pnpm build
  • Go to lib, then pnpm build
  • Go to app, then pnpm test
System Info
System:
    OS: macOS 15.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 2.96 GB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.11.0 - ~/Library/Caches/fnm_multishells/50248_1730980063968/bin/node
    npm: 10.2.4 - ~/Library/Caches/fnm_multishells/50248_1730980063968/bin/npm
    pnpm: 9.9.0 - ~/Library/pnpm/pnpm
    bun: 1.1.26 - /opt/homebrew/bin/bun
    Watchman: 2024.10.21.00 - /opt/homebrew/bin/watchman
  Browsers:
    Safari: 18.1
  npmPackages:
    @vitejs/plugin-react: ^4.3.3 => 4.3.3 
    vite: ^5.4.10 => 5.4.10 
    vitest: ^2.1.4 => 2.1.4
Used Package Manager

pnpm

Validations

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Clone the linked node-packages reproduction, build esm-only and lib, then run pnpm test from app. Compare lib/package.json and lib/build.config.ts with Vitest's dependency handling, and confirm done when lib/utils imports work in Vitest without breaking the Vite dev and production cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, rollup, typescript, vite
Domain
build-system, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.