Skip to content

Bumped vite and vitest in portal, sodo-search, announcement-bar#27869

Merged
9larsons merged 1 commit into
mainfrom
security/vite-bump-step3
May 13, 2026
Merged

Bumped vite and vitest in portal, sodo-search, announcement-bar#27869
9larsons merged 1 commit into
mainfrom
security/vite-bump-step3

Conversation

@9larsons
Copy link
Copy Markdown
Contributor

Why

The three mid-version public/UMD apps move from vite@5.4.21 + vitest@3.2.4 to vite@7.3.2 + vitest@4.1.2, aligning with the rest of the apps lane that landed via PR #27731, commit ccf3d7368f, and PR #27867. After this PR, only signup-form and comments-ui remain on the legacy stack.

Bumps

Package vite vitest @vitest/coverage-v8 vite-plugin-svgr
portal 5.4.21 → 7.3.2 3.2.4 → 4.1.2 3.2.4 → 4.1.2 3.3.0 → 4.5.0
sodo-search 5.4.21 → 7.3.2 3.2.4 → 4.1.2 3.2.4 → 4.1.2 3.3.0 → 4.5.0
announcement-bar 5.4.21 → 7.3.2 3.2.4 → 4.1.2 3.2.4 → 4.1.2 3.3.0 → 4.5.0

Also removed: @vitest/ui from portal/package.json — it was listed but no script referenced it.

Patch version bumps on all three packages (CI version-bump check requires this whenever source files change in a monitored app).

Substantive changes beyond the bumps

SVG migration (vite-plugin-svgr v3 → v4)

v3 exposed both default (URL) and named ReactComponent on every .svg import; v4 splits them — ./foo.svg is the URL, ./foo.svg?react is the React component (as default export). v3's dual-export came from its transform hook merging with Vite's URL handling; v4's load hook bypasses Vite's asset pipeline entirely, so the dual export cannot be preserved by configuration.

Migrated 55 imports total:

  • 51 in portal (29 files)
  • 3 in sodo-search (1 file)
  • 1 in announcement-bar (1 file)

All are the simple form: import {ReactComponent as Foo} from '...svg'import Foo from '...svg?react'. No import.meta.glob patterns in these workspaces (unlike shade), and no typings.d.ts changes needed (these are .js projects, not TS).

vitest 3 → 4

No breaking patterns hit. None of the workspaces use typed vi.fn<> generics, global.fetch, or MockInstance<>. The function-shape generic fix that hit shade isn't needed here.

Test plan

  • pnpm --filter @tryghost/portal test — 541/541 passing (1 skipped, pre-existing)
  • pnpm --filter @tryghost/sodo-search test — 8/8 passing
  • pnpm --filter @tryghost/announcement-bar test — 1/1 passing
  • pnpm --filter @tryghost/portal build — exit 0; UMD wrapper intact at apps/portal/umd/portal.min.js (~2.4MB, comparable to main)
  • pnpm --filter @tryghost/sodo-search build — exit 0; UMD wrapper intact at apps/sodo-search/umd/sodo-search.min.js (~307KB)
  • pnpm --filter @tryghost/announcement-bar build — exit 0; UMD wrapper intact at apps/announcement-bar/umd/announcement-bar.min.js (~136KB)
  • Lint clean for all three (one autofix applied for import sort in sodo-search/src/components/popup-modal.js after the SVG migration)
  • CI confirms against the canonical environment

Notes

  • The "Module has been externalized for browser compatibility" warnings emitted for fs/path imports from @tryghost/root-utils, @tryghost/i18n, and find-root are pre-existing — same modules were externalized under vite 5; the warning text format is just more visible in vite 7.
  • Portal in particular loads in every Ghost site, so the UMD bundle compatibility check is the highest-stakes piece of CI for this PR.

The three mid-version public/UMD apps move from vite@5.4.21 + vitest@3.2.4
to vite@7.3.2 + vitest@4.1.2, aligning with the rest of the apps lane
that landed via PR #27731, ccf3d73, and #27867.

@vitest/coverage-v8 bumped from 3.2.4 to 4.1.2 in all three.
@vitest/ui (portal only) removed - it was listed but no script
referenced it.

Substantive changes beyond the bumps:

vite-plugin-svgr v3 -> v4 changed the SVG import API. v3 exposed both
`default` (URL) and named `ReactComponent` on every .svg import; v4
splits them - ./foo.svg is the URL, ./foo.svg?react is the React
component (as default export). Migrated 55 `import {ReactComponent as
X} from '...svg'` patterns to `import X from '...svg?react'` across:

- 51 imports in portal (29 files)
- 3 imports in sodo-search (1 file)
- 1 import in announcement-bar (1 file)

No vitest 3 -> 4 breaking patterns were present in these workspaces
(no typed `vi.fn<>` generics, no `global.fetch` references, no
`MockInstance<>` patterns).

Verification:
- portal: 541/541 tests (1 skipped, pre-existing), build, lint
- sodo-search: 8/8 tests, build, lint (one autofix for import sort
  in the SVG migration target)
