Skip to content

PWA parity and analytics (migration 7/8) - #695

Open
charityquinn-cognition wants to merge 2 commits into
devin/react-migration-6-userfrom
devin/react-migration-7-pwa
Open

PWA parity and analytics (migration 7/8)#695
charityquinn-cognition wants to merge 2 commits into
devin/react-migration-6-userfrom
devin/react-migration-7-pwa

Conversation

@charityquinn-cognition

@charityquinn-cognition charityquinn-cognition commented Aug 25, 2026

Copy link
Copy Markdown

Summary

Stacked on #694. Restores the two things the React build was missing versus Angular: the service worker / installability metadata, and page-view tracking.

Service workervite-plugin-pwa@0.20.5 (Workbox) replaces ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }). The config mirrors ngsw-config.json's two asset groups: precache the app shell (js,css,html,ico + manifest.json, matching the prefetch group) and runtime-cache /assets/** (the lazy group). navigateFallback: '/index.html' keeps deep links like /item/123 working offline. manifest: falsepublic/manifest.json stays the single source of truth instead of generating a second one. No runtime caching for node-hnapi.herokuapp.com; Angular didn't cache API responses either. devOptions stays disabled and registration is manual (registerSW({ immediate: true })), so the SW is production-only as before.

The assets route uses StaleWhileRevalidate, not CacheFirst. Angular's asset group was installMode: lazy + updateMode: prefetch — fetch on first request, but refresh cached copies when a new version activates — and public/assets/* filenames aren't content-hashed, so CacheFirst would serve a changed logo from cache forever. Revisioned precaching is the closer analogue of updateMode: prefetch, but it would download every icon at install time, which is exactly what installMode: lazy avoided; StaleWhileRevalidate keeps the lazy fetch and lets a stale asset heal on the next load.

index.html — carries over the full metadata block from src/index.html: description, twitter/og cards, theme-color #b92b27 (the Angular index also had a stray CLI-generated #1976d2; dropped in favor of the one matching the manifest), msapplication + apple-mobile-web-app metas, mask-icon, favicons and apple-touch-icons, with paths made root-absolute for Vite's public/. The skip-nav link and <noscript> message are kept; the .app-loader spinner is not — React mounts into that container, so a pre-boot spinner would never be removed.

Analytics — the analytics.js snippet and ga('create', 'UA-66348622-3', 'auto') return to index.html, and app.component.ts's NavigationEnd subscription becomes usePageViews(), an effect on useLocation(). urlAfterRedirects meant the post-redirect URL, so the hook skips / — otherwise the //news/1 redirect would report a phantom / view. ga is declared as a narrow optional global and called through window.ga?.(...), so builds without the snippet don't throw.

Verified: yarn react:build passes; sw.js activates on the preview server with the expected precache list and a StaleWhileRevalidate strategy registered for the assets route, an offline hard-reload of /news/1 still renders the shell, and stubbing window.ga on a cold load of / records exactly ['set','page','/news/1'] + ['send','pageview'].

Devin-Org: engineering

Link to Devin session: https://app.devin.ai/sessions/1ff25c6cf2f949458f82cc596fc79c65
Requested by: @charityquinn-cognition


Open in Devin Review

@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 3 potential issues.

Open in Devin Review

Comment thread index.html
Comment on lines +14 to +19
<meta name="twitter:image" content="/assets/images/logo-loading.png">

<meta property="og:title" content="Angular 2 HN"/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="https://angular2-hn.firebaseapp.com/"/>
<meta property="og:image" content="/assets/images/logo-loading.png"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Share preview image points to a missing file

twitter:image and og:image both reference /assets/images/logo-loading.png, but no such file exists under public/assets/images (only cog.svg, logo-header.png, logo.svg). Social and share previews resolve to a 404.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Preexisting, not introduced here — logo-loading.png was deleted upstream in b954b67 ("replace images with svgs") while the meta tags kept pointing at it, so src/index.html on master 404s the same way. This PR carried the tags over verbatim as part of the metadata port. Leaving it alone rather than silently repointing the share image at logo.svg (most crawlers won't render SVG previews, so that's a content decision, not a port fix) — happy to change it if you'd rather have working previews.

Comment thread src-react/main.tsx
Comment on lines +16 to +22
if (location.pathname === '/') {
return;
}

const page = `${location.pathname}${location.search}`;
window.ga?.('set', 'page', page);
window.ga?.('send', 'pageview');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Info: Page-view skip depends on '/' redirect path

usePageViews suppresses the / view so the root redirect to /news/1 does not double-count, and the GA snippet no longer sends an initial view. Correct only while the sole redirect origin stays exactly /.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/react-migration-7-pwa branch from e1d0bfe to 391655a Compare August 25, 2026 22:29
devin-ai-integration[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

Open in Devin Review

Comment thread vite.config.ts
Comment thread src-react/main.tsx
createRoot(document.getElementById('root')!).render(
registerSW({ immediate: true });

createRoot(document.getElementById('content')!).render(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Info: Mount target renamed root to content

createRoot now targets #content, which also holds the <noscript> fallback that React replaces on mount. No #root references remain in src-react, so the rename is consistent.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

devin-ai-integration Bot and others added 2 commits August 25, 2026 22:47
Co-Authored-By: Charity Quinn <charity.quinn@cognition.ai>
Co-Authored-By: Charity Quinn <charity.quinn@cognition.ai>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/react-migration-7-pwa branch from 247e4b0 to bf01639 Compare August 25, 2026 22:48
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