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

Php Assets Laravel Package

rumenx/php-assets

Rumenx PHP Assets is a lightweight PHP library for managing frontend assets. It helps compile, combine, minify, version, and cache CSS and JavaScript files, giving PHP and Laravel applications a simple way to organize and serve optimized assets.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by installing the package and verifying what it actually manages for you versus what your build tool already handles.

composer require rumenx/php-assets

Where to look first:

  1. The published config — run php artisan vendor:publish --tag=php-assets-config (or the package's equivalent tag from its README). This is the single source of truth for asset roots, manifest location, CDN base URL, and cache busting strategy. Read it top to bottom before writing any code.
  2. The facade / helper surface — check whether the package exposes a Assets:: facade or a global asset_versioned() style helper. Most Laravel developers will only ever touch this one API.
  3. The manifest resolver — the class that reads your Vite/Mix/environment manifest. This is where 90% of "why isn't my asset updating?" bugs live.
  4. The service provider — confirm it registers a singleton and whether it's auto-discovered or needs to be added to config/app.php (it usually is auto-discovered on Laravel 9+).

First use case: Replace asset('css/app.css') with the package's versioned call in resources/views/layouts/app.blade.php. That is the smallest possible change that gives you cache busting across deployments without pulling in Vite's full manifest tooling.

{{-- before --}}
<link rel="stylesheet" href="{{ asset('css/app.css') }}">

{{-- after --}}
<link rel="stylesheet" href="{{ Assets::url('css/app.css') }}">

Once that renders a hashed or query-string URL, you've validated the whole pipeline (config → manifest → URL resolver). Everything else is incremental.


Implementation Patterns

Pattern 1: Single entry point in a Blade layout

Wrap the package behind a Blade component or partial so your views never call the package directly. When you swap to Vite, a CDN, or a different asset tool, you edit one file.

{{-- resources/views/components/assets.blade.php --}}
@props(['entry' => 'resources/js/app.js'])
<link rel="stylesheet" href="{{ Assets::url($entry) }}">
<script src="{{ Assets::url($entry) }}" defer></script>

Usage: <x-assets entry="resources/css/app.css" />.

Pattern 2: Manifest-backed versioning (Vite/Mix)

Point the config at your build manifest (public/build/manifest.json or public/mix-manifest.json). The package resolves logical names to hashed filenames. This is the pattern most Laravel teams will use because it lets you keep Vite for building but resolve URLs on the server side in places Vite's @vite directive doesn't cover (emails, PDFs, API responses that embed asset URLs, non-Blade templates).

// config/php-assets.php
return [
    'manifest' => public_path('build/manifest.json'),
    'strategy' => 'manifest',
];

Pattern 3: Strategy switching per environment

Use the environment to pick a versioning strategy: query-string in local, manifest in staging/production, CDN prefix in production. Keep this in a dedicated config key rather than branching in code.

'strategy' => env('ASSET_STRATEGY', app()->environment('production') ? 'manifest' : 'query'),
'cdn' => env('ASSET_CDN_URL'), // null in local, e.g. https://cdn.example.com in prod

Then Assets::url() automatically picks the right behavior. No if (app()->environment(...)) scattered across views.

Pattern 4: Inject, don't app(), in application code

Where the package supports DI (most do), resolve the asset manager from the container in controllers, jobs, and mailables rather than using helpers. This makes tests trivial — swap in a fake implementation that returns predictable URLs.

public function __construct(private Assets $assets) {}

public function show(): View
{
    return view('show', [
        'thumbnail' => $this->assets->url('img/placeholder.png'),
    ]);
}

Pattern 5: Asset bundles / named groups

If the package supports named groups (e.g. Assets::group('admin')->all()), use them for admin vs. public layouts. Groups keep the "which CSS do I load on this page" question out of the templates.

Pattern 6: Integration with @vite where it already fits

Do not replace @vite in Blade templates that already work — it handles HMR, preloads, and module scripts correctly. Use the package for:

  • Emails, PDF templates, and other non-Blade render paths.
  • Server-rendered Open Graph og:image URLs.
  • API responses returning image/PDF URLs that need a CDN prefix.
  • Admin panels or legacy Blade views that still use mix()/asset().

This is the highest-value usage pattern for an existing Laravel app: it's a bridge, not a replacement.

Pattern 7: Preload/prefetch and CSP nonces

If the package exposes <link rel="preload"> generation or lets you set attributes, generate those in a service provider or view composer and attach the CSP nonce from your middleware.

$preloads = $assets->preload(['fonts/inter.woff2']);

Render them in <head> before any stylesheets.


Gotchas and Tips

The manifest path is absolute and cached

public_path('build/manifest.json') is evaluated when the container boots. If you cache config (php artisan config:cache) and run config:cache before a build runs in CI, the manifest path may be correct but the contents are read lazily — check whether the package caches the parsed manifest in memory per request. If it does, long-running workers (Horizon, Octane, queue workers) will serve stale hashes until restarted. Add a deploy hook: php artisan octane:reload (or queue:restart) after assets are built.

Local dev vs. production divergence

The classic failure: production is fine, staging renders broken asset URLs. Causes:

  • Manifest published to a different directory than configured (.env not copied).
  • CDN URL set in prod config that points to a hostname only reachable from inside the VPC.
  • Relative vs. absolute path handling differs — always test with curl against the rendered HTML, not just the browser.

Rule: after every deploy, run curl -s https://staging.example.com | grep -o 'href="[^"]*"' and confirm the URLs resolve.

CDN prefixing and leading slashes

Most asset packages do rtrim($cdn, '/') . '/' . ltrim($path, '/') — but some don't. If you see https://cdn.example.com//css/app.css (double slash), that's your cue to check the package's URL builder. Some CDNs tolerate it, Cloudflare doesn't always.

Versioning strategy must be consistent across PHP and Blade

If the package's Assets::url() returns ?v=abc123 but @vite returns /build/assets/app-abc123.js, you have two versioning systems. Pick one per view. Mixing them causes double-loading of the same asset under different URLs, which blows up cache hit rate and can cause duplicate-side-effect bugs (two Vue instances, two analytics scripts).

Windows path separators

If you develop on Windows and deploy to Linux, backslashes in the manifest (rare but happens with some bundlers) will break str_replace-based path normalization. Check that the package uses DIRECTORY_SEPARATOR or str_replace('\\', '/', ...). If not, normalize the manifest keys yourself in a small custom resolver.

Cache invalidation of the manifest itself

Your server may cache the parsed manifest for N seconds (check config for a cache_ttl key). When you deploy new assets, the manifest changes but the server keeps serving old URLs. Solutions:

  1. Set the TTL to 0 (parse per request — fine for typical manifests of a few KB).
  2. Bump a config value on deploy that changes the cache key.
  3. Restart workers.

Don't guess — grep the package source for cache-> calls.

Testing: don't hit the filesystem

In feature tests, bind a fake asset manager that returns deterministic URLs (/fake-assets/foo.css). This keeps tests fast and independent of whether npm run build ran. Only the single integration test that exercises the real resolver should touch the filesystem.

$this->app->instance(Assets::class, new class implements Assets {
    public function url(string $path): string { return "/fake/{$path}"; }
});

Extension points worth knowing

  • Custom resolvers / drivers — if the package ships a driver interface (many do for "manifest", "query string", "static"), you can register your own for bespoke versioning (e.g., reading from S3 or a Redis-backed manifest). Check config for a drivers array.
  • Events — some asset packages fire AssetResolved / AssetMissing events. Hook AssetMissing to log rather than throw in production, so a single missing image doesn't 500 the page.
  • Macros — if the manager uses Laravel's Macroable trait, add application-specific helpers (Assets::ogImage()) in a service provider instead of subclassing.

When to reach for something else

If you're already using Vite in a standard Laravel app and only need Blade templates, @vite covers you — this package earns its keep when you have non-Blade render paths, multiple build tools, or a CDN layer you want to manage centrally. If you're on Vite 5+ with a monorepo, look at laravel-vite-plugin's multi-entry support before adding a second asset layer.

Version pinning

The last release is recent (Sept 2025) and the package is at 0.x-level maturity by dependent count (0). Pin to an exact minor version in composer.json ("rumenx/php-assets": "~1.2.0") and commit composer.lock. Read the changelog before every bump — asset URL generation is the kind of thing that produces silent visual regressions, not exceptions.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings