Using AI to Migrate from Lit to React

Nathan Schmidt, Senior UI Developer

Article Categories: #Code, #Front-end Engineering, #AI

Posted on

On a recent project, we needed to change from Lit.js to React to meet new infrastructure requirements without changing the launch deadline. We used AI to make the migration, which cut the time from months to a few weeks.

Migration from one framework to another is a huge undertaking, especially when it is in the middle of a project with a launch deadline. On a recent project we needed to change from Lit.js to React to meet new infrastructure requirements. We knew that we would need to lean primarily on AI to make the migration and still hit our deadline. We also needed the AI to build it right the first time so we did not have to spend time fixing a mess of code. Here is the process that we took to make the migration as smooth as possible. 

Pick the right model 

Selecting the right model is a first step that can make the entire migration process reliable and effective. Use a newer Claude model or pick a high-thinking model from any of the major AI companies. These advanced models are suited for code transformation and ensure that the codebase maintains parity.

Build a plan

Most models have the ability to create a detailed plan before doing the task. When writing the prompt to create the plan, give it as much direction as you can. Don’t leave things up to the AI to figure out if you already know the answer. Items like folder structure, file naming conventions, testing framework, and CSS frameworks. If you can, provide a demo folder structure with the files you want for a component. Anything that will give the AI a clear direction on desired results will be helpful.

There may be things you are not thinking of with the migration. Instead of waiting for the AI to figure them out, tell the AI to ask as many questions as it can. The more context the AI has the better it will be at creating a plan. Once the plan is created, read through the plan to make sure you understand what the AI plan will be doing. Don't just assume it built the plan right.

One thing that will make or break your plan is tests. If you already have tests for each component, ask the AI to build a plan to migrate them. If you don’t have tests, have the AI set them up in the repo. Having the AI build tests for each component will serve as a way for the AI to test its own work to make sure it did the migration correctly. 

# Example prompt:

Build a plan to translate the Lit components in `x/lit/components` to React components in `x/react/components`
Every Lit @property has to be duplicated in the React components
Move all the CSS from the Lit component into `*.module.css` 
The React components have to match the Lit components exactly 

Each new component needs to have a test file. That test needs to cover all the component's functionality. 
Run the tests and fix any errors that show up. 
Migrate the Lit stories over to React and update them to they pull in the new react component.

The file structure of the new React components will look like:
```
react/components/component-name
- component-name.module.css
- component-name.stories.tsx
- component-name.tsx
- component-name.test.tsx
```
The framework and packages needed:
- Tailwind for CSS
- Vitest for component tests
- Storybook to visually test each component

Ask as many questions as you can about the migration from Lit to React

Test on a few components

Once you have the plan completed, start by running it on one component. This will bubble up any errors or things that need to be updated in the plan. Pick a component that is in the middle of the road on complexity. If all goes well, select a more complex component and run the AI plan to migrate it to the new framework. This will give you a good metric on if your plan can handle the range of components. Flag any errors that are not done correctly and get them updated in the AI plan. 

Once you feel comfortable with your plan and the few test migrations have gone well. Ask the AI to run it on the entire directory/repo. Depending on the AI model and the number of tokens you have, you may want to run this overnight or run it while you work on other tasks, as it will take a while to complete. 

Ts
/* Lit Example Component */
export class LitButton extends LitElement {
static styles = css`
    button {
      padding: 0.5rem 0.875rem;
      border: none;
      border-radius: 0.5rem;
      background: #2563eb;
    }
    button:disabled { opacity: 0.5; }
  `;
  @property({ type: Boolean }) disabled = false;
  render() {
    return html`<button ?disabled=${this.disabled}><slot></slot></button>`;
  }
}
Ts
/* React Example Component */
export function ReactButton({
  disabled = false,
  children,
  ...props
}: ButtonHTMLAttributes<HTMLButtonElement>) {
  return (
    <button type="button" disabled={disabled} className={styles.button} {...props}>
      {children}
    </button>
  );
}

Post-migration: Testing and QA 

The migration is complete, but before you ship the code, everything needs to be functionally and visually tested. This is where the code tests come in handy. 

First, run a full build and run all the tests to make sure everything is up and running in the new codebase. Next, test by hand to make sure everything is working correctly. Even though there are tests built for each component, they may not cover the edge cases. Running through everything is the best way to know for sure your codebase is working in the new language like it did before. If you found a functionality bug make sure to also update the test to cover that functionality. 

Depending on the project you may need to also do visual testing on the migrated code. In our migration, the AI did not get all the styles right, especially with the CSS and styling the components. Set up a way to visually check each component, that could be using Storybook or another UI tool.

While AI can do the heavy lifting, there still needs to be a human reviewing and testing everything

Check the new components against the designs to make sure everything looks correct. This process can take the longest, as it may take several rounds of QA with designers and project managers to make sure everything is right. 

AI makes it easy but not perfect

Migrating to a new code framework only takes a day or so, but the QA and testing will probably take about two weeks, depending on how many you have to test. Using an AI for migrating code to a new framework is a smooth process, but it still has to be done with care and attention to detail. If we had not used AI, the translation process would have taken about a month to migrate and another month for QA. But by using AI, we cut that down to a few days to migrate the code and two weeks for QA. 

Writing a plan and testing on a few small components saves a lot of time and prevents hours of rebuilding and refactoring AI code slop. While AI can do the heavy lifting, there still needs to be a human reviewing and testing everything to make sure the migration is correct. 

Nathan Schmidt

Nathan is a Senior UI Developer in Colorado. He loves applying creative thinking to web development and bringing interactive components to life.

More articles by Nathan

Related Articles