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

Elixir Bundle Laravel Package

gubler/elixir-bundle

A Symfony bundle for integrating Laravel Elixir asset versioning. It provides a Twig helper that reads the Elixir manifest and returns cache-busted CSS and JavaScript paths, simplifying front-end asset management in Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

gubler/elixir-bundle is a thin Symfony adapter around Laravel Elixir — the gulp-based asset pipeline that shipped with Laravel 5.0–5.3. If you're coming from Laravel, the mental model transfers almost 1:1: same gulpfile.js, same mix.sass()/mix.scripts()/mix.version() API, same elixir() helper name — except the helper is exposed to Twig instead of Blade, and paths resolve against your Symfony web/ (or public/) directory instead of public/.

Minimal steps

composer require gubler/elixir-bundle

Register the bundle (app/AppKernel.php on Symfony 2/3, or config/bundles.php on 4+):

new Gubler\ElixirBundle\GublerElixirBundle(),

Then bring your own Node toolchain — the bundle does not ship gulp or Elixir:

npm init -y
npm install --save-dev gulp@3 laravel-elixir

Create a gulpfile.js at the project root exactly as you would in Laravel:

var elixir = require('laravel-elixir');

elixir(function (mix) {
    mix.sass('app.scss', 'web/css/app.css')
       .scripts(['app.js', 'vendor.js'], 'web/js/app.js');

    if (process.env.NODE_ENV === 'production') {
        mix.version(['css/app.css', 'js/app.js']);
    }
});

Where to look first

  1. DependencyInjection/Configuration.php — the config keys (public_dir/build_dir/manifest path naming varies between releases; read the tree, don't guess). As of v0.3.0 there is also a prefix URL key (added for CDN/subdirectory hosting — verify the exact name in the config tree, it's not documented in the release note).
  2. The Twig extension class under Twig/ — this is where the elixir() function is defined and where the manifest is read. This is also where the new prefix is applied to the resolved URL.
  3. Resources/config/services.xml (or .yml) — the service IDs you'd override to customize path resolution.

First use case

The whole point is cache-busted asset URLs in Twig without Assetic:

<link rel="stylesheet" href="{{ elixir('css/app.css') }}">
<script src="{{ elixir('js/app.js') }}"></script>

In dev (no manifest) this should return the plain path; in prod (after mix.version()) it returns /build/css/app-8f3a1c.css. With v0.3.0's prefix configured, that becomes https://cdn.example.com/build/css/app-8f3a1c.css.

Implementation Patterns

Keep gulp out of the request cycle. The bundle is a resolver, not a compiler. Never shell out to gulp from a controller or a console command that runs in prod. Build in CI or at deploy time:

# .github/workflows/deploy.yml (sketch)
- run: npm ci
- run: NODE_ENV=production ./node_modules/.bin/gulp --production
- run: php bin/console cache:clear --env=prod

Layout-level helper with a dev fallback. Because the manifest only exists after a versioned build, template authors hit "manifest not found" constantly. Wrap it once:

