How to Increase Your Page Size by 1,500% with webpack and Vue

Disclaimer: This article is mostly satire. I do not think that I am better than you because I once wrote some TypeScript nor do I think that it’s a good thing for us to make web pages bigger. Feel free to misrepresent these views to maximize clicks.

You know, there are a lot of articles out there telling you how to make your page smaller: optimize your images, remove extraneous CSS rules, re-write the whole thing in Dreamweaver using framesets. Look,  Walmart just reduced their page size by some numbers, give or take.

What we don’t have are enough articles showing you how to increase your page size. In fact, the only article I could find was this one from the Geek Squad which ended up being about making the font size bigger. This is a good start, but I think we can do better.

Put on some weight

Now, why would you want to increase your page size? Isn’t that a not-very-nice thing for people on low bandwidth connections? Well, there are several excellent and in no-way-contrived reasons and here are three of them since things that come in threes are more satisfying.

  1. You have a gigabyte connection and you live in Tennessee so surely everyone else is in better shape than you are.
  2. Browsers do caching, silly. That means that you only have to download the site once. Stop complaining. First world problems.
  3. You don’t care whether or not people ever visit your site because you, “work to live, not live to work.”

If any of those completely relatable reasons resonates with you, I’d like to show you how I increased the size of my CSS by 1,500% — and you can too, with one simple webpack trick.

One weird trick

It all started when I decided to refactor my retirement plan project called The Urlist over to the Bulma CSS framework.

The original incarnation of the site was all hand-rolled and my Sass looked like an episode of Hoarders.

“Burke, you don’t need 13 different .button styles. Why don’t you pick one and we can get rid of these other 12 so you have somewhere to sleep?”

Bulma also includes things like modals that I used third-party Vue components to make.

It also has a hamburger menu because it’s a well-known scientific fact that you cannot have a successful site without a hamburger.

Look, I don’t make the rules. This is just how business works.

I was quite happy with the result. Bulma styles are sharp, and the layout system is easy to learn. It’s almost as if someone somewhere understands CSS and also doesn’t hate me. That’s just a hard combination to find these days.

After a few weeks of refactoring (during which I would ask myself, “WHAT ARE YOU EVEN DOING MAN?!? THE SITE ALREADY WORKS!”), I finally finished. As a side note, the next time you think about refactoring something, don’t. Just leave it alone. If you don’t leave any technical debt for the next generation, they’re going to be extremely bored and that’s going to be on you.

When I built the project, I noticed something odd: the size of my CSS had gone up pretty significantly. My hand-crafted abomination was only 30KB gzipped and I was up to 260KB after the refactor.

And, to make matters worse, the Vue CLI was lecturing me about it…

Which, of course, I ignored. I don’t take instructions from robots.

What I did instead was deploy it. To production. On the internet. Because I did not spend all of this time refactoring to not deploy it. Yeah, sunk costs and all that, but excuse me if I’m more pragmatic than your poster of logical fallacies. All I’m saying is I came to party and I was not going home without a buzz.

Then I took to Twitter to announce my accomplishment to the ambivalent masses. As one does.

Shortly thereafter, Jeremy Thomas, who created Bulma (and clearly loves Dragon Ball) responded. It was quick, too. It’s like there is a bat signal that goes out whenever a moron tweets.

Duplicate styles? 13 times? What the heck is a namespace? Is that a π symbol or a custom Jeremy Thomas logo?

It’s at this moment that I realized that I have no idea what I’m doing.

Put the Sass down and back away slowly

I’ll be the first to admit that I don’t know a lot about CSS, and even Less about Sass. Get it? Less about Sass? Forget it. I don’t want your pity laugh.

When I setup my Vue CLI project to use Bulma, I created a src/styles folder and dropped in a bulma-but-not-all-of-bulma-only-some-of-it.scss file. They say naming things is hard, but I don’t see why.

That file imports the pieces of Bulma that I want to use. It’s Bulma, but not all of it. Only some of it.

@import "bulma/sass/utilities/_all.sass";
@import "bulma/sass/base/_all.sass";

@import "bulma/sass/form/shared.sass";
@import "bulma/sass/form/input-textarea.sass";

// etc...

Then I imported that file into a custom Sass file which I called… site.scss. I like to keep things simple.

@import "./bulma-but-not-all-of-bulma-only-some-of-it.scss";

html,
body {
  background-color: #f9fafc;
}

// etc...

I wanted to import these files into Vue globally so that I could use them in every component. And I wanted to do it the right way; the canonical way. I think it’s clear from my willingness to deploy 2+ MB of CSS into production that I like to do things the “right way”.

I read this excellent blog post from Sarah Drasner called, “How to import a Sass file into every component in your Vue app.” She shows how to do it by modifying the webpack build process via the vue.config.js file.

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        data: `@import "@/styles/site.scss";`
      }
    }
  }
}

What I did not understand is that this imports Sass into every component in a Vue app. You know, like the title of the blog post literally says. This is also how I ended up with a bunch of duplicate styles that had a data-v- attribute selector on them. I have scoped styles to thank for that.

How Vue handles `scoped`

Vue allows you to “scope” styles to a component. This means that a style only affects the component that it’s in, and not the rest of the page. There is no magic browser API that does this. Vue pulls it off by dynamically inserting a data- attribute in both the element and the selector. For example, this: