Lucas
Lucas

Reputation: 63

how to import esm libraries without setting "type": "module" in package.json file?

I have a typescript node project which is working fine. Now I'm trying to add the vinejs library to the project. But VineJS is an ESM only package and when adding it to the project and trying to run ts-node the following error appears:

Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.

Then I added to the package.json "type": "module" and "--esm" in the ts-node command in the scripts. At this point I was able to run ts-node with no errors.

But then I tried to build the project and run it through the index.js file generated in the build in the ./dist folder and I got another error.

ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and 'C:\dev\personal\test\package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

How to run project through dist folder with "type": "module" defined in package.json ?

My config files.

package.json

{
  "name": "test",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "start:dev": "ts-node --esm -r tsconfig-paths/register src/index.ts",
    "start:dev-watch": "nodemon --watch src/** --ignore src/**/*.spec.ts --exec npm run start:dev",
    "build": "tsc && tsc-alias",
    "start:prod": "node dist/index.js",
  },
  "license": "ISC",
  "dependencies": {
    "@vinejs/vine": "^1.5.2",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.17",
    "@types/node": "^20.3.3",
    "nodemon": "^3.0.1",
    "ts-node": "^10.9.1",
    "tsc-alias": "^1.8.7",
    "tsconfig-paths": "^4.2.0",
    "typescript": "^5.1.6"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "rootDir": "./src",
    "moduleResolution": "Node",
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"]
    },
    "allowImportingTsExtensions": true,
    "outDir": "./dist",
    "noEmit": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
  }
}

Expected import an ESM only package and run the node project through the generated file in the dist folder.

Upvotes: 4

Views: 5189

Answers (1)

Evert
Evert

Reputation: 99736

The easiest will be to not set "type": "module" and import "VineJS" by using const pkg = await import('vinejs') This is how commonJS projects can import ESM-only projects.

If you're opting to do a full conversion to ESM, you will need to make a number of changes to your configuration and sources, one of which is making sure that every local import has the .js extension and stop using exports. You'll be able to find full migration guides on the web, but I think writing everything down is a bit out of scope for a stack overflow answer.

Upvotes: 1

Related Questions