{# templates/_assets.html.twig #}
{% macro asset(path) %}
    {{ elixir(path) }}
{% endmacro %}

…or configure the bundle so a missing manifest falls back to the unversioned path (check whether your version supports a fallback/strict option — early versions simply threw).

Serve assets from a CDN or subdirectory with the new prefix option (v0.3.0). This is the headline change in the release and the most useful one since 2017: instead of overriding the Twig extension service just to swap a host, set the prefix config and let the helper prepend it.

# config/config.yml (name/path depends on Symfony version — check Configuration.php)
gubler_elixir:
    public_dir: '%kernel.root_dir%/../web'
    build_dir:  '%kernel.root_dir%/../web/build'
    prefix:     'https://cdn.example.com/assets'

Caveats: the prefix is a URL rewrite only — it does not copy files to the CDN and it does not change where the manifest is read from. Your deploy pipeline still needs to sync web/build/ to the CDN origin, and the prefix must be a plain string with no trailing-slash ambiguity (see Gotchas).

Mirror the Laravel directory shape. Everything in the bundle assumes Elixir's defaults: source in resources/assets/{sass,js}, output to public/build/..., manifest in public/build/rev-manifest.json. On Symfony that usually means mapping public_dir to web/ and build_dir to web/build. Don't fight the defaults — you'll spend an afternoon on path joins.

Concatenate, don't bundle. Elixir predates ES modules. The idiomatic workflow is mix.scripts([...]) to concatenate an ordered list of plain <script> files, and mix.styles([...]) for vendor CSS. Order matters and is the most common source of "works in dev, breaks in prod" bugs.

Versioning strategy. Only version files you actually reference from Twig. mix.version(['css/app.css', 'js/app.js']) writes hashed copies plus the manifest — the originals stay in place, so a stale manifest is silently served rather than 404ing.

Watch mode during development. Run gulp watch in one terminal alongside php bin/console server:run (or your Docker stack). Elixir's watch is file-polling-based and CPU-hungry on large trees; scope it with mix.sass('app.scss', ...) rather than directory-wide tasks.

Versioning without Elixir's manifest. If you need to keep using this bundle but want off gulp, the manifest is just JSON. Any build tool that emits {"css/app.css": "css/app-8f3a1c.css"} at the configured path will satisfy the Twig extension. That's the cleanest extension point in the whole package — and it composes cleanly with the prefix option, so you can keep the elixir() call and prefix while swapping the build tool underneath.

Gotchas and Tips

This is a dead-end dependency. The bundle's last release before v0.3.0 was 2017-01-30, the same month Laravel deprecated Elixir in favour of Laravel Mix (webpack). v0.3.0 is a one-commit community contribution (prefix URL) that does not modernise the stack — gulp 3 and the Symfony ceiling below are unchanged. It is archived, has 3 stars, and zero dependents. You are the only person debugging it. Treat adoption as accepting ownership of a frozen, unmaintained adapter.

gulp 3 does not run on modern Node. Elixir pins gulp ^3, whose graceful-fs@3 / natives chain throws ReferenceError: primordials is not defined on Node ≥ 12. Workarounds are Node 8/10 in a container, or pinning [email protected] via resolutions/overrides — neither is a long-term answer. This alone makes the package impractical on any current stack.

Symfony version ceiling. The bundle targets Symfony 2.x/3.x. On Symfony 4+ you'll fight composer require constraints; on Symfony Flex there's no recipe, so bundle registration is manual. On Symfony 5.4+/6+/7+ it simply won't install without --ignore-platform-reqs-style hacks. v0.3.0 did not widen these constraints.

Prefix URL is a string rewrite, not a deployment story (v0.3.0). Two failure modes are easy to introduce:

  • Double slash — prefix: 'https://cdn.example.com/assets/' plus a manifest value css/app-8f3a1c.css can yield //. Normalise the prefix (no trailing slash) and confirm how the extension concatenates — do not assume.
  • Missing files at the CDN origin — the prefix changes the URL, not the build output. If your CDN isn't synced from web/build/, you get a 200 from Symfony locally and a 404 from the CDN in prod. Your CI must sync before/with cache:clear --env=prod.
  • Dev leakage — if the prefix is set globally, template output in dev now points at the CDN for unversioned files that may not exist there. Consider scoping the prefix to the prod environment config only.

Manifest path mismatches are the #1 support ticket. Three (or four, once you add a prefix) places must agree: Elixir's public.build.path in gulpfile.js, the bundle's public_dir/build_dir config, the URL prefix Symfony serves from, and now the new prefix URL. A trailing slash or a web vs public rename produces "file exists but 404s."

Case sensitivity bites on deploy. macOS dev + Linux CI: mix.sass('App.scss') finds app.scss locally but not in prod. Standardize filenames early.

CSS url() references are not rewritten. Elixir doesn't process relative paths inside compiled CSS. If app.scss references ../images/logo.png and you version, relocate, or prefix the output, those links break silently. The prefix option makes this worse, not better: absolute URLs in CSS are unaffected by it, so you can end up with a CSS file served from the CDN that still requests images from your origin. Serve images/fonts from a fixed, unversioned path.

Missing manifest = 500, not a fallback. Verify the behaviour of your exact version before relying on it in prod. Safest pattern: build assets before cache:clear --env=prod so nothing renders without the manifest present.

Debugging checklist: (1) does rev-manifest.json exist at the configured path? (2) does the key exactly match the string you pass to elixir() (leading slash vs not)? (3) is the Twig extension actually registered (debug:container | grep elixir)? (4) is NODE_ENV set during build — the --production flag is what triggers versioning? (5) with a prefix set, does the emitted URL match reality when you curl it from the CDN host?

Extension points worth knowing: the Twig extension service can be overridden to inject a custom manifest reader or a dynamic prefix (useful for S3/CDN-hosted assets where the host differs per environment); the DI configuration tree lets you relocate the manifest and, since v0.3.0, set a static prefix. Those are the only real integration surface — everything else is gulp's problem.

Verdict for day-to-day work: don't adopt it in 2024+. The v0.3.0 prefix option is a welcome convenience but does nothing about gulp 3 on modern Node or the Symfony ceiling, so it doesn't change the recommendation. If you're porting a Laravel 5.1-era app to Symfony, use Webpack Encore (the same mental model, maintained, Symfony-native) or AssetMapper (no Node at all). If you inherited a codebase already on this bundle, the lowest-risk exit is to keep the elixir() Twig call and the prefix option, replace gulp with a small script that emits a compatible rev-manifest.json, then swap the Twig function for asset() and drop the bundle entirely.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib