MemberJunction / MemberJunction/MJ
mj dev workspace should manage the Angular prebundle exclude for linked scopes
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 323
Description
Split out of the `next` install break triaged in #3849, so the capability isn't lost when the leak is reverted.
## The pattern
Joined-workspace host wiring keeps leaking into the public repo, because there is no supported place to put it. Three instances in about a day:
| Leak | Where | Outcome |
|---|---|---|
| `dynamicPackages` block | `mj.config.cjs` (#3842) | reverted by #3844 — the comment literally said NEVER COMMIT |
| `@mj-biz-apps/*` deps | `packages/MJAPI/package.json`, `packages/MJExplorer/package.json` (#3834) | broke `pnpm install` on every clean checkout |
| `@mj-biz-apps/*` prebundle glob | `packages/MJExplorer/angular.json` (#3834) | inert, but same class |
Reverting is right in each case, but reverting alone guarantees a fourth instance: the developer wanted a real thing, got it working locally, and the only way to keep it was to commit it.
## The specific gap
`mj dev workspace` already owns joined-workspace setup, but it does **not** touch `packages/MJExplorer/angular.json`, and no guide documents the setting. I checked — there are no references to `angular.json` or `prebundle` anywhere under `packages/MJCLI/src/lib/dev-workspace` or `packages/MJCLI/src/commands/dev`.
The setting in question:
```jsonc
// packages/MJExplorer/angular.json — serve.options
"prebundle": {
"exclude": ["@memberjunction/*"]
}
```
Angular's Vite-based dev server pre-bundles dependencies into cached optimized chunks. A workspace-linked package that gets rebuilt under `pnpm run watch` is served from that cache, so your rebuild doesn't appear until the cache is invalidated. Excluding a scope keeps the dev server reading it fresh.
`@memberjunction/*` is committed and correct — it serves the repo's primary documented dev loop. A joined workspace needs exactly the same treatment for **its** linked scopes (`@mj-biz-apps/*` and any other host's), and that list is per-developer, so it cannot be committed.
## Proposal
Have `mj dev workspace` manage the prebundle exclude for the scopes it links, the same way it manages the rest of the join. Requirements:
- Add each linked scope's glob to `serve.options.prebundle.exclude` in the consuming app's `angular.json`, preserving `@memberjunction/*`.
- Make it reversible — `mj dev workspace` teardown (or whatever the leave/reset path is) removes exactly what it added.
- Leave the file untouched when no workspace is joined, so a clean checkout stays clean and the diff never shows up in an unrelated PR.
- Document it in `guides/DEV_WORKSPACE_QUICKSTART.md`, which currently doesn't mention prebundling at all.
## Worth considering while in here
Two things about the committed `@memberjunction/*` exclusion, neither urgent:
- **Cost for npm consumers.** Excluding a scope from prebundling means many more unbundled module requests, so dev-server cold start and page loads are slower. Anyone consuming MJ from npm rather than linking pays that cost without the benefit. Scoping the exclusion to the `local_modules` serve configuration — which already exists for exactly this "working against local packages" scenario — would target it better.
- **A latent CJS trap.** Prebundling is also what converts CJS to ESM for Vite. Today this is safe: `@memberjunction/core` and `@memberjunction/global` are `"type": "module"`, and `@memberjunction/graphql-dataprovider` is dual-format. But a future `@memberjunction/*` package shipping CJS-only would break the dev server under this glob, with an error that won't point here.
## References
- #3849 — the `next` install break this was split from
- #3844 — the `mj.config.cjs` instance of the same pattern
- `packages/MJCLI/src/lib/dev-workspace/`, `packages/MJCLI/src/commands/dev/workspace/index.ts`
- `guides/DEV_WORKSPACE_QUICKSTART.md`
Contributor guide
Research direction
Start in packages/MJCLI/src/lib/dev-workspace/ and packages/MJCLI/src/commands/dev/workspace/index.ts to trace workspace setup and teardown, then inspect packages/MJExplorer/angular.json and guides/DEV_WORKSPACE_QUICKSTART.md. Confirm how linked scopes are identified and how the leave/reset path works. Done means joined scopes are added and removed reversibly, the committed @memberjunction/* exclusion remains, clean checkouts stay unchanged, and the guide documents prebundling.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, typescript, vite
- Domain
- build-system, cli, developer-experience
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100