Reputation: 6967
I have set up an example project to demonstrate the issue:
https://github.com/garethrbrown/node-share-code
In this example there are two projects, example-api (a mini express project) and example-shared (a class library), both using Node JS / TypeScript. I want example-api to be able to use classes from example-shared to avoid code duplication. Having followed this example, I have referenced the example-shared project from package.json
in example-api.
"dependencies": {
"example-shared": "file:..\\example-shared",
"express": "^4.17.1"
}
Having done this, and following running npm install
, intellisense in VSCode sees ApiClass
from the example-shared project and assists with the import.
I can then run by build command tsc --build
via NPM, which succeeds.
I can also see that the sym link has been created in the example-api node_modules
directory.
However, when I try to run the example-api project using the npm start
script from under example-api, I get an error along the lines of:
Error: Cannot find module 'example-shared/apiClass'
Require stack:
...
code: 'MODULE_NOT_FOUND',
requireStack: [
...
]
I have tried running commands from different locations such as described here, but with no luck so far.
I'm using current stable versions of Node (14+) and NPM (7+).
I don't want to share via NPM or git repositories as I feel it will slow down development.
What am I doing wrong?
Upvotes: 2
Views: 2241
Reputation: 634
As per @mtbno's answer, the standard behavior without "outDir"
is all js and map files will just be created next to each of your TypeScript files, which is super gross.
Without using some extra npm package or webpack or any of that, you can solve this by adding that "outDir"
in your tsconfig, and then making a couple of tweaks to your package.json.
For argument's sake, say your root TypeScript file is called app.ts
and your outDir folder is lib
.
Relevant sections in your package.json can look like this:
"scripts": {
"build": "tsc --build",
"clean": "tsc --build --clean",
"start": "npm run build && node ./lib/app"
},
and
"main": "./lib/app",
And here's an example tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"lib": ["es6"],
"sourceMap": true,
"outDir": "./lib",
},
"exclude": [
"node_modules"
]
}
After those 2 files are updated, then running npm run start
should build out your lib folder with the compiled JavaScript, and your server should start up successfully. Note that if you previously did a build and you have "old" .js and .map files next to your TypeScript files, you may have to delete those manually because npm run clean
won't do it for you.
Upvotes: 0
Reputation: 600
Seems like this is a discussed problem, see this post Typescript: How to resolve absolute modules paths for node.js?
I did not investigate further, but in the example-shared
folder you can remove "outDir"
from your example-shared/tsconfig.json
and then run npm run build
.
Unfortunately, this will emit the javascript files next to typescript files instead of placing them in a separate directory.
Finally, in the example-api
run npm i
, npm run build
and npm start
.
Now, Express will run because Node is using the javascript file instead of typescript file.
Upvotes: 1