chore!: bundle CLI with esbuild#2866
Conversation
🦋 Changeset detectedLatest commit: c525d5e The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Performance Benchmark (Lower is Faster)
|
| "types": "lib/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./lib/index.d.ts", |
| WORKDIR /build | ||
| COPY . . | ||
| RUN apk add --no-cache jq git && \ | ||
| npm ci --no-optional --ignore-scripts && \ |
There was a problem hiding this comment.
We don't need to skip deps under optionalDependencies, because we don't have deps at all.
| "release": "node ./scripts/release-publish.mjs", | ||
| "pack:prepare": "./scripts/local-pack.sh", | ||
| "respect:parser:generate": "pegjs --format es --output packages/respect-core/lib/modules/runtime-expressions/abnf-parser.js packages/respect-core/src/modules/runtime-expressions/abnf-parser.pegjs && cp packages/respect-core/lib/modules/runtime-expressions/abnf-parser.js packages/respect-core/src/modules/runtime-expressions/abnf-parser.js", | ||
| "build-docs:copy-assets": "cp packages/cli/src/commands/build-docs/template.hbs packages/cli/lib/commands/build-docs/template.hbs ", |
There was a problem hiding this comment.
We don't need any templates inside lib folder. We only have lib/index.js.
|
📦 A new experimental 🧪 version v0.0.0-snapshot.1781184257 of Redocly CLI has been published for testing. Install with NPM: npm install @redocly/cli@0.0.0-snapshot.1781184257 |
…ic for build-docs
| ); | ||
|
|
||
| const seenPkgRoots = new Set(); | ||
| const licenseGroups = new Map(); // spdx -> { text, packages: ['name@version — Copyright ...'] } |
There was a problem hiding this comment.
We cannot just point to our public repo, so i picked different approach to show license and packages to what it belongs. The current THIRD_PARTY_NOTICES has 772 rows.
| metafile: true, | ||
| // Avoid errors when external dependencies use CJS syntax. | ||
| banner: { | ||
| js: "import { createRequire as __createRequire } from 'node:module';\nconst require = __createRequire(import.meta.url);", |
There was a problem hiding this comment.
If i remove this it will not throw an error, but i will leave this as a guard. @tatomyr WDYT?
There was a problem hiding this comment.
Let's try without it first.
There was a problem hiding this comment.
I did more deep testing and received an error, so we leave this banner prop.
| !tsconfig.json | ||
| !package-lock.json | ||
| !README.md | ||
| !LICENSE.md |
There was a problem hiding this comment.
We have root LICENSE.md file with this extension.
| const templateSource = customTemplate | ||
| ? readFileSync(customTemplate, 'utf-8') | ||
| : DEFAULT_TEMPLATE_SOURCE; | ||
| const template = handlebars.compile(templateSource); |
There was a problem hiding this comment.
Do we still need to convert it to string?
There was a problem hiding this comment.
No, because we use 'utf-8'.
| "Roman Hotsiy <roman@redocly.com> (https://redocly.com/)" | ||
| ], | ||
| "dependencies": { | ||
| "devDependencies": { |
There was a problem hiding this comment.
Please check if npx changeset version will still correctly bump the CLI version when bumping its dev dependencies.
There was a problem hiding this comment.
I gave it a shot and looks like it updated CLI.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c525d5e. Configure here.
|
|
||
| for (const relInput of allInputs) { | ||
| const absInput = path.resolve(packageDir, relInput); | ||
| const pkgRootMatch = absInput.match(/^(.*\/node_modules\/(?:@[^/]+\/)?[^/]+)/); |
There was a problem hiding this comment.
Windows path breaks license scan
Low Severity
Third-party notice generation matches node_modules using a regex that only allows forward slashes, while path.resolve on Windows produces backslash paths. Bundled dependency discovery can be skipped on Windows, yielding incomplete or misleading THIRD_PARTY_NOTICES output.
Reviewed by Cursor Bugbot for commit c525d5e. Configure here.



What/Why/How?
Switched
@redocly/clito bundle withesbuildand produce one dependency-free file.scripts/build.mjs- esbuild config that bundlessrc/index.ts→lib/index.jsscripts/prepare-publish-dir.mjs- creates a.publishstaging directory with a minimalpackage.json(no dependencies) and only the files that need to be publishedscripts/local-pack.sh-pack:preparenow builds and packs from.publishpackages/clifromtsconfig.build.jsonreferences -tscno longer compiles theCLItemplate.hbsas a string constant inbuild-docs/utils.tsas a fallback -esbuilddoes not copy assets, soresolveTemplateSourcetries to read the file first and falls back to the embedded templatepackage.ts- replacedcreateRequirewith a static JSON import, whichesbuildhandles nativelypin-intersecting-deps.shand all yarn cache workarounds from smoke tests - no transitive deps means no version conflicts to pinReference
Testing
Locally, in CI, in other products.
Screenshots (optional)
Check yourself
Security
Note
High Risk
Major packaging and distribution change: published CLI has no
node_modulesdependencies, which can break plugins and integrators that relied on hoisting; esbuild bundling also changes how commands and assets load at runtime.Overview
@redocly/cliis now built with esbuild and published without runtimedependencies, so installs are faster and the tarball only containsbin/, bundledlib/, README, LICENSE, and generatedTHIRD_PARTY_NOTICES.The build pipeline adds
packages/cli/scripts/build.mjs(ESM bundle + code splitting, redoc leak guard on the main entry) andprepare-publish-dir.mjs(stages.publishwith a minimalpackage.json). Rootcompileruns the CLI bundle instead oftscfor the CLI;packages/cliis removed fromtsconfig.build.json. Release and snapshot flows publish from.publishviascripts/release-publish.mjsand updatedlocal-pack.sh.Breaking for plugin authors: packages hoisted from the CLI (e.g.
@redocly/openapi-core) are no longer available unless declared in the plugin’s own dependencies (documented in the changeset).build-docsis dynamically imported so heavyredoc/React code stays out of the main bundle; the default Handlebars template is inlined inutils.ts(file-based templates still work). Scorecard plugin evaluation sets__redocly_dirnamefrom an optional config directory viapathToFileURL. Smoke CI drops yarn cache/pin workarounds; Docker build no longer copiestemplate.hbsmanually.Reviewed by Cursor Bugbot for commit c525d5e. Bugbot is set up for automated code reviews on this repo. Configure here.