Skip to content

feat(app-tools): support programmatic dev/build lifecycle - #8783

Merged
GiveMe-A-Name merged 8 commits into
mainfrom
feat/export-modern-app-tools-dev
Jul 31, 2026
Merged

feat(app-tools): support programmatic dev/build lifecycle#8783
GiveMe-A-Name merged 8 commits into
mainfrom
feat/export-modern-app-tools-dev

Conversation

@GiveMe-A-Name

Copy link
Copy Markdown
Member

Use the app context command to initialize builders and resolve occupied ports for programmatic dev and start calls.

Export closeServer from the package root, await Node close callbacks, and propagate close errors.

Summary

Related Links

Checklist

  • I have added changeset via pnpm run change.
  • I have updated the documentation.
  • I have added tests to cover my changes.

Use the app context command to initialize builders and resolve occupied ports
for programmatic dev and start calls.

Export closeServer from the package root, await Node close callbacks, and
propagate close errors.
@netlify

netlify Bot commented Jul 28, 2026

Copy link
Copy Markdown

Deploy Preview for modernjs-byted ready!

Name Link
🔨 Latest commit 4a2d422
🔍 Latest deploy log https://app.netlify.com/projects/modernjs-byted/deploys/6a6c7c4e3acb690008dd2d71
😎 Deploy Preview https://deploy-preview-8783--modernjs-byted.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 99 (no change from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@changeset-bot

changeset-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4a2d422

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 118 packages
Name Type
@modern-js/app-tools Minor
@modern-js/adapter-rstest Minor
@modern-js/plugin-bff Minor
@modern-js/plugin-ssg Minor
@modern-js/plugin-styled-components Minor
@modern-js/plugin-i18n Minor
@modern-js/image Minor
@modern-js/runtime Minor
@modern-js/plugin-polyfill Minor
@integration-test/alias-set Patch
app-document Patch
async-entry-test Patch
tmp Patch
bff-api-app Patch
bff-client-app Patch
bff-indep-client-app Patch
bff-hono Patch
integration-clean-dist-path Patch
integration-compatibility Patch
integration-custom-dist-path Patch
custom-file-system-entry Patch
integration-custom-template Patch
deploy Patch
deploy-server Patch
dev-server Patch
integration-disable-html Patch
entries-app-builder Patch
app-custom-entries Patch
app-custom-routes-runtime Patch
app-custom Patch
app-entry Patch
app-route Patch
app-entry-server Patch
i18n-app-csr-html-lang Patch
i18n-app Patch
i18n-app-ssr-html-lang Patch
i18n-app-ssr Patch
i18n-custom-i18n-wrapper Patch
i18n-mf-app-provider Patch
i18n-mf-component-provider Patch
i18n-mf-consumer Patch
i18n-routes Patch
i18n-routes-ssr Patch
@integration-test/image-component Patch
main-entry-name Patch
nonce Patch
pure-esm-project Patch
react-compiler-test Patch
routes-match Patch
routes Patch
app-rsbuild-hooks Patch
rsc-csr-app Patch
rsc-csr-routes Patch
rsc-ssr-app Patch
rsc-ssr-routes Patch
basic-app-rstest-browser Patch
basic-app-rstest Patch
runtime-custom-plugin Patch
runtime-custom-config-plugin Patch
select-mul-entry-test Patch
select-one-entry-test Patch
server-config Patch
server-json-script Patch
server-monitors Patch
server-prod Patch
server-routes Patch
@source-code-build/app Patch
ssg-fixtures-mega-list-routes Patch
ssg-fixtures-nested-routes Patch
ssg-fixtures-simple Patch
ssg-fixtures-web-server Patch
ssr-base-async-entry-test Patch
ssr-base-async-pre-entry-test Patch
ssr-base-json-test Patch
ssr-base-test Patch
ssr-base-fallback-test Patch
init Patch
ssr-base-loadable Patch
ssr-partial-test Patch
rsc-closing-tags-test Patch
ssr-script-loading Patch
ssr-useid-test Patch
ssr-streaming-inline-test Patch
ssr-streaming-lazy-test Patch
ssr-streaming-test Patch
styled-components-stream Patch
styled-components-string Patch
integration-tailwindcss-v2 Patch
integration-tailwindcss-v3 Patch
integration-tailwindcss-v4-tools Patch
integration-tailwindcss-v4 Patch
tmp-dir Patch
write-to-dist Patch
@modern-js/bundle-diff-benchmark Minor
@modern-js/main-doc Minor
@modern-js/tsconfig Minor
@modern-js/builder Minor
@modern-js/plugin-data-loader Minor
@modern-js/render Minor
@modern-js/bff-core Minor
@modern-js/bff-runtime Minor
@modern-js/server-core Minor
@modern-js/create-request Minor
@modern-js/prod-server Minor
@modern-js/server-runtime Minor
@modern-js/server Minor
@modern-js/server-utils Minor
@modern-js/create Minor
@modern-js/i18n-utils Minor
@modern-js/plugin Minor
@modern-js/runtime-utils Minor
@modern-js/sandpack-react Minor
@modern-js/types Minor
@modern-js/utils Minor
@modern-js/rslib Minor
@scripts/prebundle Patch
@scripts/rstest-config Patch
@scripts/release-node Patch

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

