eloquent/composer-npm-bridge
Composer NPM Bridge lets Composer manage your npm dependencies, installing packages and running build scripts alongside composer install or update. One toolchain, one command, fewer setup steps for Laravel and PHP projects.
Architecture fit. eloquent/composer-npm-bridge is a Composer plugin that hooks Composer's install/update lifecycle and shells out to npm for dependencies declared in a package's composer.json (extra.npm). Conceptually it solves a real 2016-era problem: PHP packages that shipped frontend assets had no way to declare their Node dependencies to the consuming application. For a modern Laravel estate this fit is poor. Laravel 9+ ships Vite by default, packages increasingly publish source or prebuilt assets rather than forcing a consumer-side npm install, and the Composer/NPM boundary is now normally managed explicitly rather than by a plugin reaching across it. The package assumes a single npm binary, a single lockfile, and a flat dependency graph — assumptions that break under pnpm/yarn/bun, npm workspaces, or monorepos.
Integration feasibility. Mechanically simple to install (one Composer require plus an extra.npm block), but that simplicity is the trap. It only works where Composer plugins are permitted; since Composer 2.2, plugins must be explicitly allow-listed via allow-plugins, which means every developer machine and CI runner needs a config change. It has no awareness of Node version managers (nvm/asdf/Volta), so it will invoke whatever npm is on PATH — a frequent source of "works on my machine" drift. There is no native Laravel service provider integration; it operates entirely at the Composer layer, so Laravel's own asset build (npm run build, Vite) still has to be wired separately.
Technical risk. High, and concentrated in three areas. First, abandonment: the repository is archived, the last release was 2020-11-23, and there is no path to a CVE fix. Second, Composer 2 plugin API compatibility is unverified against current Composer 2.7+/2.8 and PHP 8.3/8.4 — the release cadence predates most of that surface. Third, supply chain: the plugin executes npm install at Composer time, which is exactly the automated, credential-adjacent install path that registry-attack guidance tells us to constrain. A transitive npm compromise becomes a Composer-time compromise on every developer laptop and build agent.
Key questions.
extra.npm, and is the bridge still the only thing installing their Node deps?allow-plugins locked down, and if so has this plugin been explicitly allowed?npm install in each package README?composer-plugin successor) the community has consolidated around?Stack fit. Poor for a Vite-era Laravel application; marginal even for a legacy Mix-era one. The bridge is only defensible if we have PHP packages that (a) genuinely need Node dependencies installed by the consumer, (b) target npm specifically, and (c) we cannot restructure. In a typical Laravel monorepo using npm/pnpm workspaces, the bridge duplicates and fights the workspace resolver.
Migration path. Treat this as a sunset, not an adoption. Concretely: inventory extra.npm usage across first- and third-party packages; for each, move the Node dependency declaration into the package's README/installation docs or into a package.json published alongside it; for packages we own, prefer spatie/laravel-package-tools with publishable assets or prebuilt bundles so consumers never run npm install on our behalf. Remove the plugin and its allow-plugins entry once the inventory is empty.
Compatibility. Verify against Composer 2.x plugin API, PHP 8.2+, Node 18/20/22, and the npm version bundled with each. Also verify behavior when npm is absent or the registry is unreachable — historically these paths produced noisy but non-fatal failures. Do not assume Composer 1 guidance from the README applies.
Sequencing.
extra.npm declarations and current composer.json plugin allowances.extra.npm usage via a lint rule or code review checklist.allow-plugins entry, and delete any cached artifacts.Maintenance. Effectively zero upstream maintenance and no security response. Every Composer or PHP minor bump becomes an unowned compatibility question for us. Budget for a periodic review that has no upstream to escalate to.
Support. None. Archived repository, no issue triage, no maintainer. Internal support means one of our engineers reading the plugin source — feasible (it is small) but a recurring tax.
Scaling. The plugin adds an npm install to every composer install, including in CI containers and ephemeral preview environments, with no caching strategy of its own. Build times scale linearly with the number of packages declaring Node deps, and cold-cache CI jobs pay the full registry round-trip. Under workspaces or monorepos it can produce duplicated or conflicting node_modules trees.
Failure modes.
npm missing or wrong version on PATH in CI or on a new hire's machine.node_modules with no rollback.Ramp-up. Individually low — the plugin is small and its extra.npm contract is easy to learn. Organizationally high: the knowledge is undocumented outside the archived README, and the people who introduced it have likely moved on. The real onboarding cost is teaching new engineers why we are removing it.
Recommendation. Do not adopt. If already present, scope a removal within one or two quarters; the risk is unowned compatibility and supply-chain exposure, not feature gaps. The underlying need — declaring frontend dependencies for PHP packages — is better served by documented package.json files, publishable assets, and standard npm workspace tooling.
How can I help you explore Laravel packages today?