[Go Make Things] The build vs. buildless tension

A big goal of Kelp is easy customization without a build step.

Leaning on the power of the modern web, I want you to be able to customize the hell out of it without ever having to jump into the command line, without ever installing any dependencies, and without every running a build.

But finding the right balance of developer experience and web performance with that setup is hard, and I'm not sure what the right structure is.

Today, I wanted to dig into a few options, and maybe even get your feedback!

Let's dig in…

The current raw structure

Kelp currently has a ton of modular files.

It uses @import to load all of the CSS from a single file, and import to load all of the JavaScript.

For a project still in development, it's been really nice to work modular files, open up a browser, and immediately see the changes without waiting for anything to compile.

But should the "finished product" work like that, too?

The benefits

In the HTTP/2 world, we can download lots of modular files concurrently, so having a bunch of smaller files can actually be a good thing.

And it makes customization absurdly easy.

Let's say you wanted to use containers and the grid, but didn't need any of the other layouts. You can just open up kelp.css and comment out or delete the stuff you don't want.

/* Layout */  @import "./layout/containers.css";  @import "./layout/grid.css";  /*@import "./layout/stack.css";  @import "./layout/split.css";  @import "./layout/cluster.css";  @import "./layout/sidecar.css";*/

If you've been a developer for a while, you may have also had the experience of opening up a project, going to run a build… and getting a bunch of errors about out-of-date dependencies or security issues.

It sucks, especially when you just want to update a line or two of CSS.

This approach completely avoids that issue. You just edit and go!

The cons

It's really just one, but it's a big one.

Kelp's modular files are really small (some are 0.3kb in size). With compression (like gzip or brotli), files under 1kb in size don't compress very well, and often end up bigger than their uncompressed versions.

I ran some tests on this with Kelp, and the entire suite of utility classes bundled into a single file was about the same size (gzipped) as just one of the individual files in it was (also gzipped).

Keeping them modular is actively harmful from an end-user perspective, resulting in 10x the data transfer for the same amount of stuff.

A few ways to fix this

I've been thinking about this a lot (probably too much), and I see two potential options.

  1. Manually combine like-stuff into some bigger files. I might put all of the smaller utility CSS files into a single, manually updated utilities.css file, all of the layout styles into a single layouts.css file, and so on.

  2. A build step for me, but not for thee. I keep the files extremely modular like they are now, and run my own build step to combine them. The source code would contain the unbundled versions alongside the bundled counterparts (eg. kelp.css and kelp.raw.css).

Both approaches get you to the same place: larger files that compress better, and a build-free experience for the end-user.

But they also both have a few trickle down effects, and I don't love either of them.

With both options, you can't just comment out an @import to customize anymore. You need to comment out or delete big chunks of code, or run your own build step.

Option 1 means scrolling through bigger source files to find the stuff you want to edit or update. Option 2 means maintaining a build system and remember to run a build before each deploy (yes, I could automate it, but still).

Text editors and @layer maybe make this easier?

Most modern text editors support folding or collapsing sections of code.

With option 1, each feature inside the larger file would still be wrapped in its own @layer, which could then be collapsed in your text editor so you can focus on just the part you want to delete/edit/whatever.

/* Hypothetical layout.css file  */    /**   * @section Containers   * Contain the max width of content   */    @layer kelp.layout {    	[class*="container"] {  		--width: var(--breakpoint-m);  		margin-inline: auto;  		max-width: var(--width);  		width: 86vw;  	}    	/* ... */    }    /**   * @section Grid   * 12 columns, divided using simple fractions   */    @layer kelp.layout {    	[class*="grid"] {  		--gap: var(--size-m);  		grid-template-columns: repeat(12, 1fr);  		grid-template-rows: 1fr;  		gap: var(--gap);    		display: flex;  		flex-direction: column;  	}    	/* ... */    }

Maybe that's ok? Maybe it's still really annoying. I dunno!

What do you think?

If you're someone who loves build steps, Kelp's core ethos probably doesn't speak to you.

But if you're drawn to the goals of this project—a focus on HTML, progressive enhancement, and build-free customization—which approach would you prefer?

Or is there another option I'm not thinking of that's even better?

Like this? A Go Make Things membership is the best way to support my work and help me create more free content.

Cheers,
Chris

Want to share this with others or read it later? View it in a browser.

Share :

Facebook Twitter Google+ Lintasme

Related Post:

0 Komentar untuk "[Go Make Things] The build vs. buildless tension"

Back To Top