Front-End Technical Vision
The following document is a guide for all future Magento front-end applications outside of core, for which we should be mindful of the following values:
- Productivity (Efficiency)
- Quality (Reliability)
Portability, Performance, Productivity, Quality, Internationalization.
React's continued growth and popularity coupled with its solid documentation make it an excellent choice for building user interfaces. If written appropriately, it enables portability by crossing over into native applications with React Native.
Performance is easy to achieve with React, because it only re-renders DOM elements where and when necessary. That's not to say that React prevents you from creating performance problems, but the docs do well at explaining what to avoid and how to profile.
Creating a new React project has never been easier with CRA, which comes out-of-the-box with hot reloading. This increases productivity by giving developers short, positive feedback loops. Hot reloading is also achievable in React Native. Another opportunity for short, positive feedback loops is testing with Jest and Enzyme. Tests are fastest when writing unit tests with the Shallow Rendering API and reserving the Full Rendering API for integration tests. The better the development experience in these cycles, the better quality we achieve as a result. Jest's snapshot testing is another way to ensure quality in that we don't inadvertently introduce breaking changes.
- Create a new React project with CRA.
- Redux as a predictable state container.
- Internationalization with react-intl.
- Warning: the documented path here is to couple the components to this library. This will be fine for most projects, but if ultimate portability is required, you will need to decouple the component from the i18n library.
Maintainability, Productivity, Quality, Consistency.
Types and interfaces are only a compile-time construct and have no effect on the generated code.
Catching errors at compile time also increases productivity, because we don't have to run the development server to see the errors. In fact, we can see them directly in the editor before anything is run. Additionally, Microsoft has open sourced the TypeScript Language Service API, which is used across the most popular editors of today. As a result, you'll see consistent errors between these editors.
Type definitions are provided for many of the most popular npm packages, meaning developers can increase productivity by staying in-editor instead of constantly task switching and looking up documentation online. Even internally, there is less need to open a local file when you can extract most of the relevant information you need via Intellisense.
- Adding TypeScript to CRA.
- Code consistency is enforced via configuration, linting with TSLint and formatting with Prettier.
- Use the most strict tsconfig rules before you write a single line of code, because it's much harder to introduce these rules later in a project.
tslint-config-prettierto ensure there is no overlap between TSLint and Prettier.
tslint-recommendedas a starting point. Introduce new rules with extreme hesitation to prevent bikeshedding over trivial and subjective preferences.
husky, ensure errors are caught before CI with a
pretty-quickpre-commit hook and a pre-push hook for linting.
- Generate TypeScript declarations for CSS Modules via css-modules-typescript-loader.
- Documentation via TSDoc.
On top of sharing code between different environments, we should also be concerned about sharing code between projects. For this, we should introduce a business logic repository that includes common helper functions – logic that we're likely to use between projects.
Business Logic Repository
- Written and documented in TypeScript.
- Semantic versioning to ensure that progress can be made without breaking things for existing - consumers.
- 100% unit test coverage via Jest for consistency.
All users should have a consistent user experience. For the best performance, those with the latest browsers should not be penalized by incurring an additional payload hit than those with older browsers.
There are various ways to achieve this goal; however, an in-house approach might be warranted to prevent the stability issues of relying on 3rd party resources. One idea would be to publish multiple build targets, tailored to various environments.
React UI Component Library
Consistency, Productivity, Scalability, Maintainability, Accessibility.
We should lean against downloading various UI components from different sources for the following reasons:
- Inconsistent implementations, documentation, theming and customization.
- Limited accessibility and support.
If you have the budget to pay for a product, it might be a good choice in this space. Why? Because it's much better to get all of your components from a single source than to have completely different paradigms scattered everywhere.
Disclaimer: there may be licensing limitations that prevent an open-source product from implementing a paid-for product.
Downloading a 3rd-party package
There are times when you may consider downloading a 3rd party package (e.g., a component). When this happens, consider the following criteria before making a final choice:
- First thing's first – what is the license?
- Is it open source?
- You may need to reach out to your legal department if things are a bit blurry.
- Does the package have a bright future?
- Popularity – are there a significant number of weekly downloads?
- Is the downloads line graph going up or down?
- Look for tests, ideally with 100% test coverage.
- Look at the bundle size with Bundle Phobia.
- Does it have good/clear documentation?
- Is it currently maintained?
- Look at the number of issues vs. pull requests.
- How long have these issues and PRs been open?
- When was the last comment made on them and by whom?
- Reliability – how serious are the issues?
- Search and compare this package with other similar packages to gauge which package is the best choice and feel free to reach out to other team members for guidance.
The coupling here is a bit unfortunate for some projects (e.g., libraries), but pretty standard for applications. For ultimate portability, reusable components should be provided their styles externally.
Quality, Maintainability, Productivity.
We should leverage the built-in code coverage reports that Jest provides, but also the following GitHub integrations/apps:
- Continuous integration with Travis-CI.
- Quality by Code Climate provides automated code review for test coverage, maintainability and more so that you can save time and merge with confidence.
- Code Climate’s engineering process insights and automated code review for GitHub and GitHub Enterprise help you ship better software, faster.
Ideally, for each front-end project, there will be a separate project that covers both performance and critical-path testing. This project is separate so that it doesn't cripple the short feedback loops of feature development. Additionally, we would do well to have additional performance testing around the most commonly used components (e.g., used in 3+ places).