How to Migrate Legacy Vue Links to a React Stack with Seamless Redirection

This article explains the challenges of migrating legacy Vue applications to a unified React stack, focusing on external link redirection, route parameter handling, and unified routing conventions, and provides a concrete implementation using Nginx, path-to-regexp, and a custom Redirector class.

Goodme Frontend Team
Goodme Frontend Team
Goodme Frontend Team
How to Migrate Legacy Vue Links to a React Stack with Seamless Redirection

Background

Currently the front‑end team at Guming uses a unified React stack for new projects, but many legacy Vue apps remain in production. To reduce cognitive load, align with infrastructure, and improve maintainability, these old projects need to be migrated and external links must be managed.

Current Situation and Goals

External link redirection issues

External links are time‑sensitive and static, so the team uses redirect logic in navigation guards to map old routes to new ones. After the old project is taken offline, those redirects disappear, making the links inaccessible.

Some external links are unknown to product teams, causing unexpected feedback when routes change.

Route parameter mental load

During migration, many routes pass numerous URL parameters without a unified convention, complicating maintenance.

Goals

Preserve legacy route redirects to keep old links functional.

Operational visibility – log accesses, detect 404s, and alert owners.

Unified stack and standards – adopt the new front‑end infrastructure and define a common routing specification.

Core Code Design and Implementation

Route Redirection

How to forward – Nginx, NodeJS or JavaScript?

Because hash routes (e.g., #) are not sent to the server, Nginx and Node cannot read them, so the redirect must be handled on the client. Nginx only forwards the base path ( /) to /college.

API design

A configuration‑driven API replaces scattered if‑else logic with a redirect table. Example registration:

const redirector = new Redirector()
  .register('/knowledge/learnList', '/pages/material-list/index')
  .register('/knowledge/detail/:id', '/pages/material-detail/index?id=:id');

Calling redirector.run() executes the redirect based on the current hash.

Redirect table design

Parameter types

Two kinds of route parameters are handled: params (part of the path, e.g., /pending/list/1234567) and query (key‑value pairs after ?, e.g., /pages/list/index?id=1234567). The implementation maps params and preserves query to keep input and output signatures identical.

Regex‑based matching

The path-to-regexp library converts route patterns into regular expressions, enabling dynamic parameter extraction.

Redirector class

import { history } from '@tarojs/router';
import Taro from '@tarojs/taro';
import { match, MatchFunction } from 'path-to-regexp';

type RegisterPath = `/${string}`;

interface RouteObject {
  matchFn: MatchFunction;
  target: string;
}

class Redirector {
  private routes: RouteObject[] = [];

  register(oldPath: RegisterPath, newPath: RegisterPath): Redirector {
    this.routes.push({ matchFn: match(oldPath), target: newPath });
    return this;
  }

  redirect(path: string, query = ''): void {
    this.routes.some(({ matchFn, target }) => {
      const result = matchFn(path);
      if (result) {
        Object.entries(result.params).forEach(([key, value]) => {
          target = target.replace(`:${key}`, value);
        });
        target = `${target}${target.includes('?') ? '&' : '?'}${query}`;
        Taro.redirectTo({ url: target });
        return true;
      }
      return false;
    });
  }

  run(): void {
    const [path, query] = location.hash.slice(1).split('?');
    this.redirect(path, query);
  }
}

const redirector = new Redirector()
  .register('/knowledge/learnList', '/pages/material-list/index')
  .register('/knowledge/detail/:id', '/pages/material-detail/index?id=:id');

export default redirector;

Execution flow

The C‑end H5 micro‑app consists of the old Vue2 project (served at / ) and the new Taro React project (served at /college ). Nginx forwards requests to the appropriate base path, allowing shared localStorage and sessionStorage.

(1) User request and Nginx forwarding

Example old link: https://host/#/knowledge/learnList?rankId=aaa&ListName=bbb is first redirected by Nginx to

https://host/college/#/knowledge/learnList?rankId=aaa&ListName=bbb

.

(2) Client‑side redirect

In app.tsx the redirector is invoked on mount:

// app.tsx
import redirector from '@/utils';
function App({ children }) {
  useMount(() => {
    redirector.run();
  });
}

Operation awareness

404 detection

If a redirect fails, a 404 is logged and the user is sent to a custom 404 page:

function App({ children }) {
  usePageNotFound(e => {
    const tag = 'PAGE_NOT_FOUND';
    const log = `path=${e.path}`;
    Slardar.logger()?.error(log, tag);
    Taro.redirectTo({ url: `/pages/404/index?from=${e.path}` });
  });
}

Redirect logging

Each successful redirect records the source and target URLs for later analysis.

class Redirector {
  // ... inside redirect()
  const tag = 'PAGE_NOT_FOUND';
  const log = `from=${path}&to=${target}`;
  Slardar.logger()?.info(log, tag);
}

Unified routing convention

To reduce parameter noise, the team enforces TypeScript definitions for page input types and provides shared utilities formatUrlParams and getUrlParams for consistent navigation and deserialization.

import { BaseAssignmentParams } from "@/pages/assignment/index/index";

const handleClick = (assignment: CourseAssignmentItem) => {
  const baseQuery = formatUrlParams<AssignmentParams>({
    trainingId: trainingDetail.id,
    semesterId: trainingDetail.semesterId,
    assignmentId: assignment.id,
  });
  Taro.navigateTo({ url: `/pages/assignment/index/index?${baseQuery}` });
};

export interface AssignmentParams {
  trainingId: string;
  semesterId: string;
  assignmentId: string;
}
const { semesterId, trainingId, assignmentId } = getUrlParams<AssignmentParams>();

Summary

The article presents a practical approach to handling external link migration, unified routing, and operational monitoring when moving legacy Vue projects to a modern React stack, offering reusable code and guidelines to reduce technical debt.

frontendMigrationVueRedirect
Goodme Frontend Team
Written by

Goodme Frontend Team

Regularly sharing the team's insights and expertise in the frontend field

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.