1-App setup [Working Title] - Snappy GL
The target of this Epic is to improve the experience working in GitLab by a magnitude through multiple technical changes on the FE and integrated UX additions. The clear target is to have for example a list of own issues in 100ms and the same when going to the detail page. At the moment a user GitLab is mostly built in page-per-page basis for each user. We do save some data so far in the localstorage of the users browser. On top of that almost all pages have quite a high baseline for any interaction of a minimum of 500ms after each click. The plan is to pre-cache in the future commonly used data (e.g. users issues, base data of most used projects, etc.) in a more structured way through a client side indexeddb. This client side data will be used by optimistic rendering without page reloads to result in super fast interaction times (e.g. 100ms after click seeing own issues!). ### Current setup ![Bildschirmfoto_2022-09-29_um_15.59.51](/uploads/33409889147f685905cc39ada465f726/Bildschirmfoto_2022-09-29_um_15.59.51.png) ## Future Setup ![Bildschirmfoto_2022-09-30_um_12.54.59](/uploads/3c0e7c21809a597570523e433a5badb0/Bildschirmfoto_2022-09-30_um_12.54.59.png) POC MR - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98444 We started already with the work on making GitLab more and more PWA capable, one of the pillars for this future strategy is a service worker (https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86906) which will enable us to prefetch in the background both files (like static JS assets) and data that would be saved into IndexedDB. By using apollo-3-cache-persist we would have the possibility to encapsulate the client caching system easily. A pillar of the strategy is to reuse now our Vue Apps (e.g. Issue List, Detail, Boards, etc.) and inject them directly into the DOM without a full page reload and provide them with pre-cached data which is then updated and enriched by data from the server after the first render in the background. ### Example Flow * User starts GitLab and lands on Projects Page * Service worker is installed and starts pre-fetching list of Own issues and the issue Vue apps * User clicks on "My Issues" top menu item * We wipe the content DOM node and inject the Vuew App + Prefetched Data * We call the API and update the rendered results + update cache ### IndexedDB Usage By using persistent Apollo Cache with a custom data transformer for IndexedDB the target is to dissect GraphQL results into individual objects which then can be reused to reassemble results from this cache in ~10ms. The same DB can be queried to use already pre-cached objects to provide results for queries that have even not been called. We would also call the server API endpoint after this first quick fast render and of course we would implement cache timeouts, etc.. The target is not to cache everything but make especially common workflows much faster (for example own issues, own MR's, data of most used projects). Especially data that is used very often and fetched every time currently would highly benefit from it for example labels or users. At the moment we fetch on a group level 3628 users (which takes up to 2 seconds) for providing data for the quickactions, if this would be used from cache the results could be there in ms. Same goes for labels which are 2255 labels and takes around 800ms from server. ![Bildschirmfoto_2022-09-30_um_12.54.52](/uploads/6b30c7c39324e5128ebb29ce17acbe57/Bildschirmfoto_2022-09-30_um_12.54.52.png) # Implementation steps ## 1. Service Worker Setup We need a working service worker setup so we are able to pre-cache both JS app files as common data. - [ ] Base Service Worker - gitlab-org/gitlab!86906 - [ ] Evaluate workbox.js - https://developer.chrome.com/docs/workbox/ - [ ] Pre-Cache JS Bundles to file cache - [ ] Pre-Cache Own Assigned Issue List ## 2. IndexedDB and persistent GraphQL setup - [x] Basic IndexedDB Wrapper - https://dexie.org/ ? - [ ] Desconstruct GraphQL results into single objects - [ ] Reconstruct GraphQL pre-results from single objects - [ ] Enrich pre-results with current results -> save back to IndexedDB - [ ] Querying of IndexedDB objects ## 3. Inject Vue List App - [ ] Update GraphQL to query for assigned issues - https://gitlab.com/gitlab-org/gitlab/-/issues/377514 - [ ] Inject Body Element for rendering simple Vue Apps like the Issue List App - [ ] Render Issue List App with pre-result data ## 4. Inject Vue Project App and Vue overall App - [ ] Inject a Project Skeleton App for rendering content of a project - [ ] Slots for Sub Apps like the Issue Detail App ### 4. a) Project Skeleton App - [ ] Render Left Menu - [ ] Render Breadcrumbs ### 4. b) Issue Detail App - [ ] Unify Initial Data data tag usage to a single object which can later be init from IndexedDB Cache Object ### 3. Save Issue Meta Data - [ ] Take a look to store labels for projects - [ ] Take a look to store asignees for projects ## Bonus topic - Command Palette With having a local cache through indexedDB this gives us waaaay more possibilities to create a command palette in GitLab. As seen in the POC, the command palette topic is split off in its own epic - https://gitlab.com/groups/gitlab-org/-/epics/8912 ## Bonus topic - synchronizing different tabs Connecting tabs through https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel/BroadcastChannel with the service worker in place will enable us to for example fetch current issue, mr and todo counts in one place (service worker) and then send through a broadcast channel to all open tabs. So different counts in the top bar are a thing from the past! ## Bonus topic - Proper notification system With a service worker in place we can also extend notifications into proper browser notifications. # Future targets Future targets for using this setup for quick navigation and additional usage: * Issue Boards * Own MR List(s) * To-Do List * Own Projects * Own Groups
epic