Skip to content

Preparation before removing babel plugins - adding import extensions and displayName manually#2580

Open
joyenjoyer wants to merge 3 commits into
masterfrom
pr1-esm-safe-source-prep
Open

Preparation before removing babel plugins - adding import extensions and displayName manually#2580
joyenjoyer wants to merge 3 commits into
masterfrom
pr1-esm-safe-source-prep

Conversation

@joyenjoyer
Copy link
Copy Markdown
Contributor

@joyenjoyer joyenjoyer commented Jun 4, 2026

Summary

This PR prepares the removal of Babel and Babel plugins. It writes two things into the source that Babel plugins inject today: explicit relative-import extensions and static displayNames. It also adds minimal webpack config so our own toolchains resolve the new specifiers.

No transpiler change. Babel still runs, with the same plugins. The plugins are idempotent. They skip a specifier already ending in .js. They skip a class that already has a displayName. So the compiled es/ and lib/ output stays semantically identical to master.

This keeps master releasable. It also makes the later SWC safe.

This is PR1 of a 3-PR stack:

  • PR1 (this one) — source prep, no transpiler change. Non-breaking.
  • PR2 — swap babel-loaderswc-loader in the Cypress + docs webpack builds. Library build still Babel. Nothing published changes.
  • PR3 — ESM-only library build on SWC, and remove Babel + its plugins. The breaking PR.

What changed (3 commits)

  1. add explicit import extensions to relative specifiers — appends .js (or /index.js for directory imports) to relative import / export ... from specifiers. Reproduces babel-plugin-add-import-extension. Relative specifiers only. Bare/package and type-only imports are untouched.
  2. add static displayName to component classes — adds static displayName = '<ClassName>' to React class components that lack one. Reproduces babel-plugin-add-displayname-for-react. It is idempotent: it skips classes that already have one, and any class without a render method. This includes the __docs__ app. Its Babel config (packages/__docs__/babel.config.js) uses @instructure/ui-babel-preset, which runs add-displayname-for-react unconditionally. So Babel was already injecting displayName into the docs' class components at build time. Writing it into the source keeps that behavior identical once Babel is removed in PR3.
  3. resolve .js specifiers to TypeScript source in webpack — adds resolve.extensionAlias (.js.ts/.tsx) to the Cypress config and the shared ui-webpack-config. This lets webpack builds that bundle the .ts/.tsx source directly (Cypress, docs) resolve the new .js specifiers. It is a consequence of the source change, so it lives here.

What is intentionally NOT in this PR

  • Removing the Babel plugins. They stay until PR3. Removing them here would change build output. It would also break the ESM output of generated files (ui-icons/src/generated, ui-themes tokens). Those are generated/gitignored, so the source edits can't cover them. Generator updates will be in a later PR.

Compiled-output deltas vs master

All behavior-preserving:

  • ESM (es/) — cosmetic codegen only. Semantically identical. The possible differences are:
    • Quote style — a specifier emitted with single quotes vs double quotes (e.g. "./useStyle.js"'./useStyle.js').
    • Blank lines — an added or removed empty line between statements.
    • Comment placement — a leading comment attached to a slightly different line.
    • Line wrapping — a long import/export wrapped across lines vs kept on one line.
    • Trailing commas / whitespace — minor punctuation or indentation noise from the codegen path.
  • CJS (lib/) — the added .js specifiers, plus the require binding names Babel derives from them. Behavior-preserving. They disappear once PR3 drops the lib/ build.

How to test?

  • Run commands (bootstrap, test, dev)
  • Spot check file in es folders, compare it to latest master
  • Use Balazs' diff tool or another comparison script but keep in mind there will be changes (read the Compiled-output deltas vs master above), it is only an issue if the two files are not semantically identical

Appends .js/index.js to relative imports across the source so the output resolves under native ESM.
Preserves component identity without Babel's add-displayname plugin.
The explicit .js relative-import extensions added for native ESM must still
resolve when webpack bundles the .ts/.tsx source directly (Cypress component
tests and the docs app). Add resolve.extensionAlias mapping .js->.ts/.tsx to
the Cypress and ui-webpack-config configs so the source prep does not break
those builds. No transpiler change.
@joyenjoyer joyenjoyer requested a review from Copilot June 4, 2026 12:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@joyenjoyer joyenjoyer self-assigned this Jun 4, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 4, 2026

PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://instructure.design/pr-preview/pr-2580/

Built to branch gh-pages at 2026-06-04 12:16 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

github-actions Bot pushed a commit that referenced this pull request Jun 4, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 4, 2026

Visual regression report

No changes.

Status Count
Unchanged 32
Changed 0
New 0
Removed 0

📊 View full report

Baselines come from the visual-baselines branch. They refresh on every merge to master.

@joyenjoyer joyenjoyer requested review from balzss and matyasf June 4, 2026 12:55
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