{"id":19472194,"url":"https://github.com/nvms/esbuild-wrapper","last_synced_at":"2025-11-19T02:03:41.346Z","repository":{"id":54242591,"uuid":"506095266","full_name":"nvms/esbuild-wrapper","owner":"nvms","description":null,"archived":false,"fork":false,"pushed_at":"2024-03-05T00:58:43.000Z","size":168,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-25T15:28:28.618Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nvms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-06-22T04:20:41.000Z","updated_at":"2022-06-22T04:21:11.000Z","dependencies_parsed_at":"2024-03-05T01:58:01.636Z","dependency_job_id":null,"html_url":"https://github.com/nvms/esbuild-wrapper","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/nvms/esbuild-wrapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvms%2Fesbuild-wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvms%2Fesbuild-wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvms%2Fesbuild-wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvms%2Fesbuild-wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nvms","download_url":"https://codeload.github.com/nvms/esbuild-wrapper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nvms%2Fesbuild-wrapper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285170109,"owners_count":27126456,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-19T02:00:05.673Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-10T19:13:22.287Z","updated_at":"2025-11-19T02:03:41.328Z","avatar_url":"https://github.com/nvms.png","language":"JavaScript","readme":"A mostly unopinionated configuration wrapper for esbuild's build API, and a really fast way to get started with a new project.\n\nThe quickest way to get started:\n\n```bash\ncd my-new-project\nnpx esbuild-wrapper generate\n```\n\nThis will ask you a few questions before scaffolding out a project in the current working directory. When it's done, take a look at the generated `package.json` and `esbw.config.js` to see how things fit together. Run it again with different prompt answers to get a feel for what it's doing.\n\nWhat you get:\n\n* Four operating modes: build, run, watch and serve.\n* A simple way to define multiple output targets with an intuitive configuration inheritance hierarchy for each of these run modes.\n* Async `beforeAll` and `afterAll` hooks for all operating modes (build, watch, run and serve) which are particularly useful for doing things like CSS preprocessing and copying static assets. Use `esbuild-wrapper generate` and create a browser project and select TailwindCSS when prompted for an example of exactly this.\n\nCreate an `esbw.config.js` that fulfills the `ESBWConfig` interface:\n\n```typescript\nexport interface StagedBuildOptions extends BuildOptions {\n  /** Called before all artifacts are built. */\n  beforeAll?: () =\u003e Promise\u003cvoid\u003e;\n  /** Called after all artifacts are built. */\n  afterAll?: () =\u003e Promise\u003cvoid\u003e;\n\n  /**\n   * Array of `artifactName`s. If defined, only these artifacts\n   * will be built. If not defined, all artifacts are built.\n   *\n   * For example, you may only need to build one artifact during\n   * `serveMode` or `watchMode`, but during `buildMode`, build all artifacts.\n   */\n  build?: string[];\n\n  /**\n   * Applicable to 'run' mode.\n   * What file to run after building all outfiles.\n   */\n  runfile?: string;\n\n  /**\n   * Applicable to all modes except 'buildMode'.\n   * Accepts regular expressions.\n   * Files that pattern match trigger rebuild.\n   */\n  watchPaths?: string[];\n}\n\nexport interface ESBWConfig {\n  /**\n   * Least-specific BuildOptions.\n   * These are spread to all defined output artifacts.\n   */\n  artifactsCommon?: BuildOptions;\n\n  /**\n   * Artifact-specific BuildOptions.\n   * \n   * Takes priority over `artifactsCommon` BuildOptions.\n   * Object key is an arbitrary \"artifactName\" that can be used\n   * as an artifact reference by things like 'server'.\n   */\n  artifacts?: {\n    [artifactName: string]: BuildOptions;\n  };\n\n  /**\n   * BuildOptions applied to all artifacts when building\n   * with `esbuild-wrapper build`,\n   * \n   * Takes priority over artifacts[artifactName].\n   */\n  buildMode?: StagedBuildOptions;\n\n  /**\n   * BuildOptions applied to all artifacts when serving\n   * with `esbuild-wrapper serve`,\n   * \n   * Takes priority over artifacts[artifactName].\n   */\n  serveMode?: StagedBuildOptions \u0026 {\n    index?: string;\n    injectArtifacts?: string[];\n    port?: number;\n  }\n\n  /**\n   * BuildOptions applied to all artifacts when watching\n   * with `esbuild-wrapper watch`,\n   * \n   * Takes priority over artifacts[artifactName].\n   */\n  watchMode?: StagedBuildOptions;\n\n  /**\n   * BuildOptions applied to all artifacts when watching\n   * with `esbuild-wrapper run`,\n   *\n   * Accepts a `runfile` which is a path to a file that\n   * will be executed after a rebuild.\n   * \n   * Takes priority over artifacts[artifactName].\n   */\n  runMode?: StagedBuildOptions;\n}\n```\n\n## Configuration hierarchy\n\n`artifactsCommon` -\u003e `artifacts` -\u003e `serve/run/build/watchMode`\n\n1. `artifactsCommon` is of type `BuildOptions`. The configuration defined here is applied to all\ndefined artifacts in `artifacts`.\n2. `artifacts` is an object of shape `{ [artifactName: string]: BuildOptions }`, and these configurations\nare prioritized over the ones defined in `artifactsCommon`.\n3. Finally, each mode accepts a `StagedBuildOptions` which is even higher priority than the configurations\ndefined in `artifacts`.\n\nA basic config when creating for the browser might look like this:\n\n```javascript\n// esbw.config.js\nexport default {\n  artifacts: {\n    main: {\n      platform: \"browser\",\n      bundle: true,\n      format: \"esm\",\n      entryPoints: [\"./src/index.ts\"],\n      outfile: \"./dist/index.js\",\n     },\n  },\n  serveMode: {\n    index: \"public/index.html\",\n    injectArtifacts: [\"main\"],\n    build: [\"main\"],\n  },\n  buildMode: {\n    minify: true,\n    minifyWhitespace: true,\n    sourcemap: false,\n  },\n}\n```\n\nBecause this is a fairly simple project with only one defined output artifact, there's no need\nto define an `artifactsCommon`.\n\nThe `serveMode` object optionally defines an html entrypoint where built artifacts\ndefined by `injectArtifacts` will be injected. `serveMode.build` is an array of artifacts\nthat should be built whenever changes are made.\n\nHere's a slightly more involved configuration for a browser project that uses a custom JSX pragma, where esbuild shims the import for the\npragma into each outfile file automatically.\n\n```javascript\n// esbw.config.js\nimport { readFileSync } from \"fs\";\nimport path from \"path\";\n\nconst pkg = JSON.parse(readFileSync(path.resolve(\"./package.json\")));\n\nexport default {\n  artifactsCommon: {\n    platform: \"browser\",\n    bundle: true,\n    loader: { \".ts\": \"tsx\" },\n    inject: [\"./pragma-shim.js\"],\n    jsxFactory: \"h\",\n    jsxFragment: \"Fragment\",\n    entryPoints: [\"./src/index.ts\"],\n  },\n  artifacts: {\n    esm: {\n      format: \"esm\",\n      outfile: \"./dist/index.esm.js\",\n    },\n    cjs: {\n      format: \"cjs\",\n      outfile: \"./dist/index.cjs.js\",\n    },\n    iife: {\n      format: \"iife\",\n      outfile: \"./dist/index.iife.js\",\n    },\n  },\n  serveMode: {\n    index: \"public/index.html\",\n    minify: false,\n    minifyWhitespace: false,\n    injectArtifacts: [\"esm\"],\n    watchPaths: [\"./src/**/*.ts\"],\n    build: [\"esm\"]\n  },\n  watchMode: {\n    external: [\"mir\"],\n    minify: true,\n    minifyWhitespace: true,\n    watchPaths: [\"./src/**/*.ts\"],\n    build: [\"esm\"]\n  },\n  buildMode: {\n    external: [\"mir\"],\n    build: [\"esm\", \"cjs\", \"iife\"],\n    banner: {\n      js: `// ${pkg.name} ${pkg.version}`,\n    },\n  },\n};\n\n// pragma-shim.js\nimport { h, Fragment } from \"mir\";\nexport { h, Fragment };\n```\n\nAn example node project:\n\n```javascript\nexport default {\n  artifactsCommon: {\n    platform: \"node\",\n    bundle: true,\n  },\n  artifacts: {\n    esm: {\n      format: \"esm\",\n      entryPoints: [\"./src/index.ts\"],\n      outfile: \"./dist/index.esm.js\",\n    },\n  },\n  runMode: {\n    build: [\"esm\"],\n    watchPaths: [\"./src/**/*.ts\"],\n    runfile: \"./test.js\",\n  },\n  buildMode: {\n    minify: true,\n    minifyWhitespace: true,\n  }\n}\n```\n\nIn the above config, `runMode` defines a `runfile` that will be called with `node \u003crunfile\u003e` after\nthe \"esm\" artifact is built.\n\n# `beforeAll` and `afterAll`\n\n`beforeAll` is handy if you need to do something before all artifacts\nare generated by esbuild, like processing styles with PostCSS as in the example below.\n\n```javascript\nasync function style() {\n  const from = \"src/style/style.css\";\n  const to = \"public/css/style.css\";\n  const css = readFileSync(from);\n  const result = await postcss([tailwindcss, autoprefixer]).process(css, { from, to });\n  writeFileSync(to, result.css);\n}\n\nexport default {\n  serveMode: {\n    index: \"public/index.html\",\n    build: [\"esm\"],\n    watchPaths: [\"./src/**/*.ts\"],\n    beforeAll: async () =\u003e await style(),\n  },\n  artifacts: {\n    esm: {\n      bundle: true,\n      entryPoints: [\"./src/index.tsx\"],\n      outfile: \"./dist/index.esm.js\",\n    }\n  },\n}\n```\n\n# Serving\n\nThe `index.html` pointed to by `serveMode.index` doesn't need to explicitly include a path to any outfile, that's the point of the `serveMode.injectArtifacts` option. The `outfile` of the referenced artifact is automatically injected during `esbuild-wrapper serve`.\n\nIn other words, if `serveMode.injectArtifacts` is `[\"esm\"]`, `artifacts.esm.outfile` gets\ninjected onto the page.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnvms%2Fesbuild-wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnvms%2Fesbuild-wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnvms%2Fesbuild-wrapper/lists"}