swc-project / swc-node

Faster ts-node without typecheck
MIT License
1.78k stars 75 forks source link

Doesn't Work with Ava Out of the Box #672

Open shellscape opened 2 years ago

shellscape commented 2 years ago

Running Node v16@latest. @swc-node/register doesn't work with Ava out of the box. The instructions in the README aren't comprehensive enough to use straight away.

config:

  "ava": {
    "extensions": ["ts"],
    "require": ["@swc-node/register"],
    "files": ["!**/fixtures/**", "!**/helpers/**", "!**/recipes/**", "!**/types.ts"]
  }

test:

import test from 'ava';

import * as tools from '../src';

test('exports', (t) => {
  t.snapshot(tools);
});

result:

  Uncaught exception in test/test.ts

  SyntaxError: Cannot use import statement outside a module

  › Module._compile (/Users/code/packages/node_modules/.pnpm/pirates@4.0.5/node_modules/pirates/lib/index.js:136:24)
  › newLoader (/Users/code/packages/node_modules/.pnpm/pirates@4.0.5/node_modules/pirates/lib/index.js:141:7)

  ✖ test/test.ts exited with a non-zero exit code: 1

Now, I understand that error message has to do with ESM module support. OK. I'll tell it to use a tsconfig that should work around that:

tsconfig.base.json:

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "declaration": true,
    "emitDecoratorMetadata": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "lib": ["ES2018", "ES2020", "esnext.asynciterable", "dom"],
    "module": "commonjs",
    "moduleResolution": "node",
    "noEmitOnError": false,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "pretty": true,
    "removeComments": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "sourceMap": true,
    "strict": true,
    "target": "es2020",
    "useUnknownInCatchVariables": false
  },
  "exclude": ["dist", "node_modules", "test/types"]
}

tsconfig.json (used by test):

{
  "compilerOptions": {
    "outDir": "dist"
  },
  "extends": "../../shared/tsconfig.base.json",
  "include": ["src", "bin/*", "test"]
}

updated config:

  "ava": {
    "extensions": ["ts"],
    "require": ["@swc-node/register"],
    "files": ["!**/fixtures/**", "!**/helpers/**", "!**/recipes/**", "!**/types.ts"],
    "environmentVariables": {
      "SWC_NODE_PROJECT": "./tsconfig.json"
    }
  }

Same result. If I swap ts-node/register back in, everything works again. There's either a bit of information left out, or this straight up does not work with Ava. I'd be baffled if it was the latter because I can see tests working here in this repo and they use ava.

octet-stream commented 1 year ago

Are you trying to setup this for ESM or CJS?

If for ESM, then AVA needs different setup. Here's my config:

export default {
  environmentVariables: {
    SWC_NODE_PROJECT: "./tsconfig.ava.json", // This one is not necessary, just my default tsconfig.json ignores tests, so swc-node will not compile them. This file just adds tests to `include` section of the config.
    SWCRC: "true"
  },
  extensions: {
    ts: "module"
  },
  nodeArguments: [
    "--no-warnings",
    "--loader=@swc-node/register/esm" // This is the one loader you need instead of swc-node/register
  ],
  files: [
    "src/**/*.test.ts"
  ]
}

Worth to mention that this will not work on Node v20, because nodeArguments are getting ignored for some reason. To fix this, you'll need to move them to package.json

  "scripts": {
    "test": "cross-env NODE_OPTIONS=\"--no-warnings --loader=@swc-node/register/esm\" ava --fail-fast"
  },

Also, I'm not sure if .swcrc would be necessary, probably not, but I have one in my project:

{
  "$schema": "https://json.schemastore.org/swcrc",
  "jsc": {
    "parser": {
      "syntax": "typescript"
    },
    "target": "es2020"
  }
}

Hope this will help.