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 Compile Plugin Laravel Package

civicrm/composer-compile-plugin

Composer plugin that adds a lightweight compile step for CiviCRM extensions and other PHP packages. Declare compile tasks in composer.json and it runs them after install or update, skipping unchanged packages via caching. A composer compile command allows manual rebuilds.

Deep Wiki
Context7

Getting Started

1. Install the plugin in the root project (it is a Composer plugin, not a library):

composer require --dev civicrm/composer-compile-plugin

Composer 2.2+ will refuse to load it unless you allow it. Either answer y at the prompt or add explicitly:

{
  "config": {
    "allow-plugins": {
      "civicrm/composer-compile-plugin": true
    }
  }
}

2. Where to look first. Two places, in this order:

  • The extra.compile block of any installed package that uses it — that is the entire public API surface. composer show -a <vendor/pkg> then read the package's composer.json in vendor/.
  • The package's own README for the exact task schema (type, name, path, script/command keys) for the version you pinned. The plugin is small and low-traffic; treat the README shipped with your pinned tag as authoritative over blog posts.

After a run, inspect the package directory under vendor/ — you should see generated artifacts plus a marker/state file the plugin uses to remember that compilation already happened.

3. First use case. You maintain an internal package that ships sources (SCSS, TypeScript, a .phar build script, generated PHP proxies) and you want consumers to get built output on composer install without committing it. Add a compile task to that package's composer.json, then in a scratch project requiring it via a path repository, run composer install -vvv and watch the task execute. That loop — path repo + -vvv — is the fastest way to learn the plugin.

Implementation Patterns

Declaring tasks (in the library/consumer package, not the root):

{
  "name": "acme/widgets",
  "extra": {
    "compile": [
      {
        "name": "Build CSS/JS",
        "type": "script",
        "path": ".",
        "script": ["npm ci", "npm run build"]
      }
    ]
  }
}

Tasks run in listed order, in the package's own directory, when the package is installed or updated. Ordering across packages follows Composer's install graph, so a package whose compile step depends on another package's output should declare that dependency in require (not just assume ordering).

Library vs. root split. The golden rule: libraries declare extra.compile; only the root project installs the plugin. If a library puts the plugin in its own require, you force a plugin (and arbitrary install-time code execution) onto every consumer. Document instead: "If you install from source, add civicrm/composer-compile-plugin to your root require-dev."

Dev-vs-prod gating. Putting the plugin in the root's require-dev means composer install --no-dev in production won't load it, so no compilers (Node, Sass, etc.) are needed on prod boxes. Ship prebuilt artifacts for prod, or accept that prod installs from source will be missing generated files — decide deliberately and write it down.

Root-project build hooks. For your own code, plain Composer scripts (post-install-cmd, post-update-cmd) is simpler and needs no plugin. Reach for this plugin specifically when the build step must live inside a dependency's composer.json so it travels with the package.

CI pattern. Cache node_modules/compiler toolchains, run composer install, then assert the expected artifact exists (a file-existence check in a test) rather than trusting exit codes alone. Compilation is a side effect; make it observable.

Local development loop.

{
  "repositories": [{ "type": "path", "url": "../widgets", "options": { "symlink": false } }],
  "require": { "acme/widgets": "*" },
  "require-dev": { "civicrm/composer-compile-plugin": "^0.x" }
}

"symlink": false is important: with symlinks, the "package directory" is your working copy, and compile artifacts land in your source tree instead of a disposable vendor/ copy — which is sometimes what you want, sometimes a mess.

Gotchas and Tips

  • Silent no-op is the #1 failure mode. Missing allow-plugins means the plugin never loads and nothing is printed. composer install -vvv and look for plugin/event lines before debugging anything else.
  • vendor/ is disposable. Compiled output lives inside vendor/<pkg> and is wiped by composer update, composer reinstall, and often by rm -rf vendor. Never hand-edit or point production at a hand-patched build; if you need persistence, commit the artifacts to the package repo and make the compile step optional.
  • Marker files cause "it didn't run." The plugin avoids recompiling packages it already compiled. To force a re-run: composer reinstall <vendor/pkg> (Composer 2.4+) or delete the package's marker/state file. Check the README for the exact filename and any force/refresh environment variable before inventing your own workaround.
  • Toolchain availability is the real dependency. npm, node, sass, php extensions, network access to registries — none of this is declared by extra.compile. A task that needs network will fail on air-gapped build agents. Prefer tasks that use vendored/local tools, and pin tool versions in the command itself (e.g., npx --no-install).
  • Cross-platform shells. script tasks execute through the shell; rm -rf, cp -r, and && chains behave differently on Windows. If Windows matters, write a small PHP script and invoke php build.php instead of shell syntax.
  • Idempotency and exit codes. Tasks should be safe to re-run (a second npm run build shouldn't corrupt anything) and must exit non-zero on failure — a compile that "succeeds" while emitting broken output is worse than a failed install. Add a post-task artifact check where you can.
  • Security posture. This is install-time arbitrary code execution by design. Keep it out of require in libraries, pin the plugin version in the root, and review any third-party package that declares extra.compile the same way you'd review a post-install-cmd script.
  • Extension points are minimal. There is no task-plugin API to extend in most versions — it is a thin orchestrator. If you need conditional logic, fan-out, or artifact checksumming, put it inside the script you invoke (a PHP/Node build entry point) rather than trying to express it in extra.compile.
  • Pin and re-verify on upgrade. Low stars, small maintainer surface: pin an exact-ish constraint, and after any plugin bump re-run your path-repo smoke test to confirm the task schema and marker behavior haven't shifted.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console