I am having difficulty getting my npm library to support subpath imports/requires via the exports field in the package.json. For context, package.json supports a field "exports" which allows you to conditonally expose files based on the runtime (i.e. commonjs OR ecmascript.
When importing the npm library in my typescript project, I get the following error:
// How I import
import logger from '@myorg/custom-logger/src/logger';
// The error I get in vscode
Cannot find module '@myorg/custom-logger/src/logger' or its corresponding type declarations.
The tsc compiler error:
TSError: ⨯ Unable to compile TypeScript:
src/config/winston.ts:1:20 - error TS2307: Cannot find module '@myorg/custom-logger/src/logger' or its corresponding type declarations.
The custom-logger
package comes with support for commonjs and esm. It is built & deployed to npm with the following structure:
esm/
--- src/
--- index.js
--- logger.js
--- index.d.ts
--- logger.d.ts
--- package.json which contains { "type": "module" } (also tried without this - same issue occurs)
cjs/
--- src/
--- index.js
--- logger.js
--- index.d.ts
--- logger.d.ts
--- package.json which contains { "type": "commonjs" } (also tried without this - same issue occurs)
package.json which contains (see below)
The main package.json
in the @myorg/custom-logger
package contains the following:
{
"name": "@myorg/custom-logger",
"version": "0.1.4",
"dependencies": {
"app-root-path": "^3.0.0",
"winston": "^3.8.1"
},
"devDependencies": {
"@types/app-root-path": "^1.2.4",
"@types/winston": "^2.4.4"
},
"types": "./esm/src/index.d.ts",
"typings": "./esm/src/index.d.ts",
"module": "./esm/src/index.js",
"main": "./cjs/src/index.js",
"exports": {
"./src/*": {
"types": "./esm/src/*.d.ts",
"import": "./esm/src/*.js",
"require": "./cjs/src/*.js"
},
".": {
"types": "./esm/src/index.d.ts",
"import": "./esm/src/index.js",
"require": "./cjs/src/index.js"
}
}
}
The issues I am having are as follows:
- Typescript and vscode doesn't seem to honour the exports logic (it throws the errors seen above)
What I am trying to achieve is:
- Be able to import subpaths. i.e.
import mylib from '@myorg/custom-logger/src/logger'
I am using "typescript": "4.7.4",
and am using esm
(ecmascript) natively in node.
CodePudding user response:
So to get this working, I had to update my tsconfig "moduleResolution" config.
Here is my new config (notice how I have "moduleResolution": "Node16"
set):
- You can also use
NodeNext
as the moduleResolution
{
"compilerOptions": {
"target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
"module": "ESNext", /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"moduleResolution": "Node16",
"outDir": "build/" /* Redirect output structure to the directory. */,
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
"rootDir": "./",
"resolveJsonModule": true
},
"include": ["src/", "e2e"],
"exclude": ["node_modules", "build", "logs", "db"],
"resolveJsonModule": true,
"esModuleInterop": true
}
Before this, the moduleResolution
value was set to node
. After further investigation, the node
moduleResolution does not support the "exports" field in the package.json. Here is a great answer that explains it in more detail