Hi,
In order to create a library of UI components exposed as ESM, I transpile an "index.ts" file that reexport each modules.
Here is the full config:
import { defineConfig, Format } from "tsup";
import path from "path";
const commonConfig = {
clean: true,
//splitting: false,
// Skip until .d.ts.map is also supported https://github.com/egoist/tsup/issues/564
// dts: true,
sourcemap: true,
tsconfig: path.resolve(__dirname, "./tsconfig.build.json"),
outDir: "dist",
format: ["esm" as Format],
};
export default defineConfig([
// actual exposed modules = 1 per component
{
entry: [
// basic reusable components
"./components/core/!(index).ts?(x)",
// sets of components eg "all form components", "all datatable components"
"./components/VulcanComponents/liteVulcanComponents/!(index).ts?(x)",
"./components/form/inputs/!(index).ts?(x)",
],
...commonConfig,
// For debugging, will output ESbuild metafile
// metafile: true,
esbuildOptions(options, context) {
// the directory structure will be the same as the source
options.outbase = "./";
},
},
// index files to allow named imports
// inspired by react-bootstrap structure
{
entry: [
"index.ts",
"./components/core/index.ts",
"./components/VulcanComponents/liteVulcanComponents/index.ts",
"./components/form/inputs/index.ts",
"./components/form/index.ts",
],
...commonConfig,
esbuildOptions(options, context) {
// the directory structure will be the same as the source
options.outbase = "./";
},
// index files must NOT be bundled!
// it acts as a map towards bundled components
// but never rebundles them
bundle: false,
},
Problem: for this to work, "index.ts" must add the ".js" extension in imports:
// index.ts
export { Foo } from "./Foobar.js"
This sounds weird, and it is, but it works both during development (TS basically seems to ignore the extension and correctly load "./Foobar.tsx") and when publishing the package (the .js is mandatory for ESM).
But it doesn't solve the underlying issue, we should not need the ".js" in the first place. To solve this issue in the context of Tsup, I would need to remove the ".js" from my source "index.ts", and add it only during transpilation of this file. Is there a way to achieve that with Tsup?
I think I am going to close for now because the solution proposed at Storybook seems to work, and it seems to be perfectly ok to have explicit ".js" in the ".ts" file.
Hi, In order to create a library of UI components exposed as ESM, I transpile an "index.ts" file that reexport each modules.
Here is the full config:
You can find more explanation on this config here: https://stackoverflow.com/a/73883783/5513532
Problem: for this to work, "index.ts" must add the ".js" extension in imports:
This sounds weird, and it is, but it works both during development (TS basically seems to ignore the extension and correctly load "./Foobar.tsx") and when publishing the package (the .js is mandatory for ESM).
However, this breaks Storybook. This ticket at Storybook explains the same situation: https://github.com/storybookjs/storybook/issues/15962
The current solution seems to be altering Storybook Webpack config like so: https://github.com/storybookjs/storybook/issues/15962#issuecomment-1163459786, using this plugin: https://github.com/softwareventures/resolve-typescript-plugin
But it doesn't solve the underlying issue, we should not need the ".js" in the first place. To solve this issue in the context of Tsup, I would need to remove the ".js" from my source "index.ts", and add it only during transpilation of this file. Is there a way to achieve that with Tsup?
Related issue with Esbuild: https://github.com/evanw/esbuild/issues/622