#Building a TypeScript library with self-referencing exports/imports

1 messages · Page 1 of 1 (latest)

dire warren
#

I'm trying to set up a library build where there are several exports conditions defined in package.json to enable self-referencing imports and exports. This seems to be supported by Node and TypeScript (also VS Code resolves the imports fine), but fails in vite build with "Rollup failed to resolve import ... " error.

I pushed a small experiment here: https://github.com/mihkeleidast/rollup-build-experiment (don't look at the repo name, I'm experimenting with multiple build tools there).

Is this simply not supported as I expected it to be, or do I need to configure something?

GitHub

Contribute to mihkeleidast/rollup-build-experiment development by creating an account on GitHub.

dire warren
#

One workaround I found was that I can define a "source" condition to package exports and direct vite to use that. I guess this works, but it is a bit unfortunate to have incorrect exports conditions defined (as consumers of the library do not have access to source...)

last locust
#

I haven't yet tried this, but I have tried Vite's Library mode enough that I know that I prefer a tool like tsup if I can help it. There's an esbuild-sass-plugin for your .scss that might work… but ultimately tsup would be better for Node.js libraries, yours is a browser one.

Another possibility could be using aliasing. You could import package.json and use its exports field to construct the aliases, but instead of ./dist/ you need to start with /src/, without the dot, that's the absolute path in Vite.

If that is good enough for you.

dire warren
#

Computing aliases may be a good option yes, thanks!

#

I may try tsup as well, but given that I also have Sass files I need to compile, not sure how well the experimental css support in esbuild works. With vite/rollup, it should work great I think, given it should work for real apps/websites as well.

Also since the real repo also has storybook, I'm looking into moving that to use vite (instead of webpack), so using the same tool for both would be benefitial...

last locust
#

Yeah, definitely in your situation I would stick to Vite as well. tsup is better if you're building a Node.js library, Vite's Library mode is geared exactly towards browser libraries.

I hope that aliases work for you 🤞 If they don't for some reason we can build you a small plugin that correctly resolves the import, as a last resort.

dire warren
#

Do you think it's something to file a feature request for though? I'd sort of expect it to work out of the box, since TS itself does support this.

#

Aliases worked like a charm btw, now onto next issues (extracting assets in lib mode for example)

dire warren
#

btw I may still need to go with my initial idea of using a "source" exports condition. I need this to work across vite, webpack, jest, eslint and TS (intellisense in editor). All of them support defining conditions, while defining aliases to all of them seems complicated...

#

I was pretty stoked initially to find that TS supports this automatic resolution in core, but it seems the rest of the ecosystem has not caught up yet.

last locust
#

It might be worth filing a feature request over imports, yes, especially since otherwise works. Sounds like a good argument for support.

#

As for the "source" condition, I'm not sure what you mean by that, I haven't understood that part. Could you elaborate?

dire warren
#

So for example, this exports configuration works in TS out of the box:

"exports": {
  "./button": {
    "types": "./dist/components/button/index.d.ts",
    "import": "./dist/components/button/index.mjs"
  }
}

For other tools that do not support the TS module resolution algorithm fully, I need to add a "source" condition:

"exports": {
  "./button": {
    "source": "./src/components/button/index.ts",
    "types": "./dist/components/button/index.d.ts",
    "import": "./dist/components/button/index.mjs"
  }
}

and then point resolvers to look at the source condition, e.g. with vite: https://vite.dev/config/shared-options#resolve-conditions

#

But I also found that I can get the same effect by defining the source rules in tsconfig paths - most tooling also has support for those via plugins or the like. That also enables me to define some local-only entrypoints, e.g. if we want to have some shared import paths for test files, without having to define them in exports at all.

last locust
#

Ah, I see, I didn't know about source before, I don't know what I would even use it for, interesting… Anyway, seeing that you have a much better grasp of this than I do, I hope you managed to land on a solution that you like 😉

dire warren
#

The condition names can be essentially whatever, it's not a predefined list

last locust
#

But there are conditions naturally recognized by tools like Node.js etc. (import, require), and by TypeScript (types), so I thought that source was one of the "known" conditions.