# Motley Migration Dev Notes
## Possible Approaches
- 100% TS / Vue
- HTTP Requests
- Generated TS Client
- 100% Blazor
- Server Side
- Client Side
- Server/Client Hybrid with Pre-Rendering
- ~~WASM~~ (Probably not the move, for our needs.)
- ~~HTTP Requests~~ (Probably an anti-pattern that's not worth pursuing.)
- C# `WebApi.Client`
- Hybrid
- Blazor App that renders Vue components
- Vue App that renders Blazor components
- ASP.NET Web API with Vue SPA
- ~~100% Rust *(Gosh, I Wish)*~~
- ~~Replace all of our backend apps in Rocket~~
- ~~Replace all of our client apps with stdweb & React~~
- ~~Replace all of our desktop apps with Tauri w/ Rust & React~~
## Composition of a modern web-app
- Components
- (*) Lifecycle
- Vue.js: [Lifecycle Hooks](https://v3.vuejs.org/api/options-lifecycle-hooks.html)
- Blazor: [ASP.NET Core Razor component lifecycle](https://docs.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-6.0)
- DOM Events: (for instance: `onClick=(evt) => handleClick(evt)`)
- Vue.js: [Events](https://v3.vuejs.org/guide/events.html)
- **A LOT** more options available here
- Blazor: [ASP.NET Core Blazor event handling](https://docs.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-6.0)
- (*) Custom Component Events: (for instance: `emit("form:submitted")`)
- Vue.js: [Custom Events](https://v3.vuejs.org/guide/component-custom-events.html#event-names)
- Blazor: **NOTHING** (other than manually writing some very clever C# & Blazor work-around)
- Composability (Reusable Components)
- Vue.js: [Slots](https://v3.vuejs.org/guide/component-slots.html)
- **A LOT** more options available here
- Blazor: **?????** (Nothing yet, other than component hierarchy, I think.)
- Data Binding
- Vue: [Value Bindings](https://v3.vuejs.org/guide/forms.html#value-bindings)
- **A LOT** more options available here
- Blazor: [ASP.NET Core Blazor data binding](https://docs.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-6.0)
- Dynamic Routes
- Vue.js: (officially supported) [vue-router-next](https://github.com/vuejs/vue-router-next)
- Blazor: (native) [ASP.NET Core Blazor routing and navigation](https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-6.0)
- Forms
- Vue.js: [(Basic) Form Input Bindings](https://v3.vuejs.org/guide/forms.html)
- **A LOT** more options available here
- Blazor: [Forms & Validation](https://docs.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-6.0)
- (*) State-management
- Vue.js
- (typesafe) [Pinia](https://pinia.esm.dev/)
- [Vuex](https://vuex.vuejs.org/)
- [ASP.NET Core Blazor State Management](https://docs.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-6.0&pivots=server)
- Testing / Testability
- [Vue.js](https://v3.vuejs.org/guide/testing.html#introduction)
- Unit
- Jest (w/ optional Vue plugin)
- Mocha (w/ optional Vue plugin)
- Component
- Vue Testing Library
- E2E
- Cypress
- Nightwatch.js
- Puppeteer
- TestCafe
- [Blazor](https://docs.microsoft.com/en-us/aspnet/core/blazor/test?view=aspnetcore-6.0)
- Component: **Nothing for component-specific testing... must use unit or E2E to test components**
- Unit
- [bUnit](https://github.com/egil/bUnit)
- E2E
- [Playwright](https://playwright.dev/dotnet/)
- Dependencies
- Complication: breaking changes in primary API—how reliant do we want our frontend to be on our backend?
```jsx
<SplitComponent
left={SomeComponent}
right={SomeComponent}
isLeftShown={fn () => true}
/>
```
## Comparing Vue vs. Blazor
- Support
- Both are open-source frameworks. As such, the open-source community surrounding each framework mainly drives the features & flexibility available.
- [Vue on GitHub](https://github.com/vuejs/vue): 191k Stars, 30.8k Forks, 6.2k watchers
- Note: this is literally more stars than [React, which just passed jQuery as the most commonly used web framework](https://github.com/dotnet/aspnetcore) (which @chazkiker was personally shocked to see...)
- [Blazor on GitHub](https://github.com/dotnet/blazor): 9.3k Stars, 687 Forks, 677 Watchers
- *Note:* Blazor was moved to ASP.NET Core—so... it is possible these numbers are lower than they would be. So... let's look at ASP.NET Core's GH stats
- [aspnetcore on GitHub](https://github.com/dotnet/aspnetcore): 26.7k Stars, 7.2k Forks, 1.5k Watchers
- Fun fact: [Vue.js and ASP.NET core are neck-and-neck in the Stack Overflow "most commmonly used web framework" list from 2021](https://insights.stackoverflow.com/survey/2021#section-most-popular-technologies-web-frameworks). Vue wins in "All Respondents" whereas ASP.NET Core wins in the "Professional Developers" category
- Take-aways: Vue has FAR more support than Blazor. As far as a frontend goes, that means:
- Better / more cohesive documentation
- Better developer support (debugging, tooling, IDE extentions/support, testing options, etc.)
- Much of Blazor's tooling is specific to Visual Studio whereas Vue's tooling includes a very wide array of choices.
- More options as far as 3rd party libraries (***including UI libraries***) are concerned
- This is a BIG point to Vue... I don't know about y'all but @chazkiker does not enjoy writing CSS
- Ecosystem
- Vue.js is a JavaScript/TypeScript library
- Blazor is a .NET Framework
- Server-side and client-side code has access to the large ecosystem of .NET.
- .NET itself is a mature and widely supported ecosystem, and this point is easily the most important strength for Blazor
- CommerceTech's entire backend foundation **is** C#, which is the reason that merits this conversation in the first place
- Maturity
- Vue.JS
- Vue is on it's *third* major version
- Vue is very much production-ready.
- Blazor just recently (as of later 2021) crossed the threshold of being considered "production-ready."
- .NET itself is very much mature, but Blazor is definitely not *yet*... it *will* get there eventually... (More on this in the "Future" section)
- Interoperability (with CommerceTech backend)
- Blazor is undoubtedly the winner on this front.
- Vue can interact with our backend in a few differnet ways... but there are some pain-points.
- Similarities
- Component-based Web frameworks
- Scoped CSS (or other styling pre-processors): Add CSS (or other styling pre-processors) to your component without fear of affecting other components or pages.
- Future
- Though Blazor is young and immature, its future has some truly exciting aspects.
- WASM will continue to grow and mature. (WASM is also really cool.) And Blazor could very likely be the first widely-adopted client web framework to (1) actually compete with JS and (2) make use of WASM. (Though of course @chazkiker would rather Rust take that crown... but the community of Rustaceans is smaller than ASP.NET Core albeit way cooler :wink:)
- Vue.js... just as any big JS framework, Vue is likely going to be around for a while. Even when it's not the "cool kid on the JS block" (which is currently [Svelte](https://svelte.dev/), as fate would have it), Vue will be around, supported, and actively iterated upon. (If ya doubt this statement... just take a look at jQuery which had its last stable release merely nine months ago.)
- Given, it probably won't do cool stuff with WASM
- Learning Curve
- Vue JS:
- Really quite simple. It's actually often considered the "easiest" JS web framework among most modern frontend web developers these days.
- (In fact, before working at TMF @chazkiker actually incorrectly considered Vue to be a more limited framework because of how simple it was considered to be... turns out it's just a well-crafted framework :smile:.)
- Lots of options for how to do it. (In fact, quite a lot more than anything I've seen before. SFC's, TS/JS, Setup scripts vs regular scripts... super dope.)
- Super wonderful TypeScript compatibility (& Vue is written in TypeScript, so no wonder.)
- Docs are amazing
- Popularity means there's a LOT of examples out there—tutorials, articles, sample apps... beyond the official documentation.
- TMF widely makes use of Vue, which means other developers can come in and get ramped up in our client app VERY easily.
- Blazor
- If ya know C# / .NET: pretty easy to get up and running. (It's kinda the whole point of the framework.)
- If ya don't know C# / .NET... good luck! Such a framework is going to feel incredibly foreign to most anybody who's walking in with experience exclusively in the frontend web app ecosystem.
- Between the two...
- If you can write C# code... Vue will truly be a breeze to learn.
## Rubric
| Factor | Weight | Vue.js | Blazor |
| ------------------------------------------------ | ------ | ------ | ------ |
| Performance | 5 | 4 | 4 |
| Production-ready | 5 | 5 | 2 |
| Support | 1 | 5 | 1 |
| Frontend 3rd Party Libraries (non-UI) | 3 | 5 | 2 |
| Backend 3rd Party Libraries | 1 | 0 | 5 |
| UI Libraries | 5 | 5 | 3 |
| Interoperability with commerce-api | 5 | 4 | 5 |
| Stability | 4 | 4 | 2 |
| Learning curve (commerce-tech) | 1 | 3 | 5 |
| Learning curve (everyone else) | 1 | 5 | 1 |
| State management | 1 | 5 | 1 |
| Dev tools | 3 | 5 | 3 |
| Maintainability | 5 | | |
| DataDog / Sentry Support | 4 | | |
| Foolish Accessibility (other Fools can help out) | 3 | | |
| IDE Support | 3 | | |
| Total | | 154 | 106 |
### Inspiration
- [C# vs Java](https://www.ideamotive.co/blog/c-sharp-vs-java-which-is-better-for-building-your-product)
- [RoR vs Django](https://medium.com/@kday_88464/make-technology-decisions-in-5-easy-steps-da6123d2e23a)
## PoC — Complicated Use Case
Complicated frontend pages usually consist of a page with the following elements:
- a form
- multiple API/backend requests
- even more so if it's multiple "GET"s with any given "POST" which changes the data that would show up in relevant "GET"s
- state management
- often complicated with forms
- made even harder with additional state which depends on what type of user is visiting
- this is most often intertwined with the API requests relevant to the page
- routing to a separate page or "view"
- data tables with filters/sorting
Some relevant examples:
- ("simple" complicated page) Product Admin
- (complicated) Promo Search
- (complicated, mixed GET and POST) edit product
## Vue.js: Exploring Possible Approaches
If we were to use Vue.js, there are a few different approaches we could take:
- Independent Vue.js
- with HTTP Requests
- with Generated API Client
- with manual TypeScript API Client
- Hybrid Vue.js with ASP.NET Core Web App
- Custom Controllers
- Exposing functionality via WebApi.Client
## API Client Generation
Please refer to this article for some interesting notes: [Six Ways to Marry C# with TypeScript](https://alex-klaus.com/marry-csharp-typescript/)
## Active Experimental Branches & Repos
- [feature/blazor-webapp](https://github.com/themotleyfool/commerce-api/tree/feature/blazor-webapp)
## Motley Pages to be Migrated
- [/Shop/Products/EditProduct.aspx](https://staging.admin.fool.com/Shop/Products/EditProduct.aspx)
- [CMT-359](https://fool.atlassian.net/browse/CMT-359)
- [/Product/Manage/?productId=3902](https://staging.admin.fool.com/Product/Manage/?productId=3902)
- [CMT-361](https://fool.atlassian.net/browse/CMT-361)
- [/shop/promotions/batchcomp.aspx?pid=76174](https://staging.admin.fool.com/shop/promotions/batchcomp.aspx?pid=76174)
- [CMT-345](https://fool.atlassian.net/browse/CMT-345)
- [/OrderHistory/ReactivateSingleItem.aspx](https://staging.admin.fool.com/Accounts/OrderHistory/ReactivateSingleItem.aspx?piid=17958983)
- [CMT-336](https://fool.atlassian.net/browse/CMT-336)
- [/OrderHistory/RefundSingleItem.aspx](https://staging.admin.fool.com/Accounts/OrderHistory/RefundSingleItem.aspx?piid=15625241)
- [CMT-335](https://fool.atlassian.net/browse/CMT-335)
- [/OrderHistory/CancelSingleItem.aspx](https://staging.admin.fool.com/Accounts/OrderHistory/CancelSingleItem.aspx?piid=15625241)
- [CMT-334](https://fool.atlassian.net/browse/CMT-334)
- [/OrderHistory/ExtendSubscription.aspx](https://staging.admin.fool.com/Accounts/OrderHistory/ExtendSubscription.aspx?sid=9784817)
- [CMT-68](https://fool.atlassian.net/browse/CMT-68)
- [/OrderHistory/SingleItemDetail.aspx](https://staging.admin.fool.com/Accounts/OrderHistory/SingleItemDetail.aspx?piid=15625241)
- [CMT-333](https://fool.atlassian.net/browse/CMT-333)
## Further Reading
- [Blazor vs Angular vs React vs Vue](https://www.angularminds.com/blog/article/comparison-between-blazor-vs-angular-vs-react-vs-vue.html)
- [Awesome Blazor](https://github.com/AdrienTorris/awesome-blazor)
- [Six Ways to Marry C# with TypeScript](https://alex-klaus.com/marry-csharp-typescript/)
- [Generate TS/C# Clients with NSwag](https://blog.logrocket.com/generate-typescript-csharp-clients-nswag-api/)
## Expectations for Interop b/w Blazor & CommerceAPI
- Blazor frontend should exclusively talk to commerce-api via the `Fool.Commerce.WebApi.Client`
- `CommerceException` type should be mapped to native `SpecificException` from commerce-api with a base `CommerceServiceException` to catch any unknown errors
- for instance, take a look at the following code
```csharp
CommerceClient = await ApiClient.EnterAsync(apingConfiguration, requestSettings);
ProductDescription? product = null;
try
{
product = CommerceClient.ProductServiceAsync.GetSubscriptionProduct(id);
}
catch (ProductNotFoundException)
{
// `ProductNotFoundException` should be thrown when API cannot find a subscription
// product with the given ID
}
catch (CommerceException ex)
{
// base `CommerceException` should happen when an unknown/unexpected exception type is thrown
}
```