feature: migrate Angular 9 app to Vite + React 18 + TypeScript - #759
charityquinn-cognition wants to merge 5 commits into
Conversation
Co-Authored-By: Charity Quinn <charity.quinn@cognition.ai>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Co-Authored-By: Charity Quinn <charity.quinn@cognition.ai>
…UTING for Vite Co-Authored-By: Charity Quinn <charity.quinn@cognition.ai>
Co-Authored-By: Charity Quinn <charity.quinn@cognition.ai>
…nstall Co-Authored-By: Charity Quinn <charity.quinn@cognition.ai>
Runtime verification — 6833920Verified in the browser (recording in session):
Not covered: a successful |
Summary
Full frontend rewrite from Angular 9 to Vite + React 18 + TypeScript + react-router-dom v6 + sass, keeping the same HN API (
https://node-hnapi.herokuapp.com), URL structure, theming and PWA behaviour.Structure
index.html(root) ports all meta/manifest/icon tags,#skip,.app-loader/noscript and GA snippet;<app-root>→<div id="root">(#root:empty + .app-loaderkeeps the pre-boot loader working).src/services/hackerNewsApi.ts: plainfetchfunctionsfetchFeed / fetchItemContent / fetchPollContent / fetchUser. Poll options are fetched withPromise.allSettledoverstory.id + i; fulfilled options are kept andpoll_votes_countis summed over them, so one failed option request doesn't hide the story (the Angular code's fire-and-forget subscriptions behaved the same way).src/context/SettingsContext.tsx:SettingsProvider+useSettings()with the same settings shape,localStoragekeys, andprefers-color-schemelistener (night/default, persisted on first load when no saved theme, as before).App.tsx:/→/news/1;/{news,newest,show,ask,jobs}/:page→<Feed feedType=…>;/item/:id,/user/:idviaReact.lazy. GAset page/send pageviewfired from auseLocationeffect.components/core/{Header,Footer,Settings},components/shared/{Loader,ErrorMessage},views/feed/{Feed,Item},views/item-details/{ItemDetails,Comment}(recursive),views/user/User.commentpipe →utils/comment.ts#formatCommentCount.utils/sanitize.ts#sanitizeHtml(DOMPurify) beforedangerouslySetInnerHTML, replacing the sanitization Angular's[innerHTML]did implicitly.Styling — Angular emulated view-encapsulation kept each component's SCSS local; React styles are global, so each ported
.scssis wrapped in a root class (.app-feed,.app-item,.app-comment, …) applied to the component root, preserving the original cascade.:host >>> x→.app-<comp> x.@import→@use … as *,/division →math.div. Theme class names (.wrapper,#header,.subtext, …) are unchanged so_themes.scssapplies as before.PWA —
@angular/service-worker/ngsw-config.jsonreplaced byvite-plugin-pwa(autoUpdate, Workbox precache of js/css/html/icons viaglobPatterns,includeManifestIcons: falseto avoid conflicting precache entries,navigateFallback: /index.html); manifest content copied into the plugin config (emitsmanifest.webmanifest),public/manifest.json+public/assetsretained so existing links resolve.Removed —
angular.json,karma.conf.js,tslint.json,ngsw-config.json,browserslist,e2e/,src/app,src/environments, polyfills/test shims,yarn.lock, all@angular/*,zone.js,rxjs,unfetchdeps. Added ESLint (Vite react-ts preset);npm run buildrunstsc --noEmit && vite build.Behavioural notes
[class.head-margin]="item.text"referenced a field that never existed onStory(so it never applied); it now keys offitem.content(the actual API field), which is the evident intent.content?: stringadded toStory..travis.ymlbumped to Node 20 and no longer installs@angular/cli.firebase.jsonstill deploysdist/.npm run dev/build/preview..agents/skills/angular-to-react-migration/SKILL.mddocumenting this migration recipe for reuse.Known open item — Snyk flags two moderate advisories in
react-router@6(GHSA-wrjc-x8rr-h8h6 open redirect via<Link>, GHSA-337j-9hxr-rhxg SSR-only). The only fix isreact-router-dom@7; kept v6 per the requested stack pending a decision.Verified locally:
npm run lint,npm run build(dist containsindex.html,manifest.webmanifest,sw.jswith 29 unique precache entries, icons), and/news/1,/jobs/1,/item/:id(nested comments) render without console errors.Devin-Org: engineering
Link to Devin session: https://app.devin.ai/sessions/045c0d5f0c904882950ce7f810c8e332
Open in Devin Desktop: https://app.devin.ai/desktop/session/045c0d5f0c904882950ce7f810c8e332?variant=devin
Requested by: @charityquinn-cognition