chore: migrate from TS path aliases to workspaces + project references#774
Draft
layershifter wants to merge 26 commits into
Draft
chore: migrate from TS path aliases to workspaces + project references#774layershifter wants to merge 26 commits into
layershifter wants to merge 26 commits into
Conversation
0e4468d to
953c290
Compare
Contributor
📊 Bundle size report✅ No changes found |
6c3e83b to
9bd737f
Compare
4 tasks
9bd737f to
e92975d
Compare
e92975d to
905f100
Compare
Squash-rebase of the earlier 4-commit migration onto current main. The migration replaces TS path aliases with yarn workspaces + project references and a custom `@griffel/source` exports condition, switches tsconfig.base.json to `moduleResolution: bundler` with composite builds, registers `@nx/js/typescript` for inferred type-check targets, moves each package's build output to `packages/X/dist`, and dual-emits ESM + CJS via `tools/build-cjs.mjs` for the three runtime-dual packages. Versions and dep ranges follow current main (post-`10b7b8f3`); the publishable packages' internal deps stay as `^X.Y.Z` so `npm pack` survives without yarn's workspace-protocol rewriting. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Switch CJS-with-issue packages (babel-preset/jest-serializer/ webpack-extraction-plugin) build target to tsconfig.build.json so they actually emit ./dist/ (their tsconfig.lib.json is typecheck-only with emitDeclarationOnly). - Move per-condition `types` from top-level into the `import`/`require` branches of core/react/shadow-dom exports so CJS consumers resolve to ./dist/cjs/index.d.cts under moduleResolution: node16/nodenext. - Drop the beachball patch — the workspace-level dist/packages/X path it redirects to no longer exists with per-package dist/. Publish works from packages/X/ directly thanks to the per-package `files` field. - Include virtual-loader/ in webpack-extraction-plugin's files, and point virtual-loader/index.js at ../dist/constants.js (was source TS). - Pin @typescript-eslint/utils to a single version via resolutions (the nested @typescript-eslint/rule-tester copy caused RuleModule type identity mismatch in eslint-plugin tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
905f100 to
863599d
Compare
Internal-only change (build pipeline + tsconfig restructuring); no version bumps intended. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Bump @typescript-eslint/utils to ^8.59.3 in root and packages/eslint-plugin/ so the version ranges align with the resolution we already pin. - Add version: 0.0.0 to apps/website/package.json so syncpack stops complaining about VERSION_IS_MISSING. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Build outputs moved from `<repo>/dist/packages/X/src/` to `<repo>/packages/X/dist/` as part of the workspace migration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the workaround that imported from `../../../dist/packages/core/src/index.js` (broken anyway after the workspace migration moved build outputs). Add `resolve.conditions: ['@griffel/source']` to the package's vitest.config so the @griffel/source export condition resolves to core's TS source under test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
webpackLoader.mts resolves its virtual-loader via path.resolve(__dirname, 'virtual-loader', 'index.cjs') — that path needs to exist next to the compiled .mjs in dist/. tsc only emits .ts/.mts files, so the .cjs loader was missing from dist/, breaking rspack's CSS extraction (no griffel chunk → null .files crash in processAssets). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 21, 2026
…hook - Move the README/LICENSE staging from a per-build run-commands step into beachball's per-package `prepublish` hook. Build no longer touches these files; only publish does. - Drop tools/copy-pkg-assets.mjs and remove its invocation from every project.json build target. - Stop copying package.json into dist/ — `beachball publish` (and the matching `npm pack`) runs from the package root, so dist/package.json was dead weight. - Drop tools/deprecate-broken-release.mjs (one-off script no longer needed). - Drop CHANGELOG.md from every published package.json `files` field. - Drop the @griffel/* aliases from monosize.config.mjs — webpack now resolves them via the workspace symlink + exports map. - Drop the nxViteTsPaths() plugin from every vitest.config — there are no tsconfig paths left for it to expose; resolve.conditions: ["@griffel/source"] handles workspace resolution. - azure-pipelines.yml: add an explicit "Build all packages" step before the publish step, since the prepublish hook no longer triggers the build itself. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop noEmit and switch composite back to true so apps/website
participates in the workspace's tsc -b graph again. Reference it
from the root tsconfig.json so the @nx/js/typescript plugin can
infer a type-check target.
The Playground code/templates/* JS files are loaded as raw strings via
webpack require.context (not compiled), so exclude them from the
tsconfig include — they were tripping TS2742 ("inferred default type
not portable") when composite emit walked into @griffel/core's source.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Match the per-package dist/ layout the rest of the workspace is moving to. Docusaurus now builds into apps/website/dist instead of <repo>/dist/apps/website. .github/workflows/deploy.yml: point the Pages artifact upload at the new path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch the @griffel/* devDependencies from workspace:* to the exact published versions (matching what's published on npm + the workspace's @griffel/e2e-utils at "*" since it's a private workspace package). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a semverGroups rule so any semver-pinned @griffel/* internal dep must use a caret. The "*" workspace marker (used by private packages like @griffel/e2e-utils) is excluded via the specifierTypes filter. Restore the carets on e2e/eslint's published @griffel/* devDeps (@griffel/eslint-plugin, @griffel/react) which the rule now enforces. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ript Configure the @nx/js/typescript plugin to also infer a `build` target (in addition to type-check) from each package's tsconfig.lib.json. Drop the redundant nx:run-commands "build" from style-types/project.json — the inferred target runs the same `tsc --build tsconfig.lib.json`. The other published packages keep their explicit build targets for now (build-cjs chains, asset copies, etc.); they migrate package by package as the workspace migration progresses. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- packages/transform: drop explicit build target — @nx/js/typescript
infers it from tsconfig.lib.json, identical to the explicit one.
- e2e/utils: collapse the single-target exports map to the short form
("./src/index.ts"). e2e-utils is a private workspace package; no
consumer benefits from the explicit conditions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the explicit build target — @nx/js/typescript can now infer it. Merge the two-config setup into one: - Move the CJS build settings (module: node16, declaration: true, customConditions: [], outDir: ./dist) into tsconfig.lib.json itself. - Delete tsconfig.build.json. The customConditions: [] override (preserved from the old build config) keeps the @griffel/source resolution disabled here so typecheck resolves @griffel/core via its require condition → .d.cts, avoiding the CJS-importing-ESM-source TS1479 error. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Only e2e/utils uses .ts extensions in its imports; the other three e2e packages just import bare module specifiers like @griffel/e2e-utils. Drop the flag from their tsconfig.lib.json — it doesn't do anything useful there. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Leftover from an earlier iteration that had **/*.d.ts in the include patterns (which picked up emitted declarations from out-tsc and dist). That include is long gone; the exclude was guarding against nothing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ypescript Same as transform / style-types — the inferred build runs the same \`tsc --build tsconfig.lib.json\`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…kage.json - Same simplification as babel-preset: merge the dual tsconfig.lib.json + tsconfig.build.json into a single tsconfig.lib.json (module: node16, customConditions: [], outDir ./dist). Delete tsconfig.build.json. Drop the explicit build target from project.json — @nx/js/typescript infers it now. - Reorder package.json: metadata first, then entry points (main/types/ exports), then files, then deps. Matches the order in core/react/ shadow-dom. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Build targets — drop now-redundant explicit build entries in eslint-plugin, jest-serializer, postcss-syntax, webpack-loader project.json files. The @nx/js/typescript plugin infers them from tsconfig.lib.json. jest-serializer: collapse tsconfig.build.json into tsconfig.lib.json (same pattern as babel-preset / webpack-extraction-plugin — CJS with internal ESM imports, customConditions: [] sidesteps TS1479). Storybook configs (devtools, react, shadow-dom): restore composite + emit, drop noEmit, and reference them from the per-package tsconfig.json so they participate in the tsc -b graph. Drop unused emitDecoratorMetadata (would have required experimentalDecorators). Add jsx: react-jsx to react's storybook config so .tsx stories type-check. Package.json ordering (webpack-loader, eslint-plugin): metadata → entry points → files → deps, matching webpack-extraction-plugin / core / react. webpack-plugin: drop the lib override on `lib` (defaults from target: es2020 already include es2020 + dom). Drop the spec config's target/lib override entirely — spec reaches lib code via project reference, no need to restate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The override exists for BigInt literal support (used in GriffelPlugin's build-time stats). \`esnext\` reads more clearly as "newer than the base default", versus picking a specific year. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the build-time copy of src/virtual-loader/ into dist/virtual-loader/. Move the source to packages/webpack-plugin/virtual-loader/ (one dir up from src/) and have `npm pack` ship it via the `files` field, matching how webpack-extraction-plugin already handles its virtual-loader. - Move src/virtual-loader/index.cjs → virtual-loader/index.cjs. - webpackLoader.mts: resolve virtualLoaderPath via ../virtual-loader/ (the compiled .mjs in dist/ is one level below virtual-loader/). - package.json files: add "virtual-loader/". - project.json: drop the explicit build target entirely — the @nx/js/typescript-inferred build does the right thing now that there's no copy step to chain. - Update 15 __fixtures__/<name>/output.ts snapshots to reflect the new relative path from each fixture to the loader. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n virtual-loader Match the simpler pattern used by webpack-plugin's virtual-loader: compute the global symbol inline via Symbol.for() instead of pulling it in from ../dist/constants. Drops the cross-file dependency and the awkward pre-build IDE state (where ../dist didn't exist yet). The JSDoc still references ../src/constants for the SupplementedLoaderContext type, which exists in workspace dev (source TS) for tooling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…d-cjs Drop the `_build_tsc` placeholder target. Rename the previous nx:run-commands "build" (which only invoked tools/build-cjs.mjs) to "build-cjs". Add a plain "build" target that runs tsc directly. The @nx/js/typescript plugin can't infer "build" for these three packages because their nested exports.require.default points outside the lib config's outDir; the explicit target keeps things simple. nx.json: targetDefaults wire the chain: - build dependsOn ^build, ^build-cjs - build-cjs dependsOn build, ^build-cjs That way `nx run X:build-cjs` builds tsc first then the CJS step, and any consumer's "build" waits for its deps' tsc + cjs outputs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`main` is the fallback for bare `require('@griffel/core')` calls in
older tooling that doesn't honor the exports map. With type: module
+ main: ./dist/index.js, require() would resolve to the ESM build —
fine on Node 22+ via require(esm), but breaks any consumer still on
an older Node or build tool. Restore the CJS path so the fallback
matches the require condition in exports.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Convert tools/build-cjs.mjs → tools/build-cjs.ts. Node 24+ runs .ts
natively (same approach the e2e packages use). Drops the awkward
\`@type {const}\` JSDoc in favor of real types — SWC_OPTIONS is now
typed as \`Options\` from @swc/core, and every helper has proper
parameter/return types.
- Drop the redundant \`!absInput.endsWith('.d.cts')\` guard. A filename
ending in .d.cts can't also end in .d.ts (the suffixes are literally
different), so the check was dead.
- Update build-cjs commands in core/react/shadow-dom project.json to
reference tools/build-cjs.ts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tsconfig.base.jsonwith Yarn workspaces + TypeScript project referencesmoduleResolutionto"bundler"withcustomConditions: ["@griffel/source"]for source-level resolutioncompositebuilds with cross-projectreferencesin tsconfig files@nx/js/typescriptplugin to infertype-checktargets automaticallyextends,rootDir, remove redundant options)workspace:*dependencies for internal@griffel/*packagestag-processor/tsconfig.build.jsonfor CJS output (wyw-in-js runtime evaluation)CI status: type-check (22), build (13), test (17 non-e2e), lint (17) all pass.
E2e tests need follow-up for
npm packcompatibility with new output paths.Test plan
nx run-many -t type-check— all 22 projects passnx run-many -t build— all 13 projects passnx run-many -t test(excluding e2e) — all 17 projects passnx run-many -t lint— all 17 projects passpackage.jsonindist/fornpm pack🤖 Generated with Claude Code