Skip to content

Latest commit

 

History

History
170 lines (103 loc) · 9.07 KB

File metadata and controls

170 lines (103 loc) · 9.07 KB

About

The project was designed with maximum emphasis on code quality, structure, architecture, scalability. Familiarize and learn new tools/approaches. Nevertheless, in the application the user has authorization, the ability to view fake articles, sort them, edit profile, change the design of the application.

For login to the application, you can use 2 profiles with different levels of access. More details - here.

A server was rented on Debian operating system, nginx was configured at the basic level, as well as distribution of static files, as well as gzip.

Project running

  npm i - installing dependencies
  npm run start:dev or npm run start:dev:vite - running on webpack5 builder, or vite builder.

Scripts

  • npm run start - start webpack5 development server
  • npm run start:vite - start vite development server using .env.development file
  • npm run start:dev - start webpack5 development server and JSON Server backend
  • npm run start:dev:vite - start vite development server and JSON Server backend
  • npm run build:prod - create production build of application, with --env variables mode=production and apiUrl=<production backend url>
  • npm run build:prod:vite - create production build of application using vite and .env.production file
  • npm run build:dev - create development build using webpack5
  • npm run lint:ts - run eslint
  • npm run lint:ts:fix - Fix all auto-fixable problems with eslint
  • npm run lint:scss - run stylelint
  • npm run lint:scss:fix - Fix all auto-fixable problems with stylelint
  • npm run test:unit - run unit and integration testing using jest for all .test. or .spec. files. You can run specific test file, by adding test filename, for ex. npm run test:unit Counter.spec.tsx
  • npm run storybook - run storybook
  • npm run storybook:build - create storybook build
  • npm run export-svg-icons - Exports all SVG icons contained in the assets directory, which have been converted to JSX format for easier use, to an index.ts file.
  • npm run generate:layer - Automatically creates a slice and segment for the given layer that was requested when the script was called according to the described template of project folders and files.
  • npm run update-shared-imports - During development it was deliberately made a mistake not to create a public API for shared/ui layer. After writing this script, it automatically creates an index.ts, if not exists, file in each UI element of the component, and exports all exported content. Moreover, the script edits all ui component imports in the project.
  • npm run update-eslint-plugin - Updates the custom eslint plugin to the current version

Project architecture

Project was written depends on Feature Sliced Design methodology.

Docs link - Features Sliced Design


Work with translation

Project using i18next library for translations. The translation files are stored in public/locales. A convenient file system of translations is provided, which makes it easy to introduce a new language: create a directory with the desired language, edit the i18next configuration a bit and create translations manually using the appropriate keys

For comfortable working with translations strongly recommend to install vscode/web-storm extension. For vscode link provided: click me

i18next docs - https://react.i18next.com/latest/using-with-hooks


Testing

Project has 4 types of tests:

  1. Default unit tests - npm run test:unit
  2. Integration testing with React Testing Library - npm run test:unit
  3. e2e tests with Cypress - npm run test:e2e
  4. regression screenshot storybook testing - npm run test:ui

More about test


Linting

Project uses ESLint for uniform code standardization and StyleLint for styles checking

So also created its own custom plugin, which contains 3 rules for controlling FSD architecture standards. Own plugin - npm, github

Plugin rules description:

  1. path-checker - restricts using absolute imports within one module
  2. layer-imports - verifies that imports are correct from an FSD architecture (For example, you can't use a Features layer in another Features layer), or use an overlying layer in an underlying layer. (For example, use a Features layer in an Entities layer, or Pages in Widgets, and so on).
  3. public-api-imports - allows imports only from public API (index.ts) file of module. Has auto-fix

Storybook

Project using storybook to describe components views. The storybook-addon-mock is used for mock requests from backend.

The storybook file is in the same directory as the component it describes and has pattern like .stories.tsx

The storybook is started with the following script - npm run storybook

More about storybook - Storybook

Code example

Additional decorators to make the storybook work with the libraries used in the project are written here.


Project configuration

For development project has 2 configs:

  1. Webpack config - ./config/build, webpack.config.ts
  2. Vite config - vite.config.ts

The project configuration is stored in /config

  • /config/babel - babel configuration
  • /config/build - Webpack configuration. Resolvers, plugins, DevServer, Loaders are stored here
  • /config/jest - jest environment config
  • /config/storybook - storybook configuration

CI Pipeline

The project has CI Pipeline and Github Actions configured at a basic level. The github configuration can be found here.


Working with data

Data interaction is handled by @reduxjs/toolkit. Reusable entities can be normalized using EntityAdapter, which allows to obtain O(n) data access complexity.

Requests to the backend are sent using both axios and RTK Query

JSON-server was used for backend in the application, as well as the basic data in the form of filling articles, comments, notifications, users and profiles were filled manually, due to the absence of backend. Can write a full-fledged backend in NestJS, for example, together with the editor of articles with the help of some library.

For async reducers loading, used DynamicModuleWrapper

It allows asynchronous loading of reducers, thus getting rid of them in the main bundle

Code example


Environment

There are a lot of custom solutions in the project. Handy scripts, hooks, scss structure allows to easily introduce new themes/styles. The app supports 4 themes - dark and light for two design options, blue and sand for old and new design respectively.

For even more comfortable development could be used some CSS-IN-JS library like styled-components.

A lot of helpers to handle redux/hooks (useDispatch -> buildSlice, useSelector -> buildSelector), class names, query parameters feature-flags handlers.

Several scripts for automated refactoring with ts-morph have been written, which allow to work with AST code tree, parse and modify it.

Also, the project was initially configured on Webpack, and then Vite was added as an additional builder.


Feature flags

The project implemented the concept of Feature Flags, which will be used for the redesign of the project and the simultaneous existence of the old, and new design of the application.

Handler functions have been created, that allow convenient interaction with the concept, as well as automatic refactoring using ts-morph, which "kicks out" a feature, either with an on flag or an off flag, based on the name of the feature.


Working with forms

One of the best solutions at the time of writing the project for working with forms - react-hook-form - is pre-integrated into the project. More about

New design

At the end of development, the application was completely redesigned to match the Figma layout, using ToggleFeatures handler functions for components and toggleFeatures for functions that return void or something that is not a component.

To switch the design, you need to click on the user avatar, go to settings and select the new design version there.