How would I start a new frontend project in 2022? By frontend project, I really mean a single page web application that talks to an API of some sort via HTTP (whether that API is RESTful, GraphQL, JSON-RPC, or something else entirely).
First of all, I would try not to. That's the subject of a different article, however. Let's assume that we're already past the point of deciding whether or not we should.
In fact, let's make some assumptions about what we're building:
- We want to rapidly reach minimal viable product (MVP) status with one or two engineers.
- The project will live for at least a decade.
- We eventually want to scale out the code base beyond more than one team of engineers.
- The founders will eventually move out of engineering roles and someone will have to backfill them.
If you don't share these assumptions, then I would just say use whatever you are most familiar and comfortable with for rapidly building something and then throw it away when you're done.
Use Webpack, Babel, and PostCSS. Learn how to write your own Webpack configuration and stick close to the defaults. ESLint everything. Pick an autoformatter like Prettier and use it everywhere.
Set up a development proxy for your bundler (e.g. webpack-dev-server) and make it easy to point it at any instance of your API so your frontend developers don't have to run the full stack. This will make it easier to reproduce production bugs (just point your development setup to the production API and load an example).
Similarly, CSS-in-JS and SASS or LESS like superset languages come and go. Most CSS-in-JS solutions are also sadly underspecified. Focus instead on mastering CSS Grid and Flexbox based layouts and CSS variables before investing into tooling. Consider sticking to plain CSS using a convention like Block Element Modifier (BEM) instead of getting caught up with trying to automatically scope your CSS. If you must use something, SASS is well-specified and has many quality implementations.
Stick to low fidelity mockups for your early stage work. Avoid tools that encourage high fidelity mockups that will eat up everyone's time.
Instead, invest in your continuous integration (CI) setup. It should be easy to push working examples of new features for anyone to review. It should be so easy that you can deploy a few alternative examples during a meeting and tear down the losers afterwards.
You need to build a design system.
As you mock up your user interface (UI), look for common user experience (UX) patterns and design reusable components around them. These are the building blocks of your design system.
Focus on building these components out as Storybook components. If you're using React, use contexts, CSS variables, and naming conventions to provide theming support. Most importantly, only implement the functionality you need -- don't spend time generalizing.
You want to build features, not frameworks. Sometimes you're also better off deprecating and replacing components in your design system as it matures. Early generalization of your design system is a waste of time.
Avoid frameworks built on top of frameworks. These are for quickly building one-off projects, and you want to build something that will last at least a decade.
Any asynchronous functions in your data access layer should support cancellation. Currently that looks like using AbortSignal and passing an instance into the function. If your function signatures have a consistent design, then you can always create a convenience layer at some later point for your component framework (i.e. using RxJS for Angular or custom hooks for React).
If you do use a state management library, focus on using it consistently throughout your business logic layer. Compose this with your UI components and try to keep them focused on presentation rather than behavior.
Does your application have a need to be embedded inside of other web pages and browsing contexts? If not, don't allow it.
Design your application with authentication in mind. It should be immediately obvious when your session has expired and possible to reauthenticate without losing your existing page state.
Watch out for any mechanism that could be used to control redirects or inject content via query parameters and path elements.
Don't try to sanitize user input using regular expressions. If you can't render into a sandboxed iframe with no origin, then either fully escape user input or parse it and safely generate an escaped version from the parsed structure.
Regularly vet your dependencies and maintain your own NPM registry mirror.
As you build out your initial application, there may be multiple pivots. Buying into too many layers of tooling or dependencies can quickly cripple your ability to swap out ideas and rewrite portions of your code. Instead of working on your application, you'll be working on updating dependencies.
Keeping it simple let's you focus on your problem. The first few months will take longer, but as you grow a reusable design system, you will speed up without the usual caveats that come with using someone else's.
Great projects never end. These are the prescriptions I would give myself if I were trying to start a new frontend project in 2022, but they're just for the beginning. Regularly take the time to reflect on your decisions and update your choices accordingly.
Finally, don't be afraid to ignore every suggestion here to quickly stand up rapid prototypes that you throw away. This is where convenience libraries, webpack project wrappers, and frameworks built on other frameworks can be extremely useful, because once you've proven out an idea, you can throw away all the cruft with the original prototype. The easier the code is to delete, the more adventurous you should be.