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

how to keep original directory structure? #728

Open
daolou opened this issue Sep 23, 2022 · 15 comments
Open

how to keep original directory structure? #728

daolou opened this issue Sep 23, 2022 · 15 comments

Comments

@daolou
Copy link

daolou commented Sep 23, 2022

src
  - tool1
    - tool1.ts
  - tool2
    - tool2.ts
  - tool3
    - tool3.ts
  - index.ts

Such as above, src/index.ts is exports all, then use tsup src/index.ts --format esm,cjs,iife build,it will output:

dist
  - index.mjs
  - index.global.js
  - index.js

it not I want.

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@oliveiraantoniocc
Copy link

Maybe you meant about the legacy output modifier. If not, what would be the expected output?
image

@daolou
Copy link
Author

daolou commented Sep 26, 2022

I want is code split,like this:

dist
  - tool1
    - tool1.js
    - tool1.mjs
  - tool2
    - tool2.js
    - tool2.mjs
  - tool3
    - tool3.js
    - tool3.mjs
  - index.js
  - index.mjs

@jimmy-guzman
Copy link

An approach I take to achieve something similar is to set up entry with a glob that would output an array of files, for example

import glob from 'tiny-glob'
import { defineConfig } from 'tsup'

export default defineConfig(async () => {
  return [
    {
      entry: await glob('./src/**/!(*.d|*.spec).ts'),

@eric-burel
Copy link
Contributor

eric-burel commented Sep 28, 2022

Maybe to elaborate, this seems appropriate when building libraries of React component or libraries of independant utilities (lodash style), see: https://stackoverflow.com/questions/72149666/a-fool-proof-tsup-config-for-a-react-component-library
In this case you want to generate one .js per component.

We seem to need:

  • globs to bundle all components, with code-splitting to favour code reuse accross components
  • for the "index.ts" that imports them and serves as the package entrypoint, we'd want to avoid bundling. This index should really be a map towards the bundled, independant components. Probably calling just Esbuild without bundle option may be easier. You can use bundle: false to disable bundling and keep only the transpiling step.

I still struggle to keep the directory structure. If entry is ["index.ts", "./smth/nested.ts"], the smth folder will be created. But this is probably not what you want since you need no bundling for index, and bundling for "nested". If entry is ["./smth/nested.ts"] it won't respect the directory structure.

Edit: here is the final result. Components are bundled with code splitting (in case 2 components use the same internal sub component for instance), index files are not bundled, only transpiled, and uses an explicit ".js" which is necessary for ESM modules to work.
I am surprised that the ".js" extension is accepted by TypeScript, but it works.
Named import works as expected, and tree shaking is now possible because each component leaves in an isolated ES module.
This is not perfect but a good first step.

@daolou
Copy link
Author

daolou commented Sep 28, 2022

An approach I take to achieve something similar is to set up entry with a glob that would output an array of files, for example

import glob from 'tiny-glob'
import { defineConfig } from 'tsup'

export default defineConfig(async () => {
  return [
    {
      entry: await glob('./src/**/!(*.d|*.spec).ts'),

It's entry seem support glob:

export default defineConfig([
  {
    entry: ['src/**/*.ts'],
    splitting: true,
    target: 'es5',
    format: 'cjs',
    dts: true,
    treeshake: true,
    bundle: false,
  }
]);

@eric-burel
Copy link
Contributor

Just to answer this precise question:

outDir: "./dist",
 esbuildOptions(options, context) {
    // the directory structure will be the same as the source
    options.outbase = "./";
    },
  },

The "outbase" option of esbuild will force the bundled files to have the same directory structure as the source.

I've updated my Stack Overflow answer here: https://stackoverflow.com/a/73883783/5513532

At this point I am stuck with one last thing, I need to add ".js" to the imports of "index.ts" and can't find a way to do that during bundling. So I add the ".js" manually in the "index.ts" source (sounds weird, but it works), except that now it breaks storybook.

@daolou
Copy link
Author

daolou commented Sep 29, 2022

Just to answer this precise question:

outDir: "./dist",
 esbuildOptions(options, context) {
    // the directory structure will be the same as the source
    options.outbase = "./";
    },
  },

The "outbase" option of esbuild will force the bundled files to have the same directory structure as the source.

I've updated my Stack Overflow answer here: https://stackoverflow.com/a/73883783/5513532

At this point I am stuck with one last thing, I need to add ".js" to the imports of "index.ts" and can't find a way to do that during bundling. So I add the ".js" manually in the "index.ts" source (sounds weird, but it works), except that now it breaks storybook.

use bundle: false and entry: ['./src/**/*.ts'] also work, but I have another problem: compilerOptions.paths not resolved
image

@daolou
Copy link
Author

daolou commented Sep 29, 2022

BTW

if use options.outbase = "./";, it maybe affect esbuild-plugins that use build.onResolve;

@aleclarson
Copy link

One drawback to using globs in entry is that new files aren't picked up, so you have to restart tsup whenever adding a new file that matches one of the globs in entry.

#748

@cenk1cenk2
Copy link

cenk1cenk2 commented Nov 23, 2022

Just to answer this precise question:

outDir: "./dist",
 esbuildOptions(options, context) {
    // the directory structure will be the same as the source
    options.outbase = "./";
    },
  },

The "outbase" option of esbuild will force the bundled files to have the same directory structure as the source.
I've updated my Stack Overflow answer here: https://stackoverflow.com/a/73883783/5513532
At this point I am stuck with one last thing, I need to add ".js" to the imports of "index.ts" and can't find a way to do that during bundling. So I add the ".js" manually in the "index.ts" source (sounds weird, but it works), except that now it breaks storybook.

use bundle: false and entry: ['./src/**/*.ts'] also work, but I have another problem: compilerOptions.paths not resolved image

Have you got a change to find a solution to compilerOptions.paths not being resolved, I have tried a couple of esbuild plugins to temporary fix but to no avail. For DTS part of the application it seems to resolve quite fine, but JavaScript part as you indicate is not resolved.

I guess this behavior is caused by esbuild not following any paths in the tsconfig when the bundling options is off.

@MrKou47
Copy link

MrKou47 commented Dec 9, 2022

I scoured the documentation and couldn't find the bundle: false option. In my case, I just want to replace tsc with tsup cause tsc is too slow. Maybe we should add a section about bundle option to documentation?

@cenk1cenk2
Copy link

cenk1cenk2 commented Dec 9, 2022

For anybody stumbling accross the issue I ended up combining what I usually use for tsc.

Setting bundle to false as expected stops following paths on esbuild side of things. I suppose this would not be a concern of tsup. From the esbuild side I could not make it work using alias plugins and injecting tsconfig in.

So just used tsconfig-replace-paths cli to swap paths on onsuccess step. It is still fast and stable enough for me so that I prefer not to mark it as being a trade off.

Something like as below:

https://github.com/tailoredmedia/backend-nx-skeleton/blob/master/packages/nx-nest/tsup.config.ts

@LennardWesterveld
Copy link

Are you guys also having the issue that it gives the error on the first line No input files, try "tsup <your-file>" instead? Getting stuck on this piece of code: https://github.com/egoist/tsup/blob/main/src/index.ts#L77-L79 while I just have the config

  { 
       bundle: false,
       entry: ['src/**/*.{ts,tsx}', '!src/**/*.stories.{ts,tsx}', '!src/**/*.d.{ts,tsx}'],
   }

@mxvsh
Copy link

mxvsh commented Mar 24, 2023

tried all, none of them worked 😢

@eddienubes
Copy link

I was trying to build a node library to use in both CJS and ESM environments and figured it out with

tsup ./src --format cjs,esm --no-splitting --dts --tsconfig tsconfig.build.json

to:

  • Preserve folder structure (./src vs ./src/index.ts)
  • Build to multiple formats (cjs, esm)
  • Disable esbuild's code splitting (--no-splitting)
  • Generate .d.ts files for library consumers
  • Provide custom tsconfig file (--tsconfig)

Hope it helps someone :)

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

10 participants