ezolenko / rollup-plugin-typescript2

Rollup plugin for typescript with compiler errors.
MIT License
819 stars 71 forks source link

Caching with id may cause problems for other plugins #441

Closed reothues closed 1 year ago

reothues commented 1 year ago

Troubleshooting

The rollup-plugin has the ability to resolve an id into another:

: https://rollupjs.org/plugin-development/#resolveid thus import from '/pathto/something.ts' may have different outputs.

like the example shown here, if you have some proxies inside resolveId, it's overwritten by rollup-plugin-typescript2 since it caches with ids without calling this.resolve first.

Example: resolve SWITCH_ID to ENV_ID

    resolveId(source, importer, options): null | ResolveIdResult | Promise<ResolveIdResult> {
      console.log('resolving'.blue, source);

      return this.resolve(source, importer, {
        skipSelf: true,
        ...options,
      }).then(originalResolve => {
        // this is importing ./const
        console.log('imported by'.gray, importer);
        if (originalResolve.id === SWITCH_ID) {
          console.log('importing const/index'.red);
          // not const/index.ts (rewritten) imported it, rewrite it to const/ttp.ts
          if (importer !== ENV_ID) {
            console.log(source, 'replaced to'.red, ENV_ID);
            return { id: ENV_ID };
          }
          console.log(source, 'resolved unchanged'.green, originalResolve.id);
        }
        return originalResolve;
      });
    },

transform ENV_ID and import from SWITCH_ID (the original one)

    transform(code, id): string | Promise<string | Partial<ModuleInfo>> {
      console.log('transforming'.blue, id);
      if (id === ENV_ID) {
        const ast = this.parse(code);
        const envExports = searchExport(ast as Node as Program, ider => ider.name);
        console.log('need to search default values first'.gray);
        return this.load({ id: SWITCH_ID }).then(defaultModuleInfo => {
          console.log('default loaded'.gray);
          const defaultExports = searchExport(defaultModuleInfo.ast as Node as Program, ider => ider.name);
          const uniqExports = defaultExports.filter(name => envExports.indexOf(name) === -1);
          const addedCodeExports = `export { ${uniqExports.join('')} } from '${SWITCH_ID}';`;
          console.log('adding import to ttp.ts'.red, addedCodeExports);
          const codeRet = `${addedCodeExports}\n${code}`;
          const astRet = this.parse(codeRet);
          return {
            code: codeRet,
            ast: astRet,
          };
        });
      } else {
        if (id === SWITCH_ID) {
          console.log(SWITCH_ID.bgBlue, 'is messing up the caching of other plugins'.bgRed);
        }
        return code;
      }
    },
ezolenko commented 1 year ago

import is being used in two contexts -- by rollup (after it gets transpiled into resolve call) -- this is run through the plugin chain. And also by typescript compiler when it parses the file that does the importing. This second run doesn't go through rollup plugin chain, so I don't think we can be compatible with plugins that rewrite imports...

Or did I get the problem wrong?

agilgur5 commented 1 year ago

it's overwritten by rollup-plugin-typescript2 since it caches with ids without calling this.resolve first.

I'm not sure what you mean by "caches with ids" since rpt2's resolveId implementation does not cache. It can also be filtered on as well.

If you mean Rollup's watch mode cache (the issue does not mention that), then your plugin may want to implement shouldTransformCachedModule. This plugin should implement that function as well, but it is a newer Rollup feature and so is still TODO.

      return this.resolve(source, importer, {
        skipSelf: true,
        ...options,
      }).then(originalResolve

Looking at this code, you're explicitly saying to run other plugins first with this.resolve, so you would expect that something may have gotten resolved by other plugins. If this plugin didn't do that and ran first in the chain, then it could resolve based on its own resolution first. Plugins are expected to resolve sequentially.

And also by typescript compiler when it parses the file that does the importing. This second run doesn't go through rollup plugin chain

As ezolenko mentions, given that this is TypeScript, the TypeScript compiler must also be able to resolve your imports. And really that's all that this plugin's resolveId implementation does.

I'm not sure what your proposed solution is here and that would need some more details as well

agilgur5 commented 1 year ago

Closing this as stale with no response from OP in a few months