HarperFast / HarperFast/harper

Component deploys install devDependencies; omitting them needs build-at-start gating, not a global default

Open
#2,092 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## Summary

Component deploys currently run `npm install --force --ignore-scripts`, which installs `devDependencies`. The suggestion on the table is to make deploys production-only (`npm install --omit=dev --no-audit --no-fund`). The reasoning is sound — but a naive global default breaks the most common non-trivial deploy shape, so the gating needs to be derived rather than flagged.

## Current behavior

`installApplication` in `components/Application.ts` has three install paths:

1. **Custom command** — `install.command` is spawned verbatim (`Application.ts:892`). Unaffected by any default-args change.
2. **`devEngines.packageManager`** — ` install`, plus `--ignore-scripts` unless `install.allowInstallScripts` (`Application.ts:962`).
3. **Default** — `npm install --force --ignore-scripts` unless `install.allowInstallScripts` (`Application.ts:1011-1013`).

Separately, the deprecated `install_node_modules` operation **already** passes `--omit=dev` (`utility/npmUtilities.ts:40`), so the two installation paths disagree today.

## Why omitting dev deps is mostly safe

The obvious objection is "some apps keep build tools in `devDependencies` and build on deploy." In the default configuration that build **cannot happen**: `--ignore-scripts` is the default, so a component's `prepare` / `postinstall` never runs on deploy unless the operator sets `install_allow_scripts`. In that default config the installed `devDependencies` are already dead weight — no code path can consume them.

Git-reference deploys are also unaffected. `npm pack` on a git ref clones the repo and runs its own install (including dev deps) plus `prepare` inside the clone; that's where a git-sourced build actually happens, and it does not go through the args above.

## Why a global default still breaks today

The gap is not npm scripts — it's **framework plugins that build in-process at component start**, bypassing the npm script mechanism entirely and therefore unaffected by `--ignore-scripts`.

`@harperfast/nextjs` defaults to `prebuilt: false` and calls `nextBuild` when the component starts (`src/plugin.ts:246`). `next build` requires typescript / postcss / tailwind / swc at build time, and `create-next-app` places all of those in `devDependencies`. A real customer Next.js app on Harper has `typescript` and `@swc/core` in `devDependencies` with `build: "next build --webpack"`.

So `--omit=dev` as a global default would break source-deployed Next.js apps — likely our most common non-trivial deploy.

## Proposal

Rather than "default on with an opt-out," tie dev-dependency omission to whether a build is possible at all:

- Omit `devDependencies` **unless** `install.allowInstallScripts` is set, **or** a loaded plugin declares that it builds at component start.
- `@harperfast/nextjs` either declares that need, or — preferably, and more consistent with the staged-artifact model — defaults `prebuilt` to `true` and expects a real prior build step.

This adds no operator-facing flag, changes nothing for anyone whose build works today, and stops installing dev dependencies in the (common) case where nothing can consume them.

Interim option if the plugin-declaration mechanism is too large for one change: add `install.omitDev` defaulting to `false`, then flip the default in a major once nextjs declares or changes its `prebuilt` default.

## Split out: `--no-audit --no-fund`

These two are unambiguous — pure output-noise and latency reduction with no semantic effect on the installed tree. Worth adding to the default args independently of the `--omit=dev` decision.

## Acceptance

- [ ] `--no-audit --no-fund` added to default deploy install args
- [ ] Mechanism for a plugin to declare "builds at component start"
- [ ] `--omit=dev` applied when no build is possible (no install scripts, no build-at-start plugin)
- [ ] `@harperfast/nextjs` declares its build-at-start need or defaults `prebuilt: true`
- [ ] `install_node_modules` / deploy install behavior reconciled
- [ ] Documented, including how an operator restores dev dependencies

Contributor guide

Open the contributing guide

Research direction

Start by reading installApplication in components/Application.ts, the deprecated path in utility/npmUtilities.ts, and the Next.js build-at-start entry point in src/plugin.ts. Trace how install scripts and plugins determine whether a build can consume devDependencies, then verify the acceptance items, including reconciled install behavior and documentation.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, next.js, node.js
Domain
build-system, devops
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.