A common problem
Web apps have come a long way since their initial appearance. We all now know how powerful JavaScript on the web is, and how many endless possibilities exist in terms of framework and technology choices. Different frameworks have their pros and cons, but some core methodologies can be applied to almost every framework. Tools such as create-react-app, next.js, vue-cli, etc., are really helpful for bootstrapping a project and its structure, but after that, you're free to form an application to your preferences and project's requirements.
I've collected some principles I found valuable when building web applications with React and Vue that can help you in defining a direction and keeping things tidy and sound. Most of the principles can be applied to all software, but this list is a bit specific to web apps.
Principles
-
Developing components, not screens
- try to encapsulate all the logic of a component in isolation, so it can be rendered everywhere with ease, for example, in different screens and sections
- all the CRUD operations go inside the controllers / providers for the data it needs, and that data is passed to presentational components
- one common scenario is redux/vuex - data is persisted to a store and is treated as a single source of truth, and container components extract the relevant data
-
Separating presentational and business / controller layer
- not all components need to be connected to stores, backend API or some other service
- by making components "data source agnostic", reusability is greatly increased
-
Using a standardized way of fetching the data
- rest-hooks is a great example of this principle as it encourages a predictable and readable structure for API calls
- for some projects, using explicit
fetch
calls may be sufficient, but if you're dealing with a lot of resources and relationships, having an abstraction over backend API can be helpful
-
Having a common user input strategy
- forms, select tags, validations, error states all fall into this category
- UI component libraries such as antd provide a solution for this out of the box
- if you're creating an app without a UI library, consider putting a bit more emphasis on standardizing these elements for better UX
-
Writing automated tests
- components are, in my experience, best tested with integration tests, specifically with Cypress
- business logic should be thoroughly covered with unit tests
- e2e are valuable for smoke testing larger user flows; they can help detect regressions between the client and the API
-
Using storybook for creating reusable components
- https://storybook.js.org/
- great way to collaborate with designers and discuss functionality
- serves as a "living style guide" for your app
-
Using linters and formatters
- examples of linters: ESLint, stylelint
- most of the bootstrap tools such as create-react-app pre-install linters for you, but if you're on a legacy codebase, they might not be applied
- they can help you catch bugs, but they can also be used in defining code style for your team — this can help in reducing mental load when developing upon a feature that you've inherited from your colleague
- sonarJS eslint plugin can help improve code quality as it checks for logical structure
- prettier is an awesome code formatter that you set up only once, and never think about it again — very useful when working in a team
-
Avoiding global styles
- overrides and resets can be made global
- CSS modules or CSS-in-JS are some of the technologies that can help in achieving scoped, isolated styles
- local styles can often lead to better component reusability
-
Using structured version control
- using a branching model
- e.g. gitflow — "a branching model for Git, created by Vincent Driessen"
- having a structure in your version control is indispensable for working in a team, but it is helpful even when working on your own
- linting commit messages - commitlint
- useful in creating a changelog and finding bugs as the project develops
- angular's commit message rules are often applicable to any software project, and commitlint can help you in keeping those messages consistent with the ruleset
- using a branching model
-
Keeping a changelog
- on the beginning of every project, it's usually easy to keep track of all the changes in your mental context
- as the project grows, the changelog can serve as a central place for discovering notable changes to a codebase, even months and years into development
The never-ending list
That's all folks! There could surely be many more items added to the list, depending on the project domain and technology, but I find these can improve many frontend apps radically. Almost all of the principles can be applied progressively and by priority defined by you and your team, so no need to worry of applying them all of once.
What principles do you find super important when creating web apps? Share these below in the comments! ⬇️
Thanks for reading. 🙏
Top comments (10)
Great article!
I also can add some more principles from Vercel's CTO:
1: Tear down the barriers
2: Make it east to delete code
3: Migrate incrementally
4: Always get better, never get worse
5: Embrace lack of knowledge
6: Eliminate systematic complexity
Great article Renato!
Thank you, Peter! Glad you liked it :)
This is awesome. Thanks for sharing!
Thank you Francesco!
Great article and a solid set of tips for starting out projects!
Thank you, Liran, I appreciate it!
Great, I think cypress is meant to be used in e2e testing not integration, would do you think?
Hello Mahmoud! 👋
I think Cypress is so versatile that you could actually use it for unit, integration and e2e altogether. For example, they have a section about unit testing in the docs -> docs.cypress.io/examples/examples/...
I believe it's also suited for integration tests. In terms of web apps, integration tests don't have a stric definition what they consist of. For example, an integration test could be a storybook story with cypress network mocks, but it's also amazing for e2e. Unit testing is feasible, but I still prefer Jest for that.
What do you use for unit and integration?
Hi Renato
I got you, I'm using Jest for both Unit and Integration testing and cypress for e2e, but now I may try to use cypress in integration testing as well!
Thanks