If you've ever worked on a long-standing JavaScript project, you know the pain of updating dependencies and dealing with broken builds. I recently went through this experience while trying to update ABTestBase, a project that had accumulated outdated dependencies, breaking aliases, and package conflicts.
This post is a deep dive into what went wrong, how I fixed it, and what I learned along the way.
🚨 The Problem: A Broken Build System
It started with a simple command:
npm run build
And then... everything fell apart.
Errors Encountered
- Outdated Browserslist Warning
Browserslist: caniuse-lite is outdated. Please run: npx update-browserslist-db@latest
- Conflicting ESLint Versions
npm ERR! peer eslint@"^5.16.0 || ^6.1.0" from eslint-config-airbnb-base@14.0.0
- Parcel Flags No Longer Supported
error: unknown option '-d' error: unknown option '--experimental-scope-hoisting'
- Aliases Not Resolving
@parcel/core: Failed to resolve '<UTILS>/addInternalCSS'
These issues came from years of dependency drift. Updating a single package like parcel
or eslint
broke others, leading to a painful dependency resolution process.
🛠️ Step 1: Updating Outdated Dependencies
Since some of the errors were related to outdated libraries, I started by updating core dependencies:
npm update caniuse-lite browserslist
That didn't fix everything, so I ran:
npm audit fix --force
Which resolved security vulnerabilities in:
- tar (arbitrary file overwrite vulnerability)
- semver (Regular Expression Denial of Service)
- tough-cookie (Prototype Pollution vulnerability)
🛠️ Step 2: Fixing Parcel Issues
Parcel had been upgraded from v1 to v2, meaning some old CLI flags no longer worked.
For example:
❌ Old Build Command (Parcel v1)
parcel build v1.js -d build --experimental-scope-hoisting --cache-dir ./.cache
✅ New Build Command (Parcel v2)
parcel build v1.js --dist-dir ./build --cache-dir ./.cache
I also had to remove @babel/preset-env
from my babel.config.json
, since Parcel v2 automatically transpiles modern JavaScript.
🛠️ Step 3: Fixing Broken Aliases
ABTestBase used custom aliases like <UTILS>
, <LIBRARY>
, and <GET>
for imports. Unfortunately, Parcel v2 doesn’t support angle-bracket aliases (<>
).
I modified package.json
to use standard aliases:
"alias": {
"UTILS": "./Library/Utils",
"LIBRARY": "./Library"
}
And then updated my imports:
// ❌ Old (Did Not Work)
import addInternalCSS from '<UTILS>/addInternalCSS';
// ✅ New (Fixed)
import addInternalCSS from 'UTILS/addInternalCSS';
Still, Parcel refused to recognize the aliases until I explicitly defined them in .parcelrc
:
{
"extends": "@parcel/config-default",
"resolvers": ["@parcel/resolver-default"]
}
🛠️ Step 4: Ensuring Builds Work from Any Test Directory
The build process originally only worked from the project root, but I wanted to run npm run build
inside any test directory:
cd Accounts/TheGood/Tests/SoftwareUpdateTest
npm run build
To fix this, I modified the build script to detect the current working directory:
"build": "parcel build ./v1.js --dist-dir $PWD/build --cache-dir $PWD/.cache"
Now, no matter which test directory I’m in, the build output is placed inside its own build/
folder.
🎯 Key Takeaways
-
Old Projects Accumulate Technical Debt
- Even if everything worked fine yesterday, dependency updates can break your project in unexpected ways.
-
Parcel v2 Has Major Changes
- Old CLI flags don’t work (
-d
→--dist-dir
,--experimental-scope-hoisting
is removed). - Built-in transpilation means you don’t need
@babel/preset-env
. - Aliases need explicit configuration in
package.json
and.parcelrc
.
- Old CLI flags don’t work (
-
Fixing One Issue Can Break Another
- Updating ESLint forced updates to eslint-config-airbnb-base.
- Removing Babel configs required rethinking Parcel’s built-in features.
- Changing alias handling forced updates to every import statement in the codebase.
🚀 Final Thoughts
After hours of debugging, I finally had a working build process again. More importantly, I learned a ton about dependency management, Parcel v2, and alias handling.
If you’re maintaining an old project, update dependencies carefully and be prepared for a cascade of fixes. It’s painful, but in the end, your project will be more stable and easier to maintain.