1

have a problem in writing typescript server app and compiling it into js for production.

TLDR - https://github.com/kricha/ts-server-test

index.ts

'use strict';

import {Server, Socket} from "socket.io";
import {App} from '@tinyhttp/app';
import {logger} from './logger';

import * as fs from 'fs';
if (!fs.existsSync('./src/test.ts')) {
    logger.error(`NOK: No  ./src/test.ts`);
}

const port = 3000;

const app = new App();
const s1 = app
    .get('/', (_, res) => void res.send('<h1>Hello World</h1>'))
    .listen(port, () => console.log(`Started on http://localhost:${port}!`));
;

const io = new Server(s1, {
    cors: {
        origin: 'localhost',
        methods: ["GET", "POST"],
        credentials: true
    }
});

io.on("connection", (socket: Socket) => {
    // ...
});

logger.info('OK: end.');
console.log('end.');

logger.ts

'use strict'

import Log4js from 'log4js';

Log4js.configure({
    appenders: {
        predictive: {
            type: 'dateFile',
            filename: 'log/predictive.log',
            pattern: 'yyyy-MM-dd',
            compress: true,
            daysToKeep: 14,
            layout: {
                type: 'pattern',
                pattern: '%d{yy-MM-dd hh:mm:ss.SSS} [%p] %m',
            },
        },
        out: {
            type: 'stdout',
            layout: {
                type: 'pattern',
                pattern: '%[%d{yy-MM-dd hh:mm:ss.SSS} [%p]%] %m',
            },
        },
        file_log: {
            type: 'logLevelFilter',
            level: 'all',
            appender: 'predictive',
        },
        console_log: {
            type: 'logLevelFilter',
            level: 'info',
            appender: 'out',
        },
    },
    categories: {
        default: {appenders: ['file_log', 'console_log'], level: 'all'},
    },
    pm2: true,
});


export const logger = Log4js.getLogger();

package.json

{
  "type": "module",
  "devDependencies": {
    "@types/node": "^16.11.12",
    "ts-node": "^10.4.0",
    "tsm": "^2.2.1",
    "typescript": "^4.5.3"
  },
  "dependencies": {
    "@tinyhttp/app": "^2.0.13",
    "log4js": "^6.3.0",
    "socket.io": "^4.4.0"
  }
}

tsconfig.json

{
    "compilerOptions": {
      "rootDir": "src",
      "outDir": "dist",
      "target": "es5",
      "lib": [
        "es2020", "DOM"
      ],
      "module": "ESNext", // (A)
      "moduleResolution": "node", // (B)
      "esModuleInterop": true,
      "strict": true,
    //   "sourceMap": true,
    //   // Needed for CommonJS modules
      "allowSyntheticDefaultImports": true, // (C)
    //   //
      "declaration": true,
    }
  }

My problems:

  1. Can't use require (maybe this is ok, i just need to readjust
  2. tsc compiling files to js not properly (it skips .js in import, and i can't run with just node dist/index.js)

So:

Just running: node dist/index.js

node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/app/dist/logger' imported from /app/dist/index.js
    at new NodeError (node:internal/errors:371:5)
    at finalizeResolution (node:internal/modules/esm/resolve:416:11)
    at moduleResolve (node:internal/modules/esm/resolve:932:10)
    at defaultResolve (node:internal/modules/esm/resolve:1044:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:422:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:222:40)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Running: node --experimental-specifier-resolution=node dist/index.js is OK:

21-12-11 20:56:00.508 [ERROR] NOK: No  ./src/test.ts
21-12-11 20:56:00.528 [INFO] OK: end.
end.
Started on http://localhost:3000!

Running: node --loader tsm src/index.ts is OK:

(node:31) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:31) DeprecationWarning: Obsolete loader hook(s) supplied and will be ignored: getFormat, transformSource
21-12-11 20:57:36.931 [ERROR] NOK: No  ./src/test.ts
21-12-11 20:57:36.948 [INFO] OK: end.
end.
Started on http://localhost:3000!

So, questions:

  • maybe need to do some changes in tsconfig.json for better compiling?
  • maybe i do something VERY wrong in scripts code?
  • for prod it will be running in docker with pm2, is it ok?

For fast test run use github.. All this code is just for example.

Thanks!

kRicha
  • 797
  • 9
  • 27
  • Does this answer your question? [ExpressJs is return error \`ERR\_MODULE\_NOT\_FOUND\` if I import the file without \`js\` extension](https://stackoverflow.com/questions/61291633/expressjs-is-return-error-err-module-not-found-if-i-import-the-file-without-j) – MarcRo Dec 11 '21 at 22:22

1 Answers1

0

This is already discussed here

You are using ES Modules in nodejs (specified by the type field in your package.json. This is a new syntax that can cause import issues, e.g. because ESModules require you to to import from files instead of folders (this includes the file-type). Also, you cannot import ESModules from CommonJS modules.

So, what you are doing is the way to go to utilize the ESModule @tinyhttp/app with TypeScript. But since the TypeScript syntax prevents you from specifying the file-type .js on your import (which is required by NodeJS with type module) you have to run node with the flag --es-module-specifier-resolution=node.

So what you are doing is correct.

MarcRo
  • 2,434
  • 1
  • 9
  • 24
  • Hello, i've posted same info in questions. I've repeated question because previous one was asked more than 1.5 year ago.. And i was asking if i'm doing right or something could be corrected. Thanks. – kRicha Dec 12 '21 at 11:41
  • @kRicha I tried to explain why what you are doing is necessary and indeed the right way to run a typescript app. Are you looking for something more? – MarcRo Dec 12 '21 at 13:31
  • ok, as i understand nothing new in this case for last 1.5 year, and i'm moving right. Thanks – kRicha Dec 13 '21 at 10:24
  • nodeJS v19 has removed support for the flag --es-module-specifier-resolution=node – John Tang Boyland Dec 02 '22 at 19:48