The Best Complex Frontend Architecture: What You Need to Know About Feature-Sliced Design

Written by mmmidas | Published 2024/01/18
Tech Story Tags: javascript | react | frontend | architecture | typescript | it | webdev | feature-sliced-design

TLDRThis article discusses the Feature-Sliced Design architecture, as, in my opinion, it is the best among the available options. It also explores the idea of FSD and the problems this architectural methodology solves. via the TL;DR App

Introduction

Frontend developers often face a problem related to application architecture. It requires the use of an architecture that can easily scale and provide loose coupling and high cohesion between application modules.

This article discusses the Feature-Sliced Design architecture, as, in my opinion, it is the best among the available options. It also explores the idea of FSD and the problems this architectural methodology solves.

We will compare FSD with classical and modular architectures and examine their pros and cons.

First and foremost, let's distinguish three concepts: layer, slice, and segment.

Layers

Layers are top-level directories and the first level of application decomposition. They are limited in number - a maximum of 7 layers - and standardized, although some of them are optional.

Currently, the following layers are distinguished:

Each layer has its own zone of responsibility and is business-oriented. Let's consider each layer separately.

  • app: This is where the application logic is initialized. Providers, routers, global styles, global type declarations, etc. are defined here. It serves as the entry point for the application.

  • processes: This layer handles processes that span across multiple pages, such as multistep registration. This layer is considered deprecated but can still be occasionally encountered. It is an optional layer.

  • pages: This layer includes the application's pages.

  • widgets: These are standalone UI components used on pages.

  • features: This layer deals with user scenarios and functionality that carries business value. For example, likes, writing reviews, rating products, etc. It is an optional layer.

  • entities: This layer represents business entities. These entities can include users, reviews, comments, etc. It is an optional layer.

  • shared: This layer contains reusable components and utilities that are not tied to specific business logic. It includes a UI kit, Axios configuration, application configuration, helpers that are not bound to business logic, etc.

These layers help organize the codebase and promote a modular, maintainable, and scalable architecture.

One of the key features of Feature-Sliced Design is its hierarchical structure. In this structure, entities cannot use functionality from features because features are higher in the hierarchy.

Similarly, features cannot use components from widgets or processes, as the layers above can only utilize the layers below. This is done to maintain a linear flow that is directed only in one direction. The lower a layer is positioned in the hierarchy, the riskier it is to make changes to it since it is likely to be used in more places in the code. For example, the UI kit in the shared layer is used in the features, widgets, and even page layers.

Slices

In each of the layers, there are subdirectories - slices—the second level of application decomposition. In slices, the connection is not to abstract things but to specific business entities. The main goal of slices is to group code by its value.

Slice names are not standardized, as they are directly determined by the business area of the project. For example, in a photo gallery, there may be sections like photo, album, and gallery. A social network would require slices like posts, users, and newsfeeds.

Closely related fragments can be structurally grouped in a directory, but they must adhere to the same isolation rules as other slices - there should be no shared access to the code in this directory.

Segments

Each slice consists of segments. Segments help to divide the code within a slice based on its purpose. Depending on the team's agreements, segments can change in composition and naming. The following segments are more commonly used:

  • api - necessary server requests.

  • UI - UI components of the slice.

  • model - Business logic, i.e., interaction with the state. For example, actions and selectors.
  • lib - auxiliary functionality used within the slice.

  • config - necessary configuration of the slice, but the config segment is rarely encountered.

  • consts - necessary constants.

Public API

Each slice and segment has a Public API. The Public API is represented by an index.js or index.ts file, which allows extracting only the necessary functionality from the slice or segment to the outside and isolating unnecessary functionality. The index file serves as an entry point.

Rules for the Public API:

  • Application slices and segments use only the functionality and components of the slice that are defined in the Public API index file.

  • The internal part of the slice or segment that is not defined in the Public API is considered isolated and only open for access within the slice or segment itself.

The Public API simplifies working with import and export, so when making changes to the application, there is no need to change imports everywhere in the code.

Deeper Into Architecture

Abstraction and Business Logic

The higher the layer, the more it is tied to the specific business node and the more business logic it contains. The lower the layer, the more abstractions, reusability, and lack of autonomy in the layer.

How Does FSD Solve the Problem?

One of the tasks of Feature-Sliced Design is to achieve loose coupling and high cohesion. It is important to understand how FSD achieves this result.

In OOP, these problems have long been solved through concepts such as polymorphism, encapsulation, inheritance, and abstraction. These concepts ensure isolation, reusability, and versatility of code, where different results are obtained depending on how a component or functionality is used.

Feature-Sliced Design helps apply these principles in the frontend.

Abstraction and polymorphism are achieved through layers. Since the lower layers are abstract, they can be reused in higher layers, and depending on the conditions, a component or functionality can work differently based on the specified parameters or props.

Encapsulation is achieved through the Public API, which isolates what is not needed from the outside in slices and segments. Access to the inner segments of a slice is restricted, and the Public API is the only way to access functionality and components from a slice or segment.

Inheritance is also achieved through layers, as higher layers can reuse lower layers.

Comparison With the Classic Architecture

I believe you have come across classic architecture many times. Most authors use it in educational articles and YouTube videos due to its simplicity. There is no specific standard for classical architecture. However, often you can see the following format:

The classic architecture has noticeable drawbacks. The biggest one is that the project becomes difficult to maintain due to implicit connections between components and module clutter. The drawbacks of the classic architecture become more apparent over time. The longer the project evolves, the more the application architecture becomes a tangled mess that is difficult to unravel.

The classic architecture is suitable for small projects without ongoing maintenance or pet projects.

Feature-Sliced Design, thanks to its concepts and standards, prevents the problems of classic architecture.

However, the level of understanding and skills of developers working with FSD should be higher than when working with classic architecture. Usually, developers with less than 2 years of experience have not heard of FSD.

However, when working with Feature-Sliced Design, problems need to be addressed "now" rather than "later." Issues in the code and deviations from the concepts become immediately apparent

Comparison With Simple Modular Architecture

Simple modular architecture has several drawbacks:

  • Sometimes it is unclear where to put functionality into modules or components.

  • Difficulties in using modules within another module.

  • Issues with storing business entities.

  • Implicit dependencies in global functions, leading to a tangled structure.

It seems that in any complex or moderately complex projects, Feature-Sliced Design should be preferred over simple modular architecture. FSD solves many fundamental architectural problems and has few drawbacks.

In terms of simplicity and development speed, a simple modular architecture may have an advantage over FSD. If an MVP is needed or a short-lived project is being developed, a simple modular architecture may be more suitable than FSD. But in any other case, a feature-sliced design looks preferable.

The Potential of Feature-Sliced Design

FSD is a young architectural methodology. However, it is already being used by many banking, fintech, B2B, e-commerce companies and others. Here is a link to the GitHub issue with a list of companies: GitHub Issue.

The GitHub repository with the official FSD documentation had more than 1.1k stars at the time of publishing this article. The documentation is actively being expanded, and the FSD development team and community in Telegram and Discord are available 24/7 to help people with architecture-related questions.

The potential of this architecture is highly regarded, and its usage is widely spread among large companies worldwide. With proper adoption, FSD has the potential to become the dominant architectural solution in the field of frontend development.

Advantages and Disadvantages of Architecture

Advantages

  • Architecture components can be easily replaced, added, or removed

  • Standardization of architecture

  • Scalability

  • The methodology is independent of the development stack.

  • Controlled and explicit connections between modules without unexpected side effects.

  • Business-oriented architectural methodology.

Disadvantages

  • A higher entry barrier compared to many other architectural solutions.

  • Requires awareness, team culture, and adherence to concepts.

  • Challenges and issues need to be addressed immediately, rather than later. Code problems and deviations from concepts are immediately visible. However, this can also be seen as an advantage.

Conclusion

Feature-Sliced Design is an interesting and valuable discovery that frontend developers should know and be able to use. FSD can provide teams with a flexible, standardized, and scalable architecture and development culture. However, utilizing the positive aspects of the methodology requires knowledge, awareness, and discipline within the team.

FSD stands out among other architectures due to its clear business orientation, entity definition, functional composition, and components composition of the application.

You can also independently explore examples of FSD usage in projects and the official Feature-Sliced Design documentation:

Official Documentation

Example. GitHub Client

Example. Nike Sneaker and Footwear Store

Example. Sudoku

This post may be long, but I hope you have learned something new. I appreciate that you have finished reading this post.

If you have any thoughts or questions, feel free to leave a comment!


Also published here


Written by mmmidas | 21 y.o. front-end developer with a special love for learning and creating
Published by HackerNoon on 2024/01/18