@github-actions

Copy link
Copy Markdown
Contributor

Rsdoctor Bundle Diff Analysis

📊 Quick Summary
Project Total Size Change
bundle-diff 471.8 KB 0

Generated by Rsdoctor GitHub Action

Remove the in-flight close tracking and callback waiting added for PIA test-kit.
Keep the existing fire-and-forget singleton shutdown behavior.
@GiveMe-A-Name GiveMe-A-Name changed the title feat(app-tools): support programmatic dev lifecycle feat(app-tools): support programmatic dev/build lifecycle Jul 29, 2026
GiveMe-A-Name and others added 4 commits July 29, 2026 15:55
The dist cleanup lived in the plugin `onPrepare` hook and gated on the CLI
argv command via `getCommand()`, so programmatic `dev`/`build`/`deploy`
(whose command lives in `appContext.command`, with a test-runner argv) never
emptied dist. Combined with the builder forcing `output.cleanDistPath: false`,
programmatic build/deploy kept stale chunks/server output that the deploy
preset could bundle.

Move the cleanup into the `dev` and `build` commands (new `cleanDistPath`
helper honoring `output.cleanDistPath`). This makes CLI and programmatic paths
behave identically and lets `deploy({ skipBuild: true })` preserve existing
dist for free (no build call -> no clean), since `onPrepare` could not see the
programmatic `skipBuild` flag. Dev restarts still clean on each (re)start,
matching prior behavior.

Add real-filesystem tests for the helper and for `build` cleaning/preserving
dist per `cleanDistPath`.

Co-Authored-By: Riff <noreply@aicu.bytedance.net>
The previous commits moved dist cleanup into the `build`/`dev` commands, but
those run after the analyze plugin's `onPrepare` has already generated
`dist/nestedRoutes.json` (router `onBeforeGenerateRoutes`). Cleaning there
deleted that file on every `build`/`dev` — including the CLI — and
`generateRoutes` never rebuilds it, so server-side route-level SSR
(`ssrByRouteIds`) silently regressed.

Move cleanup back into the plugin `onPrepare` hook, where app-tools' `post`
ordering guarantees it runs before analyze generates the routes. Detect both
the CLI argv command and the programmatic `appContext.command`, so programmatic
`dev`/`build` clean stale output like the CLI does.

`deploy` is intentionally excluded from the programmatic fallback: a
programmatic `deploy({ skipBuild: true })` only opts out when `deploy()` runs
(after `onPrepare`), so cleaning here could wipe the dist it means to reuse.
Programmatic `deploy` dist cleanup remains a known limitation. CLI
`deploy --skip-build` keeps its existing argv guard.

Remove the temporary `cleanDistPath` helper and its tests; add
`onPrepareCleanup.test.ts` covering argv and programmatic command detection,
`cleanDistPath` honoring, and skipBuild/deploy exclusions.

Co-Authored-By: Riff <noreply@aicu.bytedance.net>

@deepcoldy deepcoldy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Reviewed the programmatic dev/build/deploy lifecycle changes; second review by an independent reviewer confirmed no blockers.

Verified:

  • Dist cleanup restored to onPrepare (runs before analyze's generateEntryCode), so dist/nestedRoutes.json is preserved — confirmed via a real modern build on the routes integration fixture. Command detection now recognizes both the CLI argv command and the programmatic appContext.command.
  • Programmatic deploy is intentionally excluded from the context fallback so deploy({ skipBuild: true }) preserves existing dist; programmatic-deploy dist cleanup is an accepted known limitation. CLI deploy --skip-build keeps its original semantics.
  • Dev restart behavior is equivalent to the previous implementation.
  • pnpm --filter @modern-js/app-tools build + tsc --noEmit pass; app-tools tests 110/110 pass; Biome clean; CI all green.

Non-blocking nit: the PR description still mentions closeServer "await Node close callbacks, and propagate close errors", which no longer matches the reverted fire-and-forget implementation — worth removing.

@GiveMe-A-Name
GiveMe-A-Name merged commit eda048d into main Jul 31, 2026
10 checks passed
@GiveMe-A-Name
GiveMe-A-Name deleted the feat/export-modern-app-tools-dev branch July 31, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants