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

--packages=external does not work in conjunction with typescript path aliases #2792

Closed
josias-r opened this issue Jan 4, 2023 · 6 comments
Closed

Comments

@josias-r
Copy link

josias-r commented Jan 4, 2023

tsConfig paths:

"paths": {
	"$lib": ["lib"],
	"$lib/*": ["lib/*"],
},

With --packages=external, esbuild results in files using the $lib alias to compile to the following:

import { smth } from "$lib/something";

Instead of bundling $lib/something which is a local file, not a file from node_modules

Here's the full command I'm using:

esbuild index.ts --tsconfig=tsconfig.json --outfile=dist/index.js --bundle --format=esm --platform=node --packages=external
@evanw
Copy link
Owner

evanw commented Jan 4, 2023

That's just what the --packages=external flag does, sorry. The flag means "make any import path external that looks like a package path in the source code."

The --packages=external flag only exists for convenience. You can accomplish what it does with more verbose means such as using --external: or writing a plugin. If you want to do something more custom than what it does, then you'll need to do something more verbose.

@josias-r
Copy link
Author

josias-r commented Jan 4, 2023

That's just what the --packages=external flag does, sorry. The flag means "make any import path external that looks like a package path in the source code."

I get that, but just like mentioned in the docs for esbuild alias:

Also note that marking an import path as external happens after the import path is rewritten by any configured aliases, so the alias feature still has an effect when this setting is used.

Wouldn't it make sense to resolve typescript aliases before marking paths as imports?

Otherwise, is it possible to write a plugin that also runs after the paths are resolved?

@evanw
Copy link
Owner

evanw commented Jan 4, 2023

is it possible to write a plugin that also runs after the paths are resolved?

Yes. The current API for this is not that elegant but you can use the resolve() function in your plugin and then interpret the result. Note that if you are resolving a path that your own plugin will apply to, you can avoid an infinite loop by adding something in pluginData to tell your plugin not to resolve that path again.

@josias-r
Copy link
Author

josias-r commented Jan 5, 2023

Yes. The current API for this is not that elegant but you can use the resolve() function in your plugin
I will try that, thank you.

Still I think this should be up for discussion:

Wouldn't it make sense to resolve typescript aliases before marking paths as imports?

But I'll close the ticket and if it never gains traction I guess it's just my personal need

@josias-r josias-r closed this as completed Jan 5, 2023
@djgrant
Copy link

djgrant commented Jan 26, 2023

My intuition was also that the the externalisation of packages would happen after tsconfig paths/baseUrl are resolved. I agree this would be a good feature; an option (packages: external) that overrides the functionality of a built-in feature (tsconfig resolution) seems likely to violate expectations.

Nonetheless, the advice above on creating a plugin was helpful, and this seems to work adequately:

import { Plugin } from "esbuild";

export function externalModulesPlugin(): Plugin {
  return {
    name: "external-modules",
    setup(build) {
      build.onResolve({ filter: /.*$/ }, async (args) => {
        if (!args.pluginData?.resolved) {
          const resolveResult = await build.resolve(args.path, {
            kind: "import-statement",
            resolveDir: args.resolveDir,
            pluginData: { resolved: true },
          });
          if (resolveResult.path.includes("/node_modules/")) {
            return { path: args.path, external: true, sideEffects: false };
          }
          return resolveResult;
        }
        return undefined;
      });
    },
  };
}

@h-sifat
Copy link

h-sifat commented Mar 9, 2023

@djgrant Thanks a lot for the solution 💝. I guess this issue should be addressed.

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