← Back to context

Comment by moogly

5 hours ago

I transpile for prod, but use --strip-types when running in dev, and all I had to do was to make a 10-line ESM register hook that rewrites .js to .ts if the .js import fails, and then a one-liner import register trampoline script. Not sure I'd do that in prod, but works fine in dev at least.

This way I could just use node --watch instead of tsx or nodemon.

Mind sharing the implementation? I think it's basically what tsx is doing when used in `node --import tsx`.

  • Sure. No need for --(experimental)-strip-types since I-forget-which-version, but I use Node.js 24.17 here.

      // ---- dev-ts-resolve.js
      export async function resolve(specifier, context, nextResolve) {
        try {
          return await nextResolve(specifier, context);
        } catch (err) {
          const isRelative = specifier.startsWith('./')
            || specifier.startsWith('../')
            || specifier.startsWith('/')
            || specifier.startsWith('file:');
          if (err?.code === 'ERR_MODULE_NOT_FOUND' && isRelative && specifier.endsWith('.js')) {
            return nextResolve(`${specifier.slice(0, -3)}.ts`, context);
          }
      
          throw err;
        }
      }
      // ---- dev-loader.js
      import { register } from 'node:module';
      
      register('./dev-ts-resolve.js', import.meta.url);
      // ----
    

    usage:

      node --import ./dev-loader.js --watch-path=./src