DEV Community

Dk Usa
Dk Usa

Posted on

Vite predev/prebuild: chaining scripts without losing your mind

A project I'm working on needs 3 things to happen before dev/build:

  1. Hash legal content (license, terms) to detect changes.
  2. Split a huge GeoJSON file into per-region chunks.
  3. Generate static SEO landing pages from a metadata JSON. npm's pre- scripts hook into dev and build automatically. But chaining 3+ steps gets messy fast. ## What I tried first

json
{
  "scripts": {
    "predev": "node scripts/hash.js && node scripts/split.js && node scripts/gen.js",
    "prebuild": "node scripts/hash.js && node scripts/split.js && node scripts/gen.js",
    "dev": "vite",
    "build": "vite build"
  }
}
Works. Two problems:

Duplication: predev and prebuild are identical. Add a 4th step and you change two places.
Hard to debug: if step 2 fails, the error reaches you but the chain stops without context.
The cleaner pattern
Single orchestrator script that runs them in order with logging:

// scripts/prebuild.js
import { spawnSync } from 'node:child_process';

const STEPS = [
  ['hash-legal', 'scripts/hash-legal-content.cjs'],
  ['split-geojson', 'scripts/split_parcelas_by_sm.cjs'],
  ['gen-landings', 'scripts/generate_landings.js'],
];

for (const [name, file] of STEPS) {
  console.log(`▶ ${name}`);
  const start = Date.now();
  const res = spawnSync('node', [file], { stdio: 'inherit' });
  if (res.status !== 0) {
    console.error(`✗ ${name} failed (exit ${res.status})`);
    process.exit(res.status);
  }
  console.log(`✓ ${name} (${Date.now() - start}ms)`);
}
Then package.json:

{
  "scripts": {
    "predev": "node scripts/prebuild.js",
    "prebuild": "node scripts/prebuild.js",
    "dev": "vite",
    "build": "vite build"
  }
}
Add a 4th step? One line in the orchestrator. Want to skip a step in dev? Filter STEPS by env var. Want timing per step? Already in the log.

Bonus: parallel steps
If two steps are independent (don't write to the same file), run them in parallel:

await Promise.all([
  runStep('hash', '...'),
  runStep('split', '...'),
]);
await runStep('gen-landings', '...');
Cuts predev time roughly in half on my project.

Small refactor, much less friction every time I add a build step.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)