-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
esbuild config file #952
Comments
The API intentionally uses API calls instead of config files. This is documented in the getting started guide: https://esbuild.github.io/getting-started/#build-scripts. So instead of doing what you proposed: $ cat > esbuild.config.js
export default {
entryPoints: ['./src/index.ts'],
bundle: true,
platform: 'node',
outfile: 'build/main.js',
sourcemap: true,
target: 'node12',
external: Object.keys(require('../package.json').dependencies),
}
$ esbuild You should do this instead: $ cat > esbuild.config.js
require('esbuild').build({
entryPoints: ['./src/index.ts'],
bundle: true,
platform: 'node',
outfile: 'build/main.js',
sourcemap: true,
target: 'node12',
external: Object.keys(require('../package.json').dependencies),
})
$ node esbuild.config.js API calls are equivalent in length but more powerful than config files. Some benefits of API calls over config files:
If you must, you can implement "config file support" yourself by making your own shim command that just calls |
Thank you for prompt response! I see the natural need in having the API for more complex tasks, yet access to the API is not necessary in most cases. Here are a couple more points:
import { BuildOptions } from 'esbuild'
export default {
platform: 'node'
} as BuildOptions
function build(args) {
require('esbuild')
.build({
...buildOptions,
watch: args.includes('--watch'),
})
.catch(() => process.exit(1))
}
build(process.argv.slice(2)) > node build.js
> node build.js --watch This piece of code is relatively simple, but I use my own flag, mimicking esbuild argument. Plus, as I use Because the API is the only option, every developer using |
@ebeloded I’ve done something like this previously (ignore the comments): // TODO: Ensure that serverProps and serverPaths cannot be aliased because of
// minification.
export const transpileOnlyConfiguration = (src: string, dst: string): esbuild.BuildOptions => ({
bundle: true,
define: {
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
},
entryPoints: [src],
external: ["react", "react-dom"], // TODO: Use external strategy as defined in esnode?
format: "cjs", // For require
inject: ["packages/retro/react-shim.js"],
loader: {
".js": "jsx",
},
minify: false,
outfile: dst,
// plugins: [...configs.retro.plugins],
})
// TODO: Ensure that serverProps and serverPaths cannot be aliased because of
// minification.
export const bundleConfiguration = (src: string, dst: string): esbuild.BuildOptions => ({
bundle: true,
define: {
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
},
entryPoints: [src],
external: [],
format: "iife",
inject: ["packages/retro/react-shim.js"],
loader: {
".js": "jsx",
},
minify: true,
outfile: dst,
// plugins: [...configs.retro.plugins],
}) The point being that these configuration files could theoretically be published to NPM or even linked (using Evan makes a good point though, which is a) thinking in JS rather than explicitly as data structures provides more flexibility and b) because there are more ways to invoke esbuild than only once, (incremental, watch, etc.), sometimes you really need to have more granular control over esbuild’s lifecycle than just one-shot invoking it. Anyway, do you see any problem with creating configurations in TS and transpiling or in JS and publishing to NPM / linking so you can reuse your configurations, then using the spread operator like you’ve done above so you can decorate your configuration as you need? I also do that when using my example configurations listed above: buildResult = await esbuild.build({
...esbuildHelpers.bundleConfiguration(src, dst),
incremental: true,
minify: false,
watch: {
async onRebuild(error) {
if (error !== null) {
if (!("errors" in error) || !("warnings" in error)) throw error
await buildFailure.send(error)
}
},
},
}) I hope seeing these contextual examples help you. I think the source of the problem is that esbuild is so powerful that it requires a little more handling than other tooling. You could take this as a good or bad thing, but the point is esbuild’s incremental / watch modes make it a little more subtle than most one-shot tooling, which is probably more familiar. |
I'm closing this since the API intentionally uses API calls instead of a config file, as described above. If you still want a config file the workaround above should work (create a wrapper command that reads from the config file). |
note: esbuild doesn't have a config like most tooling. They suggest instead to use their api. See evanw/esbuild#952 (comment)
@ebeloded Hello. May you please explain how do you use .ts file inside .js ? I reference for this answer: your post above My code is: import type { BuildOptions } from "esbuild";
export const devOptions: BuildOptions = {
logLevel: "info",
bundle: true,
platform: "node",
format: "esm",
sourcemap: true,
entryPoints: ["src/index.ts"],
outfile: "dist/index.js",
}; build file: import { build } from "esbuild";
import { devOptions } from "./build/config.dev";
await build({
...devOptions,
}).catch(() => process.exit(1)); but when I try to run I get error: root@ndev:/home/node-ts-template# node esbuild.js
node:internal/errors:496
ErrorCaptureStackTrace(err);
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/node-ts-template/build/config.dev' imported from /home/node-ts-template/esbuild.js
at new NodeError (node:internal/errors:405:5)
at finalizeResolution (node:internal/modules/esm/resolve:327:11)
at moduleResolve (node:internal/modules/esm/resolve:980:10)
at defaultResolve (node:internal/modules/esm/resolve:1193:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:403:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:372:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:249:38)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:39)
at link (node:internal/modules/esm/module_job:75:36) {
url: 'file:///home/node-ts-template/build/config.dev',
code: 'ERR_MODULE_NOT_FOUND'
}
Node.js v18.19.0 I have {
"compilerOptions": {
/* Base Options: */
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"verbatimModuleSyntax": true,
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
/* Strictness */
"strict": true,
"noUncheckedIndexedAccess": true,
"noUnusedParameters": true,
/* If NOT transpiling with TypeScript(tsc): */
"moduleResolution": "Bundler",
"module": "ESNext",
"noEmit": true,
/* If your code doesn't run in the DOM: */
"lib": ["es2022"]
}
} |
Found these today which can be useful alternatives |
It would be very useful to be able to provide
esbuild
with a config, instead of having to provide individual arguments, or use the JavaScript APIHere is a sample esbuild.config.ts
CLI commands
Furthermore, the name
esbuild.config.(json|js|ts)
could be considered as a standard name, and picked up automatically. then the CLI call would be as simple as> esbuild
The text was updated successfully, but these errors were encountered: