This repository was created from scratch as part of the UlbiTV's course "To production on React".
- Install pnpm
pnpm install
- install dependenciespnpm start
orpnpm start:dev:vite
- launch server + frontend project in dev mode
pnpm start
- Launch frontend project on webpack dev server + backendpnpm storybook
- Launch Storybookpnpm start:dev:vite
- Launch frontend project on vite + backendpnpm start:dev:client
- Launch frontend project on webpack dev serverpnpm start:dev:vite:client
- Launch frontend project on vitepnpm start:dev:server
- Launch backend serverpnpm build:prod
- Build in prod modepnpm build:dev
- Build in dev mode (not minimized)pnpm build:prod:analyze
- Build in prod mode and open bundle analyzerpnpm build:storybook
- Build storybookpnpm lint:ts
- Check ts files with linterpnpm lint:ts:fix
- Fix ts files with linterpnpm lint:scss
- Check scss files with style linterpnpm lint:scss:fix
- Fix scss files with style linterpnpm test:unit
- Run unit tests with jestpnpm test:ui
- Run screenshot tests with lokipnpm test:ui:ok
- Confirm new screenshotspnpm test:ui:ci
- Run screenshot tests in CIpnpm test:ui:report
- Generate full report for screenshot testspnpm test:ui:report:chrome
- Generate full report for screenshot tests and open it in Chromepnpm test:ui:report:arc
- Generate full report for screenshot tests and open it in Arcpnpm test:ui:json
- Generate json report for screenshot testspnpm test:ui:html
- Generate HTML report for screenshot testspnpm generate:slice
- Script for generating FSD slices,pnpm prepare
- Pre-commit hookspnpm rename:slice
- Script for renaming FSD slices, Takes 3 arguments: 1. layer, 2. old slice name, 3. new slice name.pnpm rename:folder
- Script for renaming folders. Takes 3 arguments: 1. pathToFolder, 2. old name, 3. new name.pnpm remove:feature
- Removes feature using feature flag name, and state on/off (read more about feature flags here)pnpm check:layerDocs
- Checks if README.md files in each layer in src/ are up to date with the public API. Read more herepnpm postinstall
- Apply patches after pnpm i
To improve your development experience, we recommend installing the following extensions for Visual Studio Code:
- ESLint (
dbaeumer.vscode-eslint
): Integrates ESLint into VS Code to provide linting for JavaScript and TypeScript code. - Prettier (
esbenp.prettier-vscode
): An opinionated code formatter that integrates with VS Code to automatically format your code.
You can install these extensions by searching for their names in the Extensions tab in Visual Studio Code or by using the @recommended:workspace
filter to see a list of recommended extensions.
The project is written in accordance with the Feature sliced design methodology
Link to documentation - feature sliced design
The i18next library is used in the project to work with translations. Translation files are stored in public/locales.
For comfortable work, we recommend installing a plugin for webstorm/vscode
Link to documentation - i18next
The project uses 4 types of tests:
- Regular unit tests on jest -
pnpm test:unit
- Component testing with React testing library -
pnpm test:unit
- Screenshot testing with loki
pnpm test:ui
- e2e testing with Cypress
pnpm test:e2e
More about tests - testing documentation
The project uses eslint to check typescript code, stylelint to check style files and prettier to ensure style consistency in the codebase.
Also, for strict control of the main architectural principles, we use our own eslint plugin eslint-plugin-netliukh-demian-fsd-plugin, which contains 3 rules
- path-checker - prohibits the use of absolute imports within one module. Has auto fix
- layer-imports - checks the correctness of using layers from the point of view of FSD (for example, widgets cannot be used in features and entities)
- public-api-imports - allows import from other modules only from public api. Has auto fix
pnpm lint:ts
- Check ts files with linterpnpm lint:ts:fix
- Fix ts files with linterpnpm lint:scss
- Check scss files with style linterpnpm lint:scss:fix
- Fix scss files with style linter
In the project, story cases are described for each component. Server requests are mocked using msw-storybook-addon.
The file with story cases is created next to the component with the .stories.tsx extension
You can start storybook with the command:
pnpm storybook
More about Storybook
For development, the project contains 2 configs:
- Webpack - ./config/build
- Vite - vite.config.ts
Both builders are adapted to the main features of the application.
All configuration is stored in /config
- /config/babel - babel
- /config/build - webpack configuration
- /config/jest - test environment configuration
- /config/storybook - storybook configuration
In the scripts
folder there are various scripts for refactoring/simplifying code writing/generating reports etc.
The github actions configuration is located in /.github/workflows. In ci, all types of tests are run, project and storybook build, linting.
In pre-commit hooks we check the project with lint-staged, config in /.husky.
Interaction with data is carried out using Redux Toolkit.
If possible, reusable entities must be normalized using EntityAdapter.
Requests to the server are sent using RTK query.
For asynchronous connection of reducers (to avoid bundling them together in one bundle) use useDynamicModuleLoader.
Mock service worker (msw) is used to mock requests during tests and storybook stories.
More about msw.
The use of feature flags is only allowed through the toggleFeatures helper
it takes an object with options
{
name: "feature flag name",
on: "function that will work after turning on the feature"
off: "function that will work after turning off the feature"
}
As on/off functions allowed only to use concise body arrow function (e.g. () => 1)
To automatically remove a feature, use the remove-feature.ts
script,
which takes 2 arguments
- Name of the feature flag to be removed
- State (on/off)
Feature-flags in our app are not reactive, and will not update components during the session. To apply new feature-flags user need to reload website.
Shared folder contains all shared code that can be used in any part of the app and that is not related to any particular entity.
Reusable parts that are related to particular entity. They are later merged into meaningful blocks in widgets.
- Article: reusable article related components and functionality.
- Comment: reusable comment related components and functionality.
- CommentForm: reusable comment form.
- Counter: counter.
- Country: reusable country related components and functionality (e.g. SelectCountry).
- Currency: reusable currency related components and functionality (e.g. SelectCurrency).
- Notification: reusable notification related components and functionality.
- Order: reusable sort order related components and functionality (e.g. SelectOrder).
- Profile: reusable profile related components and functionality.
- Rating: reusable rating related components and functionality.
- SortField: reusable sort field related components and functionality (e.g. SelectSortField).
- User: reusable user related components and functionality.
- View: reusable view related components and functionality (e.g. SelectView).
- Editor:
Features are some functionality blocks that provide functionality for the user.
One feature = one functionality.
- ArticleCommentList: displays a list of comments for a given article.
- ArticleListFilters: allows users to filter articles based on various criteria.
- ArticlePageGreeting: displays a greeting message on the article page when user first time enter it.
- ArticleRating: allows users to rate articles.
- ArticleRecommendationsList: displays a list of recommended articles.
- AuthByUsername: allows users to login or register using their username.
- EditArticle: allows users to edit articles.
- EditableProfileCard: displays a user's profile information and if user has rights, allows to edit it.
- LangSwitcher: allows users to switch between different languages.
- NotificationButton: displays a notifications on button click.
- ProfileRating: allows users to rate profiles.
- ScrollToTop: allows users to scroll to the top of the page.
- ThemeSwitcher: allows users to switch between different themes.
- ToggleDesign: allows users to toggle between different designs.
- UserDropdown: displays a dropdown menu for the user.
- UserNavigation: displays navigation links for the user.
- CreateArticle: allows users to create or edit articles.
- ImageToolbarPlugin:
- AutoLinkPlugin:
- CodeActionMenuPlugin:
- CodeBlockToolbarPlugin:
- SelectBlockTypeToolbarPlugin:
- LinkToolbarPlugin:
- TextFormatToolbarPlugin:
- CodeHighlightPlugin:
- HeadingPlugin:
- DraggableBlockPlugin:
Widgets merge reusable entity blocks with features, creating meaningful blocks.
- ArticleAdditionalInfo: displays additional information about an article, such as the author, date, and number of views.
- ArticleInfiniteList: displays a list of articles that can be scrolled infinitely.
- LoaderLayout: displays the whole page skeleton while content is being loaded, and then displays the content once it's ready.
- Navbar: displays a user related data like notifications or user panel.
- Page: a basic page component that sets default page styles(e.g. paddings, margins) and shared page functionality (e.g. restoring page scroll position).
- PageError: displays an error blcok with message when a page fails to load.
- PageLoader: displays a full page loading spinner while a page is being loaded.
- ScrollToolbar: displays a toolbar to go to the top of the page that appears when the user scrolls down the page.
- Sidebar: displays a sidebar with links to different sections of the website.
- CreateArticle:
- ArticleEditor:
Pages are composed of widgets and features while remaining as "thin" as possible.
- AboutPage: displays information about the website and its creators.
- AdminPanelPage: provides access to the website's administrative tools.
- ArticleDetailsPage: displays the details of a specific article.
- ArticleEditPage: allows the user to edit an existing article.
- ArticlesPage: displays a list of articles.
- ForbiddenPage: displays an error message when the user tries to access a forbidden page.
- HomePage: displays the website's home page. Every user starts here.
- NotFoundPage: displays an error message when the user tries to access a non-existent page.
- ProfilePage: displays the user's profile information.
- SettingsPage: allows the user to modify their account settings.
App folder contains all app related code that is not used in any other slices at any time (except types).