Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Composer Npm Bridge Laravel Package

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.

Deep Wiki
Context7

Getting Started

eloquent/composer-npm-bridge is a Composer plugin that teaches Composer a new package type — npm-asset — so npm packages can be required and versioned alongside PHP dependencies without a package.json in the loop. Composer resolves the package name and version constraint against the npm registry, downloads the tarball, and installs it under vendor/ next to your PHP code.

Minimum steps:

  1. Install the plugin in the root project only (Composer plugins are never loaded from transitive dependencies):

    composer require eloquent/composer-npm-bridge
    
  2. On Composer 2.2+, plugins must be explicitly allowed — otherwise Composer will prompt (or silently skip in non-interactive mode):

    {
      "config": {
        "allow-plugins": {
          "eloquent/composer-npm-bridge": true
        }
      }
    }
    
  3. Require your first asset using the npm-asset type:

    {
      "require": {
        "npm-asset/jquery": "^3.5"
      }
    }
    
    composer update npm-asset/jquery
    
  4. Confirm what landed:

    composer show npm-asset/jquery
    composer why npm-asset/jquery
    

Where to look first. Read the README section on supported package types and the installer class it registers — that pair tells you exactly which type string is honoured and what the on-disk layout will be. Then inspect the installed tree (vendor/npm-asset/... by convention) before wiring anything into a build.

The canonical first use case: a pure-PHP package (or a Laravel app) that needs a handful of front-end assets — jQuery, Bootstrap, a datepicker — and whose CI has no Node toolchain. Instead of adding node_modules, package-lock.json, and an npm ci step to the pipeline, the assets become ordinary Composer dependencies, pinned in composer.lock and deployed with the rest of vendor/. That is the whole value proposition: one dependency manager, one lockfile, one artifact.

Because the package is archived (last release November 2020), treat adoption as a small, time-boxed experiment: verify it installs and resolves on your exact PHP and Composer versions before committing a team to it.

Implementation Patterns

Constraint translation is the daily friction point. You are writing Composer constraints, not npm ranges. The mental mapping is close but not identical:

Intent Write instead of npm Use
Caret ^3.5.1 ^3.5 (widely compatible)
Tilde ~3.5.1 ~3.5
Exact pin 3.5.1 3.5.1
Any 3.x 3.x ^3.0 or >=3.0 <4.0
Range >=3.0 <3.6 >=3.0 <3.6

Pin the exact version in composer.lock by committing the lockfile, and keep the constraint loose enough in composer.json to accept patch releases. Treat composer.lock as the npm lockfile — it is the only reproducibility guarantee you get.

Serve assets through the framework, not from vendor/ directly. In Laravel:

// config/filesystems or a publish step
'vendor/npm-asset/bootstrap/dist/css/bootstrap.min.css'

Publish or copy into public/vendor/ at deploy time. In Blade, reference the published path, not the vendor path — vendor paths change with the install layout and are not web-servable by default.

Point your build tool at the vendor directory. If you do still run webpack/Vite/Sass, the assets are not in node_modules, so resolution will fail unless you tell the tool where to look:

// vite.config.js
resolve: {
  alias: { jquery: path.resolve(__dirname, 'vendor/npm-asset/jquery/dist/jquery.js') }
}
// sass-loader / dart-sass
sassOptions: { includePaths: ['vendor/npm-asset/bootstrap/scss'] }

This is the highest-value integration pattern: it lets PHP devs consume front-end packages while the JS build, if any, stays in the hands of the front-end team.

Keep the plugin in require, not require-dev. The installer only exists while the plugin is installed. If you put it in require-dev and your CI runs composer install --no-dev, the npm-asset packages become unresolvable and the install fails. The plugin is runtime infrastructure, not a test tool.

Add a guardrail to CI. Because resolution hits a remote registry:

composer install --no-interaction --prefer-dist --no-progress
composer show --direct | grep npm-asset   # sanity check in verbose builds

