tailwind2-7 Exercise 1: Output Size, Build Time and Watch Mode ============================================================== Setup: a folder with npm install tailwindcss @tailwindcss/cli and this generator (gen.py, run with py gen.py ). It writes HTML files, each with random classes from a pool, plus app.css with @import "tailwindcss"; @source "./src"; --- gen.py --- import random, sys, pathlib, shutil n_files, per_file, pool_kind = int(sys.argv[1]), int(sys.argv[2]), sys.argv[3] root = pathlib.Path(sys.argv[4]); shutil.rmtree(root, ignore_errors=True); (root/'src').mkdir(parents=True) random.seed(1) colors = ['red','blue','green','amber','sky','rose','slate','teal','lime','pink'] shades = [50,100,200,300,400,500,600,700,800,900] pool = [] for c in colors: for s in shades: pool += [f'bg-{c}-{s}', f'text-{c}-{s}', f'border-{c}-{s}'] for i in range(0, 97): pool += [f'p-{i}', f'm-{i}', f'w-{i}', f'h-{i}', f'gap-{i}'] if pool_kind == 'small': pool = pool[:150] if pool_kind == 'variants': base = pool[:]; pool = [] for v in ['', 'hover:', 'md:', 'dark:', 'focus:', 'lg:hover:']: pool += [v + b for b in base] pool = list(dict.fromkeys(pool)) used = set() for i in range(n_files): cls = random.sample(pool, per_file) used.update(cls) (root/'src'/f'f{i}.html').write_text('
x
\n') (root/'app.css').write_text('@import "tailwindcss";\n@source "./src";\n') print(pool_kind, 'pool', len(pool), 'unique used', len(used)) Commands (each project folder needs node_modules reachable, e.g. a link to the one above; build FROM INSIDE the project folder): py gen.py 500 30 small g_small ; py gen.py 500 30 base g_base ; py gen.py 500 30 variants g_variants cd g_small node ../node_modules/@tailwindcss/cli/dist/index.mjs -i app.css -o out.css (and again with --minify) gzip -c out.css | wc -c Results (one Windows laptop): project distinct classes plain --minify minified+gzip small 150 18,992 B 13,605 B 3,072 B (plain gzip 3,929 B) base 785 53,825 B 41,673 B 7,050 B (plain gzip 7,626 B) variants 4,513 (of 4,710) 326,471 B 239,489 B 29,008 B (plain gzip 32,550 B) Settings on the small project (minified): default 13,605 B | @import "tailwindcss" theme(static); 27,524 B | theme.css + utilities.css only (no preflight) 9,953 B | --optimize without --minify 17,309 B Build time: npx @tailwindcss/cli ... : about 3.4-3.7 s for every project (npx start-up) node .../dist/index.mjs, cold build, variants project: Done in 225 ms, 328 ms, 218 ms ; small project: 120 ms, 121 ms, 251 ms watch mode: node .../index.mjs -i app.css -o out.css --watch=always (plain --watch exited at once in a non-interactive shell) start-up 356 ms; after appending classes to content files: several Done lines of 5, 48, 4, 69, 6, 33, 82, 66 ms and 401 us; after adding a @theme colour to app.css: 270 ms and the new bg-zz rule was in the output WHY THIS WORKS AS AN ANSWER --------------------------- The three sizes grow with the number of distinct class-plus-variant combinations (150 -> 785 -> 4,513), not with the file count, which was 500 in every case. Variants multiply rules: the same 785 classes with five variant prefixes made the minified output 5.7 times larger. Gzip shrinks the larger outputs less in proportion than the smallest (3,072 B of 13,605 B against 29,008 B of 239,489 B). theme(static) doubled the small output because it writes every theme variable; the default only writes variables that are used. Dropping preflight saved 3.6 KB but removes the reset, which I did not check against real pages. The timing lesson is in the build commands: the first measurement (npx) said 3.5 s everywhere; the program itself, timed by its own "Done in" line, took 120-330 ms. In watch mode content edits cost far less than a cold build, and an edit to the CSS file cost about as much as one. Also note what went wrong first: building all three projects from their parent folder produced the same 328,215 B each time, because the scanner starts at the working directory and read all three. I did not check Tailwind's release-note speed claims and did not time a bundler.