Open macrozone opened 6 months ago
I've run into this a few times as well and finally made a plugin for it, here's the link if helpful.
Unfortunately I don't think there's a way to know the full list of dependencies that were externalized (for ex. by other plugins), so it only uses whatever is passed to esbuild's build
function external
property manually.
Usually for Node.js users the devDependencies
are ok to be bundled in and dependencies
peerDependencies
are externalized because they will be installed by npm when used in production (i.e. being used as a dependency of other project). Therefore, it is a common practice to only externalize these packages:
external: Object.keys({
...pkg.dependencies,
...pkg.peerDependencies
})
Sometimes this external list works the same as --packages=external. This needs the author to check out.
This way, you can just use the same package.json as you write. That's why tsup does this by default.
On the other hand, you can also run a simple scanner on the final build to collect external deps like using esm-module-lexer or with a custom esbuild plugin that gather args.path with args.kind != entry-point in the onResolve() callback.
@hyrious The concern with using the package.json
as is, is that it means potentially including a lot of code that'll never get used. In the case of something like a serverless bundle, the size starts to matter eventually. The optimal goal becomes targeting ESM, bundling as much as possible, installing the bare minimum external modules needed only for those that would otherwise break the bundle, and then code-splitting on intentional async dynamic imports.
This was my use-case at least, the final package size is a lot smaller than it would be compared to externalizing all production dependencies, but sentry's profiling integration and a few other indirect dependencies don't behave properly if not in their original directory structure.
@JQuezada0 What you said doesn't conflict with my comment. If including some dependencies into the bundle is by purpose, the common practice is just move those dependencies to devDependencies
. Then on the server it runs npm i --omit=dev
to not install dev dependencies (which are already in the bundle).
@hyrious ohhh sorry I misunderstood, good idea! Definitely simpler
Problem 1:
i am using esbuild with externalized packages:
externalizing packages is needed because some modules may rely on a certain folder structure and may not work correctly when bundled.
Local dependencies in a monorepo get bundled with this, which is nice.
However you still need to install certain packages, but if you use the original package.json, you may have local dependencies there that can't be installed after bundling with esbuild.
Problem 2
When you just externalize some packages and bundle others, you still have a package.json that contains all dependencies.
Solution: