"Yo Swiz, why aren't there any generated assets on preprod?"
Preprod is production-but-not. As the last step before deploying to production, it acts just like the real deal. Real data, real users, real configuration, real everything except payments. Because that would be rude.
"Errr ... what do you mean there's no assets?"
"Well, we ran out of environments, so I'm testing on preprod. It's like Webpack doesn't output anything, but it works on localhost and all our other environments."
O.o
ERROR in tutor_onboarding.js from UglifyJs SyntaxError: Unexpected token: name (defaultHeaders) [./~/better-fetch/index.js:2,0]
That's funny ... UglifyJS throws an error on the first line of my better-fetch library. Why would it do that? ?
"We don't minify our code on localhost, do we? What about on staging?"
"Yeah, only prod and preprod"
Great, at least we know how nobody noticed this in over a month. It only happens on servers configured for production.
Thank the-god-of-grizzled-veterans for preprod! Error happens, deploy goes through, assets are empty, nothing works. Imagine how absolutely fantastic this would be to discover when deploying to real production ?
Here's the line that broke UglifyJS:
let defaultHeaders = {};
I built a fetch()
wrapper in ES6. Fuck me, right? Not like it's an ES6+ only API or anything like that…
Hint: it is. It's ES6 only. You'd think building a wrapper in ES6 without compiling before
npm publish
would work, right?
Nope. Not if a project that imports your library minifies their assets.
How to package your ES6 library so anyone can use it
3.73 months ago, I thought packaging a library was hard. Turns out it's not so bad at all.
You have to add Babel, the ES6 -> ES5 compiler1, configure it, update your new main
entry, and add a build
script to npm scripts. That makes it easier to run.
These 7 lines are all it takes: diff on Github
You have to install babel-cli
and babel-preset-latest
:
$ npm install --save-dev babel-cli babel-preset-latest
And configure Babel:
// package.json
"babel": {
"presets": ["latest"]
}
Configuring in package.json
is easiest. 17 characters is not a good enough reason to add another config file to your project.
You should update your main
entry as well. It tells npm which file to use when somebody uses require('your-library')
or import YourThing from 'your-library'
.
// package.json
"main": "lib/index.js"
Many projects use lib/
for their compiled files. dist/
is another popular choice.
To improve your quality of life, you should add a build
script. Also in package.json
:
// package.json
"scripts": {
"build": "babel src -d lib"
}
Now you can use npm run build
to run babel
, read files from src/
, and output the compiled versions in lib/
. Library fixed. Crisis solved. \o/
Further quality of life improvement
While heroically saving the day with the above 7 lines of configuration, I found another way to improve my quality of life: automatic version bumping and GitHub pushing.
Add these 3 lines to package.json
:
// package.json
"scripts": {
"preversion": "",
"version": "npm run build && git add -A lib",
"postversion": "git push && git push --tags && rm -rf build/temp",
}
You can use npm version X
where X is one of patch
, minor
, major
, etc. to bump your library version number. That always works.
These three lines make it better. preversion
runs a command before updating the version number. If the command fails, the version doesn't change. Usually these are tests. In my case, it's empty because I'm a bad person.
version
runs a command when the version updates. This is a great spot to compile your library and add the compiled files to git.
postversion
runs after the version updates. And this is a great spot to push to GitHub and perform any build cleanup.
Now you can update your library then run npm version patch
to bump the version, build the lib, and push to github. npm publish
announces the fix to the world.
Time to congratulate yourself and grab a beverage. ?
Lesson Learned
UglifyJS doesn't support ES6. They've been working on it since at least March of 2014. As of December 6th, 2016, it's still not ready. Turns out this is a hard problem.
Most real world projects use UglifyJS to minify their JavaScript.
You have to distribute a compiled version of your JavaScript libraries no matter what they do. Such is life.
- Yes, Babel is technically a transpiler ↩
Continue reading about Fun surprise: UglifyJS can't ES6
Semantically similar articles hand-picked by GPT-4
- Arcane JavaScript knowledge still useful
- Migrating to Webpack 2: some tips and gotchas
- How to debug unified, rehype, or remark and fix bugs in markdown processing
- Webpack lazy loading on Rails with CDN support
- Configuring your JAMStack app for prod vs. dev
Learned something new?
Read more Software Engineering Lessons from Production
I write articles with real insight into the career and skills of a modern software engineer. "Raw and honest from the heart!" as one reader described them. Fueled by lessons learned over 20 years of building production code for side-projects, small businesses, and hyper growth startups. Both successful and not.
Subscribe below 👇
Software Engineering Lessons from Production
Join Swizec's Newsletter and get insightful emails 💌 on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.
"Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"
Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.
Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.
Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.
Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev
Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization
Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections
Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog
Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com
By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️