Cache ~/.composer/cache between runs; registry metadata and tarballs are cached there and it materially cuts install time.

Migration pattern — replace package.json incrementally. Start by declaring only assets that are stable and version-tagged on npm (Bootstrap, jQuery, Font Awesome, lodash). Leave anything that needs a bundler plugin, a postinstall script, or a peer-dependency tree in npm. Do not attempt a wholesale swap.

Extension point: the plugin is a standard Composer plugin (PluginInterface + Capable) registering an installer for its package type. If you need a different registry, a different install path, or a second asset type, the supported route is to write your own installer plugin modelled on this one and have it take over the type — you should not patch this package in place, given it is archived.

Gotchas and Tips

Archived means untested against modern stacks. The last release predates Composer 2.3+ and PHP 8.x. Before committing: run a clean composer install on your target PHP version, ideally in a container, and check for deprecation noise and any composer/composer API signature mismatches in the plugin. If it breaks, there is no upstream fix coming.

allow-plugins is the number one "nothing happened" bug. On Composer 2.2+, an un-allowed plugin is skipped, and the symptom is not an error about the plugin — it is a confusing "could not find a matching package for npm-asset/jquery" because no installer claims the type. If the type is unknown, check allow-plugins before anything else.

Plugins only load from the root project. If a library you depend on requires eloquent/composer-npm-bridge, it will not be activated. Each consuming project must require the plugin itself. This makes it unsuitable as a way to ship npm assets inside a reusable library — document the npm-asset requirements for consumers, or ship the compiled asset.

No transitive npm dependencies are installed. Requiring npm-asset/some-plugin does not pull in the packages that plugin expects in node_modules. If the asset needs a peer at runtime, you must require that peer explicitly, and you must get the version alignment right yourself. Expect to discover this the hard way in the browser console.

Prereleases and dist-tags don't translate. npm's @next, @beta, and latest tags have no Composer equivalent; Composer stability flags (@dev, @beta) operate on a different model and may not line up with npm's semver prerelease suffixes. If you need a release candidate, pin the exact version string and be prepared to test whether it resolves.

Scoped and nonstandard package names are a landmine. Composer package names are strictly vendor/package; npm's @scope/name shape and other naming surprises may not round-trip cleanly. Test one scoped package explicitly before designing around it, and prefer unscoped packages where possible.

Private registries are likely a dead end. Assume the resolver targets the public npm registry. If your organisation proxies npm through Artifactory/Nexus or uses private scoped packages, plan on a fork or an alternative approach rather than fighting it.

Debugging sequence when resolution fails:

composer clearcache                       # stale registry metadata is a common cause
composer update npm-asset/<pkg> -vvv      # shows the registry request and chosen dist
composer diagnose

clearcache first is not superstition — registry documents are cached aggressively, and a package published or re-tagged recently may not be visible until the cache is dropped.

Verify the installed tarball layout once, manually. npm tarballs typically nest contents under a package/ directory. The installer normally strips this; if you ever bypass the plugin (manual download, custom installer), that prefix will silently break your require/include paths.

Vendor is disposable — make sure deploys treat these assets as build artifacts. If your deploy strategy strips or re-installs vendor/ (common with optimized Composer deployments), the npm assets must be part of that same artifact, or republished into public/ after the install step. Getting the ordering wrong yields a green deploy and missing CSS in production.

Don't run both mechanisms for the same package. Committing node_modules or a package-lock.json that also pins Bootstrap while Composer pins npm-asset/bootstrap creates two sources of truth and guaranteed version drift. Pick one owner per asset and write it down.

Evaluate the exit before you start. Given the archived status, the realistic alternatives are fxp/composer-asset-plugin or an asset repository like Asset Packagist paired with oomphinc/composer-installers-extender, or simply accepting npm + a committed lockfile in CI. All of them are more maintained; composer-npm-bridge wins mainly on being a single, focused, low-configuration plugin — a reasonable trade for a small, stable set of pinned front-end assets, and a poor one for anything that needs to move.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource