Перейти к содержимому
Все проекты
05 · SHOPPING FROM ABROAD · CUSTOMER ACCOUNTНа сайт

CDEK.Shopping: 37% fewer regression bugs after refactoring the legacy code

  • E-commerce
  • Accounts

Стек:

  • JavaScript
  • jQuery
  • Vue 2
  • Vuex
  • SCSS
  • Webpack
  • Cypress
  • Jest
  • axios
  • portal-vue
  • Bootstrap
  • Popper
  • Owl Carousel
  • Slick
  • lightGallery
  • noUiSlider
  • jQuery Masked Input
  • Laravel
  • Blade
  • Sentry
  • Diginetica

использовал я

Роль
Middle Frontend Developer
Команда
4 frontend, 8 backend, 2 QA and a designer
Срок
2 years, 10.2021 – 10.2023
Статус
The site is live, my work on the project is over

What I did

  • Customer accountThe entire frontend of the account in Vue 2 and Vuex: five sections in one app with no page reloads. I wrote every component of the account from the team designer's mockups.
  • Vue inside BladeConvinced the team to adopt Vue 2 and came up with a way to embed the SPA account into Laravel + Blade without a separate frontend project.
  • Legacy refactoringCovered the jQuery code with Cypress E2E tests and visual baselines, then split files of 6,000+ lines into modules with Jest unit tests.
  • Laravel and analyticsBlade templates, routes and account data in API responses. Set up Yandex Metrica and added events. Reviewed the tasks of the other frontend developers.

Context and starting point

Business

CDEK.Shopping is an agent for shopping abroad run by CDEK.Market LLC, a service of the CDEK group. Customers in Russia order products of brands from the US, Europe and Asia: they pay with a Russian card and see prices in rubles right away.

The service handles customs and logistics, and its own logistics company carries the delivery. If a product is not in the catalog, the customer can leave a purchase request.

The situation

The business wanted to launch as soon as possible, so the new service was built on the CDEK Market codebase: jQuery and Blade, files of 6,000+ lines. The customer account there looked straight out of the 2000s, and every action reloaded the page.

The business had no interest in tech debt, so refactoring had to fit into the same deadlines as the launch.

Goal

Build an interactive customer account by the launch, where no action reloads the page. CDEK.Shopping users never saw the old account: they started right away in the new one.

Process, architecture and decisions

Customer account

The customer moves between the account sections without a reload. The tabs show counters: how many orders are waiting for payment and how many products have no review yet.

  1. 01My detailsContacts with a separate email and phone change, details for customs clearance
  2. 02Orders“All”, “Unpaid” and “By purchase request” tabs, a filter, the status of every item, a separate order page
  3. 03My pointsActive, accrued and frozen points, the points history
  4. 04Delivery addressDefault address, delivery to the door or to a pickup point
  5. 05ReviewsProducts waiting for a review and reviews already written

Architecture

The storefront stayed server-rendered, while the account runs as a single-page app inside the same site. It did not need a separate frontend project.

  • STOREFRONTStorefront

    Server rendering with Blade, interactivity with jQuery.

  • ACCOUNTCustomer account

    Vue 2 and Vuex. The backend serves an #app container, the app mounts inside it, routing goes through the hash.

    • account
    • orderListing
    • orderDetailsPage
  • APIREST on Laravel

    The account gets its data through axios: profile, orders, points, delivery and reviews.

    • /api/v1/account
    • /api/v1/loyalty
    • /api/v1/customer
  • SERVICESExternal services

    Payments, the Mindbox marketing tracker, Diginetica search, Yandex Metrica.

Account components

We designed the component system together with the team designer, with BEM naming. The account has 16 base UI components: buttons, a checkbox, tabs, a select, a filter, a modal, a notification, a tooltip, pagination and others.

They make up about 40 section blocks, and the icons live in a sprite of about 30. I built the account responsive from the start, with a separate mobile navigation.

Integrations

  • Yandex Metrica · events
  • Online payments
  • Mindbox · marketing tracker
  • Diginetica · search with autocomplete

подключал я

Data security

The account works with customers' personal data, including the data needed for customs clearance. The backend returns sensitive fields masked, and the interface shows them in full only after the “Show data” button.

Quality and releases

Before the refactoring I covered the store's critical scenarios with Cypress E2E tests and took visual baselines of the components. The modules that appeared after the refactoring are covered with Jest unit tests.

Every task goes through CI checks and a test stand, then on the planned release date it lands on a preprod identical to production. After acceptance the release rolls out to production with no downtime, and if something goes wrong we can quickly roll back to the previous stable version.

  1. develop test stand
  2. preprod acceptance
  3. master production, no downtime

We worked in two-week sprints with a demo at the end of each. Every task went through code review, and I reviewed the tasks of the other frontend developers.

Challenges

Legacy files of 6,000+ lines

Проблема
The jQuery client code lived in files of 6,000+ lines. Writing unit tests for such spaghetti was impossible, and touching it without tests was risky.
Решение
First I covered the critical scenarios with Cypress E2E tests and took visual baselines, so the refactoring would break neither the logic nor the layout. Then, following the Refactoring.Guru principles, I moved repeated code into modules and kept splitting them until only pure functions covered with Jest unit tests were left.
Итог
Regression bugs dropped by 37% according to QA reports. Features started shipping faster, and sprint overruns went down.

Vue 2 in a jQuery project

Проблема
The whole project was written in jQuery and Blade. An interactive account needed a modern framework, and the team had to be convinced to adopt one.
Решение
Got approval to add Vue 2 to the account and embedded it without a separate project: the backend serves an #app container, the app mounts inside it, routing goes through the hash. The account was meant to show on a live example that writing in Vue is simpler and faster than maintaining the legacy code.
Итог
The new service's account launched on Vue 2 and Vuex and became an argument for leaving the legacy code: the team decided to rewrite the project in Nuxt.

Metrics and results

  • −37%regression bugs after the refactoring
  • 5account sections in one app
  • 16base UI components of the account
  • 2 yearson the project

CDEK.Shopping customers worked in the new account from day one, and the legacy refactoring cut regressions and sped up feature delivery.

Need a modern customer account in a legacy project?

I will embed an interactive account into your existing site without a separate frontend project, cover the legacy code with tests and split it into modules.