build-pipeline
GitHub解析并修复 Tabler 前端资源构建流水线,涵盖 Astro 集成、Vite/Terser 构建及目录同步机制。用于解决资产缺失、冲突或生成异常等问题。
Trigger Scenarios
Install
npx skills add tabler/tabler --skill build-pipeline -g -y
SKILL.md
Frontmatter
{
"name": "build-pipeline",
"description": "Understand or repair the Tabler asset pipeline — `core\/dist`, `tmp-assets\/`, the generated `public\/` directories, the `copy-assets` Astro integration, `build-css.ts`, the vite\/terser JS builds and the turbo dev graph. Use when assets are missing, stale, duplicated or growing between builds, when a watcher's output disappears after a restart, when a page 404s on `\/dist\/css\/tabler.css`, and before editing anything under `.build\/`, a package's asset manifest in `astro.config.mjs`, or the dev\/build scripts."
}
The asset pipeline
Astro only renders pages. Every stylesheet, script, font and image on a page arrives through a separate pipeline, and almost every "weird assets" bug is a directory being written by the wrong step.
1. Who writes what
| Directory | Written by | Notes |
|---|---|---|
core/dist/ |
@tabler/core (css:dev, js:build, copy) |
the framework: css, js, fonts, img, vendored libs |
preview/tmp-assets/ |
preview assets / watch:css (build-css.ts + vite/terser) |
demo css/js, isolated from Astro's output |
docs/tmp-assets/css/ |
docs css / watch:css (build-css, --no-prefix) |
docs stylesheets |
<pkg>/public/ |
copy-assets only |
fully generated, wiped and rebuilt on every Astro start |
<pkg>/dist/ |
astro build |
the shipped site |
public/, tmp-assets/ and dist/ are all git-ignored per package. Never hand-edit a file in any of them, and never commit one.
2. copy-assets (.build/copy-assets.ts)
An Astro integration, configured per package in astro.config.mjs:
- On
astro:config:doneit deletespublic/and rebuilds it from thecopiesmanifest (core dist, the package'stmp-assets,shared/static, favicons). Running it twice must never accumulate content — that is why it starts from a clean directory. - It is skipped when the Astro command is
sync, soastro check(and CI's type-check job) does not need built workspace assets. - In dev it watches
syncDirsand copies changed files intopublic/, then sends one coalescedfull-reload(250 ms window,.mapfiles ride along with their source file). allowDestinationFallbackkeeps the existing copy when the source vanishes mid-copy —@tabler/corecleaningdist/whileturbo devstarts the dependents.
Rule for watchers: copy-assets is the only writer of public/. It wipes the directory at startup, and the wipe can race a watcher that writes there directly — that was the ENOENT in #3006. Every watcher (preview's and docs' watch:css) writes into tmp-assets/css, and copy-assets syncs it into public/ via syncDirs. Do the same for anything new.
3. Ordering
turbo.json encodes the graph: @tabler/core#dev:prepare → @tabler/preview#dev:prepare → the dev tasks (docs depends on both). dev:prepare is what guarantees core/dist and preview/tmp-assets exist before a dependent package's copy-assets runs. If you add a package or an asset dependency, add the edge here too — inside a package, ordering comes from Astro's own lifecycle, not from a pre-script.
4. Traps already paid for
Do not undo these; each has a comment at the site:
- Build output must not be an Astro output dir.
preview/.build/vite.config.mtswrites totmp-assets/js, not insidedist/:astro buildcopiespublic/intodist/, so anoutDirunderdist/gets re-seeded and re-copied, growing without bound across builds. - No leading-dot output path. terser's CLI
--source-mapparser rejects a path segment starting with a dot (.build/out/…) with a bogus "not a supported option". - One write per output file.
build-css.tsruns sass + postcss + clean-css in-process so each file is written once, fully processed; it also skips writes when the content is unchanged, to keep watchers quiet. Do not reintroduce a step that rewrites a finished file in place — that is what shifted every source-map mapping when the banner was added afterwards (#2766). - Two environment variables, two questions.
NODE_ENVanswers "dev server or build?" — Vite forces it toproductionfor every build, including branch previews, so it can only pick unminified assets and the dev favicon.VERCEL_ENVanswers "which deployment?" —productionon the main hosts,previewon branch deploys, unset locally — and is the only value that may openrobots.txtor anything else that must stay off on a preview. CheckingNODE_ENV === 'preview'is never true anywhere. Both are inglobalEnvinturbo.json; a new variable read by a build must be added there or the cache ignores it. - Vendor copies are not pages.
preview'sprettify-htmlintegration formats built HTML onastro:build:donebut excludesdist/preview/anddist/dist/, which are asset copies and contain third-party HTML that breaks the parser.
5. Diagnosing
Work down this list; each step is cheap:
- 404 on
/dist/css/tabler.cssor/preview/css/demo.css— the source was never built.pnpm --dir core run dev:prepare, thenpnpm --dir preview run dev:prepare. - Assets vanished after restarting dev — something wrote into
public/thatcopy-assetsdoes not know about; it was wiped at startup. Add it to the manifest, or write it intotmp-assetsinstead. - CSS/JS edits do not appear — the watcher is not running (started
astro devalone instead of the package'sdevscript), or its output dir is not insyncDirs. - Stale content that survives a rebuild —
pnpm --dir <pkg> run clean, thendev:prepare. dist/grows between identical builds — an output dir is nested inside another copy step (see the first trap).- CI type-check fails on missing assets — something made
copy-assetsrun for thesynccommand; keep the early return.
Read the dev server's own log first: copy-assets logs public/ rebuilt from workspace assets, each fallback warning, and every reload with the file that caused it.
6. When you change the pipeline
- Verify both paths:
pnpm --dir <pkg> run devand a cleanpnpm --dir <pkg> run build. - Verify both packages when the change is in
.build/— preview and docs share those files, with different manifests. - Run the build twice in a row and compare
du -sh <pkg>/dist— equal sizes are the accumulation check. - Confirm
git statusstays clean: nothing generated may become tracked. - Do not start a build while a dev server is running (
astro-devskill).
7. Checklist
- Nothing writes into
public/exceptcopy-assets - New generated output lands in
tmp-assets/, and is listed in the package'scopies(andsyncDirswhen it changes during dev) - Cross-package ordering added to
turbo.jsonif a new dependency appeared - Dev and clean build both verified, build run twice with stable output size
-
git statusclean;pnpm run type-checkclean without prebuilt assets
Version History
- 340f719 Current 2026-09-22 21:47


