ts-node icon indicating copy to clipboard operation
ts-node copied to clipboard

Expose SWC plugins configuration

Open dmaretskyi opened this issue 2 years ago • 2 comments

Desired Behavior

SWC added support for WASM-based ast transformers. It would be useful to expose this in the configuration.

The config is JSON-compatible, so it could be read from the "ts-node" section in tsconfig.json:

{
  "compilerOptions": {
    ...
  },
  "ts-node": {
    "swc": true,
    "swcConfig": {
      "jsc": {
        "experimental": {
            "plugins": [
              ["my-plugin", { "pluginOption": true }]
            ]
        }
      }
    }
  }
}

Alternatives you've considered

We're currently using a PNPM patch to hack in this feature: https://github.com/dxos/dxos/pull/2220/files/09762cb5b7f322f8f7d999aae98011d14b27927e#diff-67ce40d8249e12d3c63b1a3aaa38589a39e22b32383a74e696933cf05a63fa8a

dmaretskyi avatar Jan 06 '23 18:01 dmaretskyi

I think this is pretty important functionality to support in order to offer a complete experience with swc. I don't think ts-node can try to figure out what plugins should be provided as that would largely be a userland setup.

For my use case, I'd like to be able to use the transform-imports plugin. I can work around this and use @swc/node directly, but the ability to have a single configuration via ts-node is very convenient.

In reviewing the ts-node codebase, it seems like this would be fairly easy to implement if an additional tsconfig option were to be permitted. The swc transpiler seems to already accept the entire config object from the specific tsconfig. If a new option were to be exposed (e.g. swcPlugins) then it could accept the same format as the jsc.experimental.plugins option from .swcrc. That value could be passed to createSwcOptions and if defined simply merged into the experimental object as a new property plugins which would then allow swc to make use of the defined plugins.

I'd be interested in working on a PR to expose this possibility, but I'd like to make sure that this approach is suitable before doing so.

Summary

  • Allow for new option within the ts-node object in tsconfig named swcPlugins which accepts a plugin configuration from swc
  • Update the swc transpiler to take any value supplied in this property and set it as value of the jsc.experimental.plugins property in the generated swc configuration passed to swc.

shawnmcknight avatar Feb 20 '23 01:02 shawnmcknight

If no options are provided to swc.transformSync call made by ts-node then swc will read the config from .swcrc. I have applied the following patch package to resolve the issue (v10.9.1):

diff --git a/dist/transpilers/swc.js b/dist/transpilers/swc.js
index eeddd4fbb2f18a7e8b20bb628d5f5c806ae20594..6a6fd953355f650f3f681c856fdce3b83e1f6868 100644
--- a/dist/transpilers/swc.js
+++ b/dist/transpilers/swc.js
@@ -32,14 +32,14 @@ function create(createOptions) {
         swcInstance = swc;
     }
     // Prepare SWC options derived from typescript compiler options
-    const { nonTsxOptions, tsxOptions } = createSwcOptions(config.options, nodeModuleEmitKind, swcInstance, swcDepName);
+    // const { nonTsxOptions, tsxOptions } = createSwcOptions(config.options, nodeModuleEmitKind, swcInstance, swcDepName);
     const transpile = (input, transpileOptions) => {
         const { fileName } = transpileOptions;
-        const swcOptions = fileName.endsWith('.tsx') || fileName.endsWith('.jsx')
-            ? tsxOptions
-            : nonTsxOptions;
+        // const swcOptions = fileName.endsWith('.tsx') || fileName.endsWith('.jsx')
+        //     ? tsxOptions
+        //     : nonTsxOptions;
         const { code, map } = swcInstance.transformSync(input, {
-            ...swcOptions,
+            // ...swcOptions,
             filename: fileName,
         });
         return { outputText: code, sourceMapText: map };

valeneiko avatar Mar 14 '23 20:03 valeneiko