- announcement-bar: 1/1 tests, build, lint
- All three UMD wrappers intact in produced .umd.js bundles
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9d34f672-6c3f-496e-9c84-65b6b14c200e

📥 Commits

Reviewing files that changed from the base of the PR and between 17f2ba2 and 99918e1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (32)
  • apps/announcement-bar/package.json
  • apps/announcement-bar/src/components/announcement-bar.js
  • apps/portal/package.json
  • apps/portal/src/components/common/action-button.js
  • apps/portal/src/components/common/back-button.js
  • apps/portal/src/components/common/close-button.js
  • apps/portal/src/components/common/gift-details-toggle.js
  • apps/portal/src/components/common/inbox-link-button.js
  • apps/portal/src/components/common/member-gravatar.js
  • apps/portal/src/components/common/popup-notification.js
  • apps/portal/src/components/common/powered-by.js
  • apps/portal/src/components/common/products-section.js
  • apps/portal/src/components/notification.js
  • apps/portal/src/components/pages/AccountHomePage/components/email-preferences-action.js
  • apps/portal/src/components/pages/AccountHomePage/components/paid-account-actions.js
  • apps/portal/src/components/pages/email-suppressed-page.js
  • apps/portal/src/components/pages/feedback-page.js
  • apps/portal/src/components/pages/gift-page.js
  • apps/portal/src/components/pages/loading-page.js
  • apps/portal/src/components/pages/magic-link-page.js
  • apps/portal/src/components/pages/newsletter-selection-page.js
  • apps/portal/src/components/pages/offer-page.js
  • apps/portal/src/components/pages/recommendations-page.js
  • apps/portal/src/components/pages/share/share-modal.js
  • apps/portal/src/components/pages/signin-page.js
  • apps/portal/src/components/pages/signup-page.js
  • apps/portal/src/components/pages/support-error.js
  • apps/portal/src/components/pages/support-success.js
  • apps/portal/src/components/pages/unsubscribe-page.js
  • apps/portal/src/components/trigger-button.js
  • apps/sodo-search/package.json
  • apps/sodo-search/src/components/popup-modal.js

Walkthrough

This pull request systematically modernizes SVG icon imports across three Ghost applications. The change migrates from the legacy SVGR ReactComponent named import pattern to Vite's ?react query syntax for loading SVG files as React components. Accompanying this syntax migration are package version increments for announcement-bar, portal, and sodo-search, plus coordinated upgrades to shared dev dependencies: Vite, vite-plugin-svgr, vitest, and @vitest/coverage-v8. The refactoring is applied consistently across dozens of components without altering component logic or behavior.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: bumping vite and vitest versions across three packages (portal, sodo-search, announcement-bar).
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the why, the specific version bumps, substantive SVG import changes, test results, and verification steps.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch security/vite-bump-step3

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.73%. Comparing base (17f2ba2) to head (99918e1).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #27869      +/-   ##
==========================================
- Coverage   73.74%   73.73%   -0.01%     
==========================================
  Files        1519     1519              
  Lines      127726   127726              
  Branches    15291    15291              
==========================================
- Hits        94186    94182       -4     
- Misses      32613    32615       +2     
- Partials      927      929       +2     
Flag Coverage Δ
admin-tests 53.43% <ø> (-0.03%) ⬇️
e2e-tests 73.73% <ø> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@9larsons 9larsons merged commit 37f548f into main May 13, 2026
46 checks passed
@9larsons 9larsons deleted the security/vite-bump-step3 branch May 13, 2026 17:23
9larsons added a commit that referenced this pull request May 13, 2026
The final two public/UMD apps move from vite@5.4.21 + vitest@1.6.1 to
vite@7.3.2 + vitest@4.1.2, finishing the unification across apps/* that
started with PR #27731 and continued through #27867 and #27869. Every
workspace under apps/ now runs the same vite + vitest pair.

@vitest/coverage-v8 in comments-ui jumped from 0.34.6 to 4.1.2 - it had
been pinned to a version compatible with vitest 0.x and was years out
of date.

Substantive changes beyond the bumps:

1. vite-plugin-svgr v3 -> v4 changed the SVG import API (./foo.svg
   now gives the URL, ./foo.svg?react gives the React component as
   default export). Migrated 16 imports across:
   - 14 in comments-ui (12 files)
   - 2 in signup-form (2 files)
   Both typings.d.ts files were split into *.svg (URL default) and
   *.svg?react (component default), using `import type` instead of
   the legacy `import React = require('react')` pattern.

2. vitest 1 -> 4 had two test-side issues in comments-ui:

   a. setup-tests.ts: `global.ResizeObserver = vi.fn()
      .mockImplementation(() => ({...}))` - vitest 4 enforces that
      mocks called with `new` have constructable implementations, and
      arrow functions are not constructable. Switched to function
      expression form.

   b. test/unit/utils/api.test.ts: three tests each called
      vi.spyOn(window, 'fetch') with no teardown. The spy persisted
      across tests, accumulating call counts. Added an afterEach
      with vi.restoreAllMocks().

3. vite 5 -> 7 build performance fix in all four public UMD apps
   (signup-form, comments-ui, plus portal and sodo-search already on
   vite 7 from #27869). Each app's vite.config used
   `commonjsOptions.dynamicRequireTargets: SUPPORTED_LOCALES.map(
   locale => '../../ghost/i18n/locales/' + locale + '/X.json')`,
   producing an array of ~60 explicit paths. Under vite 7's bundled
   @rollup/plugin-commonjs, each entry in that array triggers a full
   directory crawl from `dynamicRequireRoot` (= repo root, including
   node_modules) at the start of every build. The result was a ~58s
   delay before rollup's buildStart hook fired, which under
   `vite build && vite preview` blew playwright's webServer timeout
   (10s for signup-form, 20s for comments-ui).

   Replaced the N-entries-per-locale array with a single glob -
   `['../../ghost/i18n/locales/*/X.json']` - which the plugin
   resolves with one crawl. Same bundle output (verified byte-for-byte
   for portal/sodo-search/comments-ui; signup-form bundle size
   unchanged at 301817 bytes). Build time drops from ~60s to ~2s.

   Also fixed for portal and sodo-search in this PR even though
   they're not on the failing branch - they were already shipping
   the slow pattern on main via #27869 and the savings apply.

Patch version bumps on both new packages (CI version-bump check
requires this whenever source files change in a monitored app).

Verification:
- comments-ui: 207/207 unit tests, build (2.7s, was 60s), lint
- signup-form: build (2.0s, was 60s), lint
- portal: build (3.6s, was 60s+) - bundle byte-identical
- sodo-search: build (4.7s, was 60s+) - bundle byte-identical
- Local repro: dev:test webServer ready in 4s (was timing out)
9larsons added a commit that referenced this pull request May 13, 2026
The final two public/UMD apps move from vite@5.4.21 + vitest@1.6.1 to
vite@7.3.2 + vitest@4.1.2, finishing the unification across apps/* that
started with PR #27731 and continued through #27867 and #27869. Every
workspace under apps/ now runs the same vite + vitest pair.

@vitest/coverage-v8 in comments-ui jumped from 0.34.6 to 4.1.2 - it had
been pinned to a version compatible with vitest 0.x and was years out
of date.

Substantive changes beyond the bumps:

1. vite-plugin-svgr v3 -> v4 changed the SVG import API (./foo.svg
   now gives the URL, ./foo.svg?react gives the React component as
   default export). Migrated 16 imports across:
   - 14 in comments-ui (12 files)
   - 2 in signup-form (2 files)
   Both typings.d.ts files were split into *.svg (URL default) and
   *.svg?react (component default), using `import type` instead of
   the legacy `import React = require('react')` pattern.

2. vitest 1 -> 4 had two test-side issues in comments-ui:

   a. setup-tests.ts: `global.ResizeObserver = vi.fn()
      .mockImplementation(() => ({...}))` - vitest 4 enforces that
      mocks called with `new` have constructable implementations, and
      arrow functions are not constructable. Switched to function
      expression form.

   b. test/unit/utils/api.test.ts: three tests each called
      vi.spyOn(window, 'fetch') with no teardown. The spy persisted
      across tests, accumulating call counts. Added an afterEach
      with vi.restoreAllMocks().

3. vite 5 -> 7 build performance fix in all four public UMD apps
   (signup-form, comments-ui, plus portal and sodo-search already on
   vite 7 from #27869). Each app's vite.config used
   `commonjsOptions.dynamicRequireTargets: SUPPORTED_LOCALES.map(
   locale => '../../ghost/i18n/locales/' + locale + '/X.json')`,
   producing an array of ~60 explicit paths. Under vite 7's bundled
   @rollup/plugin-commonjs, each entry in that array triggers a full
   directory crawl from `dynamicRequireRoot` (= repo root, including
   node_modules) at the start of every build. The result was a ~58s
   delay before rollup's buildStart hook fired, which under
   `vite build && vite preview` blew playwright's webServer timeout
   (10s for signup-form, 20s for comments-ui).

   Replaced the N-entries-per-locale array with a single glob -
   `['../../ghost/i18n/locales/*/X.json']` - which the plugin
   resolves with one crawl. Same bundle output (verified byte-for-byte
   for portal/sodo-search/comments-ui; signup-form bundle size
   unchanged at 301817 bytes). Build time drops from ~60s to ~2s.

   Also fixed for portal and sodo-search in this PR even though
   they're not on the failing branch - they were already shipping
   the slow pattern on main via #27869 and the savings apply.

Patch version bumps on both new packages (CI version-bump check
requires this whenever source files change in a monitored app).

Verification:
- comments-ui: 207/207 unit tests, build (2.7s, was 60s), lint
- signup-form: build (2.0s, was 60s), lint
- portal: build (3.6s, was 60s+) - bundle byte-identical
- sodo-search: build (4.7s, was 60s+) - bundle byte-identical
- Local repro: dev:test webServer ready in 4s (was timing out)
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.

1 participant