Skip to content
Go back

Your Laravel App Is Shipping JavaScript Nobody Uses

My app’s JavaScript bundle was 240KB. After a performance audit, I found three libraries that were imported, configured, and bundled into every page load — but never actually used anywhere. Removing them took 20 minutes and cut the bundle by 28%.

The interesting part wasn’t the fix. It was how the dead code got there. Each library had been added for a good reason, then made redundant by something else, and nobody noticed.

Table of contents

Open Table of contents

How dead JavaScript accumulates in Laravel apps

I asked Claude Code to audit my entire codebase for performance issues:

do a full search through the codebase and find the biggest performance bottlenecks and areas that are impacting performance the whole responsiveness and feel of the application

One of the first things flagged was a monolithic JavaScript bundle — 240KB loaded on every page. I didn’t think some of these libraries were even used any more:

lets investigate this — Single monolithic JS bundle (235KB) loaded on every page — i didn’t think chart.js or moment were used any more? please investigate

Chart.js and Moment had already been removed at some point. But three other dead dependencies were still there, silently inflating the bundle.

Axios: the library Livewire made redundant

Every new Laravel app ships with a bootstrap.js file that imports and configures axios — a popular HTTP client:

// resources/js/bootstrap.js
import axios from 'axios';
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

This made sense before Livewire. If you needed to make AJAX calls from JavaScript, you used axios. But Livewire handles all its own HTTP communication — every wire:click, every wire:model, every server round-trip goes through Livewire’s internal mechanism. It never touches window.axios.

I searched the entire codebase — every Blade template, every Alpine component, every JavaScript file — for any reference to axios or window.axios outside of bootstrap.js. Nothing. Axios was imported, configured, assigned to window, and never called.

The fix was deleting bootstrap.js entirely.

date-fns: the function nobody called

The app.js file imported date-fns and defined a date formatting helper:

import { format, parseISO } from 'date-fns';

window.formatDate = function(dateString) {
    const date = parseISO(dateString);
    return format(date, "do MMMM yyyy");
};

When I asked what these libraries were actually for:

what are axios + date-fns ?

It turned out window.formatDate was defined but never called from any Blade template or Alpine component. The function existed, the library was bundled, but no page ever used it. Date formatting had been moved to PHP at some point and the JavaScript version was left behind.

13 console.logs left over from debugging

After cleaning up the libraries, I moved on to the remaining JavaScript:

now fix the console.log stuff

The TipTap editor image extension had 13 console.log statements — left over from when the extension was first built:

// Before: debugging logs shipped to production
document.addEventListener('flux:editor', (e) => {
    console.log('Flux editor event received:', e.detail);
    try {
        console.log('Attempting to register Image extension...');
        console.log('Image extension imported:', Image);
        console.log('Registering with config:', {
            inline: true,
            allowBase64: false,
            HTMLAttributes: { class: 'max-w-full rounded-lg' }
        });
        e.detail.registerExtensions([
            Image.configure({
                inline: true,
                allowBase64: false,
                HTMLAttributes: { class: 'max-w-full rounded-lg' }
            })
        ]);
        console.log('Image extension registered successfully');
    } catch (error) {
        console.error('Failed to register Image extension:', error);
    }
});

// After: just the code that does the work
document.addEventListener('flux:editor', (e) => {
    e.detail.registerExtensions([
        Image.configure({
            inline: true,
            allowBase64: false,
            HTMLAttributes: { class: 'max-w-full rounded-lg' }
        })
    ]);
});

13 lines of debugging output removed. The extension registration went from a verbose logging exercise to four clean lines.

The results

MetricBeforeAfterChange
JS bundle size240KB173KB-28%
Gzipped size~74KB~53KB-28%
npm packages removed24

Three changes — deleting bootstrap.js, removing the date-fns import, and cleaning up console.logs — removed 67KB from every page load and 24 packages from node_modules.

How to check your own bundle

The pattern for finding dead JavaScript in a Laravel app:

  1. Search for actual usage, not just imports. A library imported in app.js isn’t necessarily used anywhere. Search your Blade templates and Alpine components for references to window.axios, window.formatDate, or whatever the library exposes. If nothing calls it, it’s dead code.

  2. Check if Livewire replaced your JavaScript. If you switched from vanilla AJAX to Livewire, you probably don’t need axios, fetch wrappers, or any custom HTTP client code. Livewire handles its own requests.

  3. Search for console.log in production code. Every console.log that shipped to production was a debugging statement someone forgot to remove. Search your JavaScript files and decide which ones are actually needed (almost none of them).

  4. Rebuild and compare. After removing dependencies, run npm run build and check the output file size. The difference tells you exactly how much dead code you were shipping.

Key takeaway

Dead JavaScript accumulates silently. Libraries get added for a feature, the feature gets rebuilt with Livewire or moved to PHP, and the original library stays in the bundle. Nobody notices because the app still works — it’s just heavier than it needs to be. The fix isn’t complicated. It’s asking the question and searching for actual usage instead of assumed usage.

For the PHP and Livewire side of this same performance audit, see I Asked AI to Audit My Page Speed. It Found 9 Issues.


Back to top ↑