-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Frontend architecture
Problems:
- Developing new features is slow and not straightforward due to competing frontend approaches and lack of good HTML / JS / CSS architecture
- Our collecion-based PHP frontend has not proved to be viable solution: for complex layouts it is hard to read; it is not easy to extract to separate higher level components ("regions" in current implementation); it treats Vue components as loosely connected, making hard to create full-page interactions etc.
- Performance is a key factor for future SEO and we are not delivering https://www.smashingmagazine.com/2021/01/front-end-performance-2021-free-pdf-checklist/
Solutions:
✅ Start writing new UIs in VueJS 3 and InertiaJS. Incrementally refactor old controllers and components to Inertia pages and VueJS components, per route.
Why:
- One single approach for frontend building
- Page loading and navigation is way faster
- Developer experience is improved (VS Code tooling for Vue etc)
- We can deliver SPA-like user experience without creating a fill SPA, so we can re-use existing auth, routers, models and most of the controllers.
Working example:
- Code: https://github.com/kristjanjansen/laravel-vite
Demo: https://laravel-vite-uwusu.ondigitalocean.app/
Notes:
- We already have 42 Vue components implemented
- SEO is a valid concern with SPAs. Note that Google SPA indexing has been significantly improved, crawled pages are rendered via latest Chromium and there seems to be no penalty on indexing frequency etc https://devchat.tv/js-jabber/jsj-477-understanding-search-engines-and-seo-for-devs-part-2/
- There's https://inertiajs.com/server-side-rendering but it might complicate our stack too much
- Inertia is a single-author project and its API is changing fast
- While data display, routing and simple interactions are trivial with Inertia, form submissiom, validation, error messaging and redirecton needs extra work and some sort of form building abstraction. Note that this is still significantly simpler than full SPA form management. See also https://engineering.aryeo.com/refactoring-to-inertia-forms
- Named routes need special handling https://github.com/tighten/ziggy
- We need to maintain Blade views / components for Mailables
- Performance critical issues -- layout shifts, image loading etc still need addressing, going to Vue / Inertial does not automatically solve it
Alternatives:
-
Keep the hybrid Blade / Vue approach, just get rid of the collection-based view controllers
-
Server-rendered JS framework: Nuxt (VueJS) / Next (React). Requires refactoring controllers into REST endpoints, creating authentication layer, form submission layer and duplicating a lot of state handling in the client. It is a massive overtaking.
CSS
Problems
- Current CSS setup is somewhat complex. We use many PostCSS plugins that create smooth but very optionated user experience where regular CSS approach does not apply (
?ifconditionals etc) - Many of the PostCSS plugns are now superseded by CSS features, such as CSS custom properties https://caniuse.com/css-variables
- Our PostCSS variables are somewhat limited and not really discoverable
- In some cases we also use SASS
Solutions:
❓ A. Use Tailwind
❓ B. Keep custom CSS but rely more on native CSS features, reduce amount of PostCSS plugins and perhaps use Tailwind naming conventions and values for CSS variables (with our own colors / typography)
When going Tailwind:
- Those "class streams" are still really long and hard to mainain even with Prettier plugin
- There gonna be portions of site that rely on regular CSS for a long time, so it means two CSS pipelines need to be preserved.
- We need to maintain a separate CSS for Mailables (or use
@applyapproach for intergrating Tailwind). - Utiliy-based CSS sort-of requires all the third party components be style-less, not to bring in builtin styles. There is not that many "bring your own styles" UI components in Vue ecosystem. There is https://headlessui.dev/ but it does not have all the components we require, for example combobox. See also https://gist.github.com/kristjanjansen/92b4803be1357ecc2b73d6a02aac738c
The upgrade is a big undertaking but it is likely needed anyway when upgrading to Vue 3.
Alternatives:
- SASS. Do we need it in 2021? CSS is almost catching up with SASS features and what can not be covered (nesting?), can be polyfilled with PostCSS.
Upgrade Vue
✅ Upgrade to Vue3, it's 2x smaller and 2x faster
Notes:
- Our third-party components might not all have Vue 3 versions and / or their APIs have changed
- Vue3 composition API is a bit verbose. To mitigate this, it's recommended to use
<script setup>syntax.
Frontend bundling
Problems:
- Webpack is slow and aging
- No proper hot reloading, just a hackish page reload based on Browsersync
- Supporting latest Vue needs a lot of reconfiguration
Solutions:
✅ Use ViteJS by authors of VueJS https://vitejs.dev/
Notes:
- Working, production-ready example is here https://github.com/kristjanjansen/laravel-vite
- We might temporary need to support two parallel frontend bundling pipelines (legacy and current)
I18N
❓ Multiple options
When moving to JS-based Vue3 / Inertia frontend, there are multiple options to bring in translations:
-
All translations in frontend based on
vue-i18n-next, with component-based strings and optionally a global translations file
https://github.com/intlify/vite-plugin-vue-i18n
https://github.com/intlify/vite-vue-i18n-starter -
Keep translations in PHP format http://blog.basaksecmen.com/localizing-a-laravel-app-with-vue-js-and-inertia-js-without-any-dependencies/ and pass them as page data. See also Add translation support for Inertia stack laravel/jetstream#232
-
Convert translations to JSON-based format https://laravel.com/docs/8.x/localization#using-translation-strings-as-keys, do the conversion: https://github.com/kkomelin/laravel-translatable-string-exporter and try to use JSON both in backend and fronend. This means converting all existing transtlations from
t('page.section.title')to__('Page title'). -
Do not use translations, use hardcoded Estonian strings. Sounds radical but when there is no foreseeable push for foreign markets we can cut development time here (and possibly re-introduce translations later). Note that testing already relies on hardcoded Estonian strings.
Backend performance
Problems:
- Backend speed could always be improved
- Upscale plans in Digital Ocean are expensive
Solutions:
✅ Use Laravel Octane as soon as it is production-ready https://github.com/laravel/octane / https://beyondco.de/blog/laravel-octane-introduction, can improve performance at least 4x.
Notes:
- Octane likely needs latest Laravel and PHP versions, so Laravel upgrade has to come first
- There is a Docker image for running Octane in Digital Ocean / Render https://github.com/kristjanjansen/laravel-vite
- There is Forge support https://blog.laravel.com/forge-octane-support
Search
Problems:
- Current search code is a custom complex MySQL fulltext implementation that duplicates content and comments data (needs factcheck)
- Algolia is a fast alternative but with our content numbers are massive so Algolia pricing is too expensive https://www.algolia.com/pricing/ (1$ per 1000 records).
Solutions:
✅ Use https://meilisearch.com/, an "open source Algolia".
Notes:
- Force can set up Meilisearch https://blog.laravel.com/forge-meilisearch-server-type
- DO can set up Meilisearch https://marketplace.digitalocean.com/apps/meilisearch
- Do we query Meilisearch server directly or use Laravel backend as a proxy? In latter case we can also inject other search results such as tags lookup into the results but this requires "double REST" implementation.
Alternatives:
- A separate Elasticsearch instance with
matchish/laravel-scout-elasticsearchdriver.
https://github.com/kristjanjansen/trip_search - A split solution: "hot" search via Algolia, "cold" search via mysql
E2E Testing
Problems:
- When moving to JS-based frontend, we a good E2E browser test suite based on Puppeteer.
Solutions:
✅ Use Laravel Dusk https://laravel.com/docs/8.x/dusk
Why:
- 1st party support
- We already have a set of tests in Dusk so only the legacy
laravel/browser-kit-testingtests has to be ported - We get Laravel-specific integrations / assertions
Notes:
- Current Dusk tests rely on component class naming convention for selecting items. It is more sturdy to rely on Dusk selectors https://laravel.com/docs/8.x/dusk#dusk-selectors
<button dusk="login">/$browser->click('@login')
Alternatives:
- https://pestphp.com on top of Laravel Dusk. Nice UI / ergonomics but Dusk integration is not complete, does not feel finished. See also https://www.twilio.com/blog/unit-test-laravel-api-pest-framework
- Creating tests in e2e JS testing framework (Cypress, Jest + Puppeteer)
Deployment
Problems:
- Depoloyment to master is a brittle process including announcements, timing the deployments to off-peak hours, weekends etc
- No easy way to preview the PRs
- UIs do not sumbit temporary downtime (form composing and submissions)
- We need zero-downtime or minimal-downtime deployment
- UI's should support auto-save drafts / stored input fields
Technical Solutions:
❓ Forge
❓ Digital Ocean apps
❓ Render
Notes:
- There is no clear winner, it needs to be evaluated
Images
https://www.smashingmagazine.com/2021/04/humble-img-element-core-web-vitals/
https://imageengine.io/
https://imagekit.io/
https://github.com/imagekit-developer/imagekit-vuejs
🚧 TODO
Models
🚧 TODO
Auth / Roles
🚧 TODO
Mailables
https://github.com/beyondcode/helo-laravel
https://beyondco.de/software/helo
🚧 TODO
Debugging
🚧 TODO
Ads
🚧 TODO
https://paramdeo.com/blog/opting-your-website-out-of-googles-floc-network
https://plausible.io/blog/google-floc