Back to all posts

Why Your Shopify Store Is Rendering the Same CSS and JavaScript Twice Because Nobody Cleaned Up After a Theme Migration

Shopify Performance Theme Development Technical CRO

The Problem Nobody Notices Until They Look for It

When Shopify brands migrate from one theme to another, there is usually a cleanup list that gets started and never finished. Design decisions get made, the new theme goes live, the team moves on, and the old theme's asset references quietly stay behind in the codebase.

What we find in audits is that a surprisingly large number of stores running a polished, modern theme are also loading CSS files, JavaScript libraries, and icon fonts from a theme that was retired six to eighteen months ago. Nobody deleted the references. Nobody checked. The performance metrics looked acceptable at launch, so nobody asked questions.

The result is a store that loads two sets of conflicting CSS rules, two versions of the same JavaScript utility library, and sometimes two completely separate icon font packages. Shoppers on mobile never notice in an obvious way. But the browser does, and so does your LCP score.

How This Happens in Practice

Theme migrations in Shopify almost never start from zero. Most brands move from Dawn to a premium theme, or from a heavily customized version of their old theme to a fresh build. The developer responsible for the migration copies over custom sections, custom CSS blocks in the theme editor, and snippets that were built to power specific product page features.

Here is the part that creates the problem. When a developer copies a snippet from the old theme, that snippet often contains its own stylesheet link or script tag baked directly into it. The snippet gets pasted into the new theme, the feature works, and nobody notices that the snippet is calling an external stylesheet that has nothing to do with the new theme's design system.

We audited a skincare brand last quarter that was running two separate versions of a custom font loading script, one from their 2022 theme build and one from a developer who patched a font rendering issue in 2023 without removing the original. Both scripts were loading on every page. Neither was conditional. The fonts looked fine because the browser resolved the conflict by defaulting to the second load, but the first script was still adding roughly 280 milliseconds to time-to-interactive on mobile.

Another pattern we see constantly is duplicate icon font payloads. A brand migrates to a new theme that ships with its own icon system, but an old app integration or custom snippet is still calling Font Awesome or a legacy icon library in the head. Both libraries load. Only one is used visibly. The unused one adds weight to every page request without doing a single visible thing for the shopper.

What to Actually Check

The fastest way to surface this is running a WebPageTest audit on your homepage, a collection page, and a product page separately. Look at the waterfall chart and filter specifically for CSS and JavaScript files. Group them by domain and by filename. Any file that appears to be loading from a cdn.shopify.com path that does not match your current theme's asset structure is worth investigating.

In Chrome DevTools, open the Coverage tab while on your product page. Run a page load. The Coverage tool will show you exactly which CSS and JavaScript bytes are being downloaded but never executed during the page session. A healthy product page should have coverage utilization above sixty percent on critical resources. If you are seeing stylesheet files at eight percent or twelve percent coverage, you have dead assets loading on every visit.

The Shopify theme editor itself is also worth auditing manually. Open the theme code and search globally for script tags and link tags that contain external URLs. Any URL pointing to a CDN you do not recognize or a version number that predates your current theme launch is a candidate for removal. Cross-reference it with your current app list. If the app that required that asset is no longer installed, the tag has no reason to exist.

One more place to check: the layout/theme.liquid file and any section schema files that include asset loading in their JavaScript. Developers sometimes add asset loading logic inside section schemas specifically so the asset only loads when that section is on the page. But when a migration happens and the new theme restructures how sections work, those conditional loads can become unconditional ones without anyone realizing it.

Why This Hurts Conversion Specifically

Page weight and execution time have a direct relationship with add-to-cart rates on mobile. Google's own research has consistently shown that each additional second of mobile load time increases bounce probability significantly, and most of the stores we audit see sixty to seventy percent of their traffic arriving on mobile.

The compounding issue with duplicate assets is not just raw load time. It is the browser's parse and execution work. When a browser encounters two versions of the same JavaScript library, it has to parse both, check for conflicts, and in some cases execute initialization logic twice. That work happens on the main thread, which is the same thread handling user interactions. A shopper who taps the size selector or taps Add to Cart during that execution window will experience a noticeable lag. That lag is not dramatic enough to make someone close the tab, but it is exactly the kind of small friction that increases the probability they do not complete the purchase.

We have seen stores recover between 0.3 and 0.6 seconds of LCP improvement purely from removing duplicate asset loads after a theme migration, with no other changes. On a store doing three million dollars a year, that kind of improvement in mobile LCP has a measurable impact on the conversion rate for mobile sessions.

Cleaning It Up Without Breaking Anything

Before removing any asset reference, take a full backup of your theme code and test on a development or staging theme first. The risk with removing old CSS files is that some part of your current site might be inheriting styles from that old file without your team realizing it. Use the Coverage tool in DevTools to confirm that the selectors in the file you plan to remove are not being applied to any visible elements on your live pages.

For JavaScript files, search your codebase for any function calls or object references that come from the library before deleting the import. Global namespace pollution from old libraries means your current theme code might be accidentally depending on a utility function exposed by a library it should not be using at all.

Remove one asset at a time. Deploy to staging. Run a visual regression test on your key pages. Confirm nothing breaks. Then move to production.

The cleanup is tedious but it is not complicated, and it pays off in load time, Core Web Vitals scores, and conversion rates on the traffic segment that matters most.

If you are not sure where to start or whether your store has this problem, a conversion audit will surface it in the first pass through your technical performance layer. We check for this in every audit we run for brands in this revenue range because it is genuinely one of the more common performance issues we find hiding in otherwise well-built Shopify stores.