Fighting Bloated Software
All I wanted to do was create a Web app with authentication.
I started with the excellent project nextjs-starter. The excitement was building when I got authentication to work locally. I gutted the starter content, hoping to achieve a “clean slate”. It appears clean enough, but does it load clean?
Out of the gate, the HTML coming down from the server is 247Kb, and the main JS bundle is a whopping 628Kb. Since when is “Hello World” 1Mb? WTF is this?
The Gardener
I am an aspiring gardener. I want to plant seeds and tend to them as they grow. Buying pre-grown plants would be the quickest way to set up my garden. But what kind of gardener would I be?
Projects like nextjs-starter and Bootstrap are well intended enough. They help developers start with something quickly. But at what cost?
In a first attempt at “gutting” the starter project, I left in all the “starter dependencies”, like Bootstrap, JQuery, and about 25 others, so the authentication flow and appearance would not break. Having observed the bloated build, I feel I must gut everything except the bare minimum authentication flow. The pains of rolling your own authentication flow is why I want to use this particular starter project in the first place.
Gutting CSS
It turns out that the HTML coming down from the server is 247Kb of CSS.
By some unfortunate twist of fate, the “production build” of the starter project is spitting out unminified CSS of a handful of libraries concatenated together.
The culprit is of course `css/index.scss`, which is pulling these in.
Yeah so I’ll just delete everything here and remove those dependencies from package.json
, thank you very much. Oh and I think I’ll delete css/nojs-menus.scss
while I’m at it, which appears to be a whole library dropped into the project rather than added as a dependency.
Fortunately, all the essential elements of the authentication flows still work!
Removing that CSS reduced the initial HTML payload from 247Kb to 2.9Kb. This feels so right.
Gutting JS
What’s in our 628Kb JS bundle anyway? I bet it’s the JS counterparts of the CSS libraries we removed. I’m going to delete all dependencies I don’t think are useful. These include jquery
, popper.js
(Bootstrap’s faithful friends), reactstrap
, react-syntax-highlighter
, and react-transition-group
.
The next exercise is refactoring all the starter code that uses reactstrap
. This consisted of replacing things like <Container>
with <div>
. In fact, I did a blanket text replace for all Reactstrap imports, replacing them all with <div>
(except Form
became form
, and Input
became input
).
For fellow Vim nerds:
:%s/Row\|Col\|Label\|Button\|FormGroup/div/g
:%s/Form/form/g
:%s/Input/input/g
Removing those dependencies reduced JS bundle size from 628Kb to 254Kb.
I still feel like it should be smaller, but this is the price of shiny things.
Time to plant my seeds.
[Update]
The gutted code is here:
* https://github.com/iaincollins/nextjs-starter/pull/86
* https://github.com/curran/nextjs-starter/tree/aggressive-gutting
Also I learned later about the smaller starter example https://github.com/iaincollins/next-auth/tree/master/example