12

I am trying to use esbuild to bundle and minify my files in an npm project. It is minimizing every file that I pass in, but it is not bundling. It gives me the error that I must use 'outdir' when there are multiple files. However, this gives me back all of those files, minimized, in a folder. This is not the behavior that I want and is not bundling. I just want it to take all of those files and merge them into one.

let {build} = require("esbuild");
let files = ["file1.js", "file2.js"];

build({
    entryPoints: files,
    outdir: "./views/dashboardPage/bundle",
    minify: true,
    bundle: true
}).catch(() => process.exit(1));

I have bundle set to true, but it still demands that I use outdir and it just returns those files to me, minimized. They have basically 0 documentation on this and every post online about it has just copy/pasted the README from the GitHub. How can I make it bundle?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Lee Morgan
  • 550
  • 1
  • 6
  • 26

4 Answers4

10

Each entry point file will become a separate bundle. Each bundle includes the entry point file and all files it imports. Passing two entry points will create two separate bundles. The bundling process is not the same thing as file concatenation.

If you want all of the files in a single bundle, you can reference them all from a single file and use that file as the entry point:

import "./file1.js"
import "./file2.js"

Doing that with esbuild could look something like this:

let {build} = require("esbuild");
let files = ["./file1.js", "./file2.js"];

build({
    stdin: { contents: files.map(f => `import "${f}"`).join('\n') },
    outfile: "./views/dashboardPage/bundle.js",
    minify: true,
    bundle: true
}).catch(() => process.exit(1));
constexpr
  • 1,021
  • 10
  • 7
  • 1
    How do you do this from the command line without creating a temporary file just so that you can feed it to ebuild.exe – user3700562 Jul 11 '21 at 16:42
6

Based on Alexander response I finally came to this solution to pack a whole folder into a single file:

const esbuild = require('esbuild');
const glob = require('glob');

esbuild
    .build({
        stdin: { contents: '' },
        inject: glob.sync('src/js/**/*.js'),
        bundle: true,
        sourcemap: true,
        minify: true,
        outfile: 'web/js/bundle.js',
    })
    .then(() => console.log("⚡ Javascript build complete! ⚡"))
    .catch(() => process.exit(1))
txigreman
  • 339
  • 3
  • 6
  • Doesn't this one have side effects, as you might try to load some dependencies ahead of their time? – HellBaby Feb 14 '23 at 06:30
5

You can use inject option (https://esbuild.github.io/api/#inject), for example,

const options = {
  entryPoints: ['index.js'],
  inject: ['file1.js', ..., 'fileN.js'],
  bundle: true,
  minify: true,
  sourcemap: true,
  outdir: path,
};
esbuild.buildSync(options);
Alexander
  • 51
  • 1
  • 2
0

The problem is because the files are not being found.


Install this package to grab all files from the folder:

npm i files-folder

Your esbuild.config.js file will look like this one:

import { filesFromFolder } from 'files-folder'
import esbuild from 'esbuild'

esbuild
    .build({
        entryPoints: filesFromFolder('src'),
        bundle: true,
        minify: true,
        sourcemap: true,
        target: 'node16',
        define: { 'require.resolve': undefined },
        platform: 'node',
        allowOverwrite: true,
        outdir: 'views/dashboardPage/bundle'
    })
    .catch((error) => {
        process.exit(1)
    })
Marcos Viana
  • 91
  • 1
  • 4
  • 1
    Please don't post code-only answers but add a little textual explanation about how and why your approach works and what makes it different from the other answers given. You can find out more at our ["How to write a good answer"](https://stackoverflow.com/help/how-to-answer) page. – ahuemmer Jan 03 '23 at 09:06