Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Netlify and Vercel lambda functions expect CJS, not ESM #400

Closed
GrygrFlzr opened this issue Feb 21, 2021 · 9 comments
Closed

Netlify and Vercel lambda functions expect CJS, not ESM #400

GrygrFlzr opened this issue Feb 21, 2021 · 9 comments

Comments

@GrygrFlzr
Copy link
Member

Describe the bug
For both Netlify and Vercel, the functions are expected to be in CJS format.

Logs

Netlify
{
    "errorType": "Runtime.UserCodeSyntaxError",
    "errorMessage": "SyntaxError: Cannot use import statement outside a module",
    "trace": [
        "Runtime.UserCodeSyntaxError: SyntaxError: Cannot use import statement outside a module",
        "    at _loadUserApp (/var/runtime/UserFunction.js:98:13)",
        "    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
        "    at Object.<anonymous> (/var/runtime/index.js:43:30)",
        "    at Module._compile (internal/modules/cjs/loader.js:999:30)",
        "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)",
        "    at Module.load (internal/modules/cjs/loader.js:863:32)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:708:14)",
        "    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)",
        "    at internal/main/run_main_module.js:17:47"
    ]
}
Vercel
2021-02-21T09:39:07.112Z	undefined	ERROR	/var/task/index.js:1
import { parse, URLSearchParams } from 'url';
^^^^^^
SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at /var/task/___now_launcher.js:26:28
    at Object.<anonymous> (/var/task/___now_launcher.js:74:7)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
RequestId: 4f971773-0d4d-4914-90d4-eb2f6706c2c8 Error: Runtime exited with error: exit status 1
Runtime.ExitError

To Reproduce

  1. Use any of the example apps in kit/examples
  2. Build and then adapt with the Netlify adapter
  3. Initialize the project on Netlify
  4. Build will succeed, but all pages will error as the function cannot run

Repeat above with Vercel.

Expected behavior
No import issues.

Information about your SvelteKit Installation:

  System:
    OS: Windows 10 10.0.19042
    CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
    Memory: 8.05 GB / 31.95 GB
  Binaries:
    Node: 14.15.3 - C:\Program Files\nodejs\node.EXE
    npm: 7.5.2 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 88.0.4324.182
    Edge: Spartan (44.19041.423.0), Chromium (88.0.705.63)
    Internet Explorer: 11.0.19041.1
  npmPackages:
    @sveltejs/adapter-netlify: 1.0.0-next.1
    @sveltejs/adapter-vercel: 1.0.0-next.2
    @sveltejs/kit: 1.0.0-next.34
    @sveltejs/snowpack-config: next => 1.0.0-next.3
    svelte: ^3.29.0 => 3.32.3

Severity
This makes the Netlify and Vercel adapters unusable. The user might be able to postprocess the adapter results to CJS themselves, but practically speaking it's a blocker for those platforms.

Additional context
In an ideal world, the lambdas could run ESM, but it seems the adapter output might need to be translated to CJS instead.

This would likely affect all variants of AWS lambdas. AWS recently added Node 14 support but it does not mention supporting ESM imports, so I'm not sure of their stance on it. There's also an open Netlify forum post about it.

#349 is likely related, as this impedes the goal to have everything in ESM.

@GrygrFlzr
Copy link
Member Author

I contacted Vercel support and they said that they do support ESM functions, which Next.js supposedly does out of the box. Will follow up when I get more details.

@antony
Copy link
Member

antony commented Feb 25, 2021

@leo can we get @GrygrFlzr added to the Vercel Slack? it might be easier than going via the support route.

@benmccann
Copy link
Member

It seems that AWS Lambda only supports CJS (sdk issue) and so that's the only option for Netlify which relies on Lambda. I guess the only solution is to have at least that adapter transpile with Rollup

@GrygrFlzr
Copy link
Member Author

GrygrFlzr commented Mar 11, 2021

Correspondence with Vercel has ground to a halt for now.

I looked into this further - I can make Vercel import .mjs files using await import from index.js (which is treated as a CJS file) and it will properly resolve the rest with ESM:

module.exports = async (res, req) => {
  const { default: app } = await import("./index.mjs");
  await app(res, req);
};

But then #324 pops up, despite the fact that @sveltejs/kit is set as a prod dependency:

Vercel logs
{
  "errorType": "Runtime.UnhandledPromiseRejection",
  "errorMessage": "Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/kit' imported from /var/task/server/app.mjs",
  "reason": {
    "errorType": "Error",
    "errorMessage": "Cannot find package '@sveltejs/kit' imported from /var/task/server/app.mjs",
    "code": "ERR_MODULE_NOT_FOUND",
    "stack": [
      "Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/kit' imported from /var/task/server/app.mjs",
      "    at packageResolve (internal/modules/esm/resolve.js:655:9)",
      "    at moduleResolve (internal/modules/esm/resolve.js:696:18)",
      "    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:810:11)",
      "    at Loader.resolve (internal/modules/esm/loader.js:86:40)",
      "    at Loader.getModuleJob (internal/modules/esm/loader.js:230:28)",
      "    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:56:40)",
      "    at link (internal/modules/esm/module_job.js:55:36)"
    ]
  },
  "promise": {},
  "stack": [
    "Runtime.UnhandledPromiseRejection: Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/kit' imported from /var/task/server/app.mjs",
    "    at process.<anonymous> (/var/runtime/index.js:35:15)",
    "    at process.emit (events.js:327:22)",
    "    at processPromiseRejections (internal/process/promises.js:245:33)",
    "    at processTicksAndRejections (internal/process/task_queues.js:94:32)"
  ]
}

To summarize:

  • Vercel functions do support ESM - but only if you have the file use the .mjs extension.
  • There appears to be no way to specify a package.json for the function.
  • The entry point must use .js if you use .vercel_build_output, so there needs to be at least the CJS entry point if we want to continue using that approach.
  • Vercel functions have no access to any package.json dependencies (either prod or dev), so the adapt process needs to bundle @sveltejs/kit.

@GrygrFlzr
Copy link
Member Author

Someone else contacted the Vercel slack and apparently:

Currently ESM is compiled to CJS (import changed to require) but we plan to add support for ESM proper once Node.js 10 goes EOL

Which happens 30th April (end of next month), so that's potentially something to look forward to. We'd probably still have to bundle @sveltejs/kit though.

@GrygrFlzr
Copy link
Member Author

GrygrFlzr commented Mar 11, 2021

After the (partial) success with getting .mjs files to at least execute on Vercel, I thought I'd at least give it a try on Netlify. Lo and behold, they support ESM in .mjs files, it's just being blocked by the lack of access to @sveltejs/kit in a lambda environment.

module.exports = {
  async handler(event) {
    const { handler } = await import("./index.mjs");
    return await handler(event);
  },
};
{
  "errorType": "Error",
  "errorMessage": "Cannot find package '@sveltejs/kit' imported from /var/task/src/app.mjs",
  "trace": [
    "Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sveltejs/kit' imported from /var/task/src/app.mjs",
    "    at packageResolve (internal/modules/esm/resolve.js:650:9)",
    "    at moduleResolve (internal/modules/esm/resolve.js:691:18)",
    "    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:784:11)",
    "    at Loader.resolve (internal/modules/esm/loader.js:100:40)",
    "    at Loader.getModuleJob (internal/modules/esm/loader.js:246:28)",
    "    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:47:40)",
    "    at link (internal/modules/esm/module_job.js:46:36)"
  ]
}

It looks like we can skip transpiling to CJS as long as we have a single CJS file acting as the entry point! That should make it easy to migrate to 100% ESM in the future should it be supported by the serverless services.

@GrygrFlzr
Copy link
Member Author

This issue can be closed as soon as #483, #485, and #486 all get merged.

@GrygrFlzr
Copy link
Member Author

Closing this as the relevant PRs have been merged. Further discussion should go to #503 instead.

@spences10
Copy link
Member

This issue can be closed as soon as #483, #485, and #486 all get merged.

Do you have a code example for the Vercel example you have here @GrygrFlzr, please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants