typescript icon indicating copy to clipboard operation
typescript copied to clipboard

Cannot load "serverless.ts": Initialization error - caused by incompatible tsconfig `module` setting that breaks serverless.ts compilation

Open justingrant opened this issue 2 years ago • 7 comments

I spent the last hour troubleshooting why serverless.ts was failing to load. The root cause was my tsconfig.json included "module": "esnext" which made the compiled severless.ts unable to be require-d by read.js. After a lot of googling and step-through debugging, I finally ended up at #28, which helped me identify a workaround: create a blank tsconfig file and use it for serverless.ts compilation using the TS_NODE_PROJECT environment variable. Like this:

TS_NODE_PROJECT=serverless-blank-tsconfig.json sls offline start

To avoid others having the same painful experience, here's some suggestions:

  • Could the TS_NODE_PROJECT workaround be documented somewhere other than #28 ?
  • Could read.js override the module setting and any other tsconfig settings required for a successful compilation? AND/OR
  • Could read.js warn the user if their tsconfig has an incompatible setting?

For others who run across this error, here's a honeypot of Google keywords:

% sls offline start
 
 Serverless Error ----------------------------------------
 
  Cannot load "serverless.ts": Initialization error: /Users/justingrant/Documents/hdev/h3/api/serverless.ts:147
  export {};
  ^^^^^^
  
  SyntaxError: Unexpected token 'export'
      at compileFunction (<anonymous>)
      at Object.compileFunction (node:vm:352:18)
      at wrapSafe (node:internal/modules/cjs/loader:1025:15)
      at Module._compile (node:internal/modules/cjs/loader:1059:27)
      at Module.m._compile (/Users/justingrant/Documents/hdev/h3/api/node_modules/ts-node/src/index.ts:1225:23)
      at Module._extensions..js (node:internal/modules/cjs/loader:1124:10)
      at Object.require.extensions.<computed> [as .ts] (/Users/justingrant/Documents/hdev/h3/api/node_modules/ts-node/src/index.ts:1228:12)
      at Module.load (node:internal/modules/cjs/loader:975:32)
      at Function.Module._load (node:internal/modules/cjs/loader:816:12)
      at Module.require (node:internal/modules/cjs/loader:999:19)
      at require (node:internal/modules/cjs/helpers:93:18)
      at /usr/local/lib/node_modules/serverless/lib/configuration/read.js:141:18
      at parseConfigurationFile (/usr/local/lib/node_modules/serverless/lib/configuration/read.js:156:9)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at module.exports (/usr/local/lib/node_modules/serverless/lib/configuration/read.js:183:23)
      at /usr/local/lib/node_modules/serverless/scripts/serverless.js:189:22
      at /usr/local/lib/node_modules/serverless/scripts/serverless.js:187:11
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information ---------------------------
     Operating System:          darwin
     Node Version:              16.5.0
     Framework Version:         2.55.0
     Plugin Version:            5.4.3
     SDK Version:               4.2.6
     Components Version:        3.15.1

justingrant avatar Aug 18 '21 22:08 justingrant

Thanks for raising this issue @justingrant.

Could the TS_NODE_PROJECT workaround be documented somewhere other than Support tsconfig-paths and specify tsconfig*.json #28 ?

I'd be happy to accept a documentation PR outlining this issue. Would you like to make it :) ?

Could read.js override the module setting and any other tsconfig settings required for a successful compilation? AND/OR Could read.js warn the user if their tsconfig has an incompatible setting?

At the moment, no additional language-specific (understand TS-specific) modification will be brought to main framework. However, discussion is open and PR are welcome to remove TS-specific code from main serverless/serverless to dedicated lib. Once this seperation has been made, such warning could be implemented. Please see https://github.com/serverless/serverless/issues/9311 for additional info regarding this migration.

fredericbarthelet avatar Aug 20 '21 07:08 fredericbarthelet

@justingrant @fredericbarthelet I'm facing a similar issue with Serverless Typescript and ESModules. However, the workaround via TS_NODE_PROJECT=tsconfig.serverless.json didn't work for me, because it keeps complaining about the "type": "module" in the package.json:

zirkelc@MBP serverless-esm-test % TS_NODE_PROJECT=tsconfig.serverless.json npx sls package
Environment: darwin, node 16.13.0, framework 3.4.0 (local), plugin 6.1.2, SDK 4.3.1
Docs:        docs.serverless.com
Support:     forum.serverless.com
Bugs:        github.com/serverless/serverless/issues

Error:
Cannot load "serverless.ts": Initialization error: Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/zirkelc/Code/serverless-esm-test/serverless.ts
require() of ES modules is not supported.
require() of /Users/zirkelc/Code/serverless-esm-test/serverless.ts from /Users/zirkelc/Code/serverless-esm-test/node_modules/serverless/lib/configuration/read.js is an ES module file as it is a .ts file whose nearest parent package.json contains "type": "module" which defines all .ts files in that package scope as ES modules.
Instead change the requiring code to use import(), or remove "type": "module" from /Users/zirkelc/Code/serverless-esm-test/package.json.

    at createErrRequireEsm (/Users/zirkelc/Code/serverless-esm-test/node_modules/ts-node/dist-raw/node-cjs-loader-utils.js:97:15)
    at assertScriptCanLoadAsCJSImpl (/Users/zirkelc/Code/serverless-esm-test/node_modules/ts-node/dist-raw/node-cjs-loader-utils.js:30:11)
    at Object.require.extensions.<computed> [as .ts] (/Users/zirkelc/Code/serverless-esm-test/node_modules/ts-node/src/index.ts:1451:5)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at /Users/zirkelc/Code/serverless-esm-test/node_modules/serverless/lib/configuration/read.js:148:18
    at parseConfigurationFile (/Users/zirkelc/Code/serverless-esm-test/node_modules/serverless/lib/configuration/read.js:157:9)
    at async module.exports (/Users/zirkelc/Code/serverless-esm-test/node_modules/serverless/lib/configuration/read.js:184:23)
    at async /Users/zirkelc/Code/serverless-esm-test/node_modules/serverless/scripts/serverless.js:200:22
    at async /Users/zirkelc/Code/serverless-esm-test/node_modules/serverless/scripts/serverless.js:198:11

zirkelc avatar Feb 27 '22 09:02 zirkelc

yarn global add ts-node fixes the problem for me.

link2malkeet avatar Sep 21 '22 23:09 link2malkeet

Or use npm to solve it: npm install ts-node

Genereux-akotenou avatar Sep 27 '22 15:09 Genereux-akotenou

I have a similar issue. I work in monorepo and base tsconfig is NOT where serverless.ts resides.

I did some testing and setting "baseUrl": "." in the tsconfig where serverless.ts resides fixes the issue, but then entire compilation doesn't work obviously :(

It seems that Serverless cannot handle situation where "baseUrl": "." is NOT the same location as serverless.ts. This makes it impossible for now to use it in monorepo. I would love to be able to use it but for now it seems impossible.

Bielik20 avatar Oct 28 '22 10:10 Bielik20

@Bielik20

I was in a similar situation with the monorepo. I got around this by having a serverless.base.ts file in the root directory ( same directory as the tsConfig) and then importing that in the individual monorepo packages. I copied this approach from this nx-serverless template

So in the root directory have a serverless.base.ts file

export const serverlessBaseProvider:  AWS["provider"] = {
  name: "aws",
  runtime: "nodejs16.x",
  ...
};

export const serverlessBasePlugins: string[] = [
  "serverless-esbuild",
  "serverless-offline",
  ...
];

And then in the packages/auth-api/serverless.ts

import {
  serverlessBasePlugins,
  serverlessBaseProvider,
} from "../../serverless.base";
import type { AWS } from "@serverless/typescript";


const serverlessConfiguration: AWS = {
  provider: {
    ...serverlessBaseProvider,
    environment: {...}
    iam: {...}
    ...
  }
}

sukhrajghuman avatar Apr 11 '23 10:04 sukhrajghuman

I had a similar problem, in my case I solved it by setting the moduleTypes property for the ts-node in a separate typescript config file.

my serverless-tsconfig.json:

{
  "extends": "../../tsconfig.json",
  "ts-node": {
    "moduleTypes": {
      "**/*.ts": "cjs"
    }
  }
}

and I'm able to run TS_NODE_PROJECT=serverless-tsconfig.json sls deploy without any problems

wonsu avatar Dec 01 '23 23:12 wonsu