In my Express project, I import from paths like @common/foo
. Thanks to paths
in tsconfig.json
, it's just an alias to ../common/src/foo
. That's awesome and works in development with this script in nodemon.json
:
{
"watch": ["src", "../common/src"],
"ext": "ts",
"ignore": ["src/public"],
"exec": "ts-node -r tsconfig-paths/register src/index.ts"
}
The problem is that I can't make it work in production mode.
I build the project with tsc
, and if I inspect the generated files, they import stuff from @common/
and not from ../common/src/
. At first I thought it's fine, since tsconfig-paths
works in runtime, so I just need to include it in the start
script as such:
node -r tsconfig-paths/register dist/index.js
Unfortunately it didn't work, and I get those Cannot find module '@common/foo
error messages in console.
What's the problem? Did i configured it wrong?
My package.json
(dropped all irrelevant parts):
{
"main": "index.js",
"scripts": {
"start": "cross-env NODE_ENV=prod node dist/index.js",
"build": "rimraf ./dist/ && cross-env NODE_ENV=prod tsc"
},
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"@types/express": "^4.17.4",
"@types/node": "^13.11.0",
"cross-env": "^6.0.3",
"rimraf": "^3.0.2",
"ts-node": "^8.8.2",
"tsconfig-paths": "^3.9.0",
"typescript": "^3.8.3"
}
}
My tsconfig.json
(dropped all irrelevant parts):
{
"compilerOptions": {
"module": "commonjs",
"baseUrl": "./",
"outDir": "dist",
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"noImplicitAny": false,
"target": "es6",
"emitDecoratorMetadata": true,
"moduleResolution": "node",
"importHelpers": true,
"types": [
"node"
],
"typeRoots": [
"node_modules/@types"
],
"paths": {
"@common/*": [
"../common/src/*"
]
}
},
"include": [
"./src/**/*.ts"
],
"exclude": [
"./src/dist/"
],
"references": [
{
"path": "../common"
}
]
}
ts-node supports a variety of options which can be specified via tsconfig.
The tsconfig. json file specifies the root files and the compiler options required to compile the project. JavaScript projects can use a jsconfig. json file instead, which acts almost the same but has some JavaScript-related compiler flags enabled by default.
The tsconfig. json is generally put in the root folder of the project.
for anyone still stuck on this:
node -r ts-node/register/transpile-only -r tsconfig-paths/register dist/index.js
this is what you need to do.
This was asked around in many places, and apparently Typescript can make path aliases for development, but not production (Don't quote me on that, have been working with it for barely a month).
To work around that, I installed 'module-alias', a package that solves the path issue after build, without interfering with development.
I was building an Express-js app, and had these files:
server.js:
import env from '@env';
import app from './app';
app.listen(env.SERVER_PORT || 3000);
tsconfig.json (relevant parts):
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@env": ["path/to/env"]
}
}
}
This resolved the path during development runtime, but not after building with 'tsc'. To work around it, I added the 'module-alias' package and did the following changes:
server.js:
import './paths';
import env from '@env';
import app from './app';
app.listen(env.SERVER_PORT || 3000);
paths.js
import 'module-alias/register';
import { addAliases } from 'module-alias';
addAliases({
'@env': `${__dirname}/path/to/env`,
});
This ensured that @env would resolve in both dev runtime and after building. Hope it helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With