Skip to content

Latest commit

 

History

History
77 lines (57 loc) · 3.86 KB

README.md

File metadata and controls

77 lines (57 loc) · 3.86 KB

Esbuild-Preact

Bare minimum modern frontend setup. Not a library or solution, just a starter template for myself, as I've grown tired of the node_modules black hole being 100 times larger than the entire project codebase.

  • Preact (1:1 React experience with smaller bundle)
  • Global store using Jotai
  • SASS
  • Esbuild (Blazingly fast bundling/re-building)
  • Compatibility defaults from Vite and no Babel used - 'es6', 'chrome87', 'firefox78', 'safari14', 'edge88'
  • Gzip/Brotli/Both output encoding
  • Built-in chunking (at least in the js department, though I'm not sure about CSS)
  • Re-build simple caching to cut time even further
  • Env vars substitution
  • Live reload and partial Hot Module Replacement (CSS only)
  • Linter (not a heavy eslint)
  • Prettier
  • Tested with chakra-ui to ensure react backwards compatibility (lib not included)

To use with React:

  • Add react, react-dom
  • Remove aliasing in esbuild.config.js
  • Remove preact paths, jsxFactory, jsxFragmentFactory and jsxImportSource in tsconfig.json

Build time:

  • Gzip, No chakra ; yarn build -> 270ms ; actual build -> 57ms

  • Gzip, With chakra ; yarn build -> 340ms

Rebuild time:

  • Gzip, No chakra ; initial yarn build -> 270ms ; changes -> 15ms

And it could be even lower with optimizations, but with such absurdly low metrics, there's just no point.

All of that fits into 84.1 MiB of node_modules space, including dev dependencies.

These are the bare minimum dependencies used:

"dependencies": {
  "jotai": "^2.10.0", // 1.2 MiB
  "preact": "^10.22.1", // 1.8 MiB
  "preact-iso": "^2.6.3", // 68.0 KiB
  "preact-render-to-string": "^6.4.0" // 964.0 KiB
},
"devDependencies": {
  "@types/node": "^22.5.1", // 2.3 MiB (@types in general)
  "esbuild": "^0.24.0", // 9.7 MiB
  "picomatch": "^4.0.2", // 116.0 KiB
  "prettier": "^2.7.1", // 10.8 MiB
  "quick-lint-js": "^3.2.0", // 11.6 MiB
  "sass": "^1.79.3", // 5.5 MiB
  "typescript": "<=5.2.0" // 38.6 MiB
}

Additionally, there are some child dependencies totaling 2-3 MiB, and that's it. There are only 17 directories in the node_modules folder, so you could literally read the source code of all of them in one day. 👀


I haven't compared the output bundle size with other build tools yet since the codebase is too small to draw any real conclusions, but I'll probably add that in later.

It's worth mentioning that I had to write some custom build-related code to get esbuild to handle what seemed like trivial tasks at first glance—things I was used to getting out of the box from CRA, Vite, and Webpack. Esbuild was missing essential parts here and there, and there aren’t many well-written and optimized plugins to fill the gaps. Moreover, I wanted to include as few dependencies as possible. So, I had to dig through what's available and piece together a 'regular' web development environment step by step. It was fun, and more importantly, an insightful experience as I learned things I never would have with all those pre-built tools.

Esbuild isn't 'production-ready' in the sense that it frequently ships breaking changes. However, it's highly agile with its custom plugin feature. You need to be prepared to get your hands dirty in exchange for fast build speeds and a somewhat immature ecosystem. For me, it's been worth it, and I hope to extract even more value over time.

Also shoutouts to tsoding and his React exploration video for making me rethink how bad it all is in webdev land.

Usage:

yarn start
yarn build