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

Laravel Vite Helper Laravel Package

motomedialab/laravel-vite-helper

A lightweight Laravel package that adds convenient Blade directives and PHP helpers for Vite, simplifying asset resolution, dev-server detection, and script/style tag generation. It works with Vite's manifest and hot file so you can ship frontend assets with less boilerplate.

Deep Wiki
Context7

Getting Started

Install

composer require motomedialab/laravel-vite-helper

The package is a thin wrapper around Laravel's Vite facade, so there is nothing to publish and no migration step. If the package does not rely on auto-discovery for a global helper, add its helper file to composer.json under autoload.files and run composer dump-autoload.

Before the first call, make sure a Vite build exists:

npm run build   # produces public/build/manifest.json

The helper reads the same manifest @vite uses, so calling it before a build (or in a fresh CI checkout) will throw a manifest-not-found error.

First use case — Open Graph / social card images in your layout, where relative /build/... URLs are silently ignored by crawlers:

<meta property="og:image" content="{{ vite_asset('resources/images/og-card.jpg') }}">
<meta name="twitter:image" content="{{ vite_asset('resources/images/og-card.jpg') }}">

Then confirm the asset is actually in the manifest (public/build/manifest.json). Only files Vite has processed (imported from JS/CSS or listed in build.rollupOptions.input) will resolve; random files dropped in public/ will not.

Where to look first

  • public/build/manifest.json — the source of truth for what vite_asset() can resolve.
  • Your vite.config.js — controls which non-JS assets end up in the manifest.
  • The package's src/ — it is small enough to read end-to-end; you will want to know whether it uses asset(), url(), or config('app.url') internally, because that determines CDN and CLI behaviour.

Implementation Patterns

Centralise a meta-tag partial. Rather than scattering helper calls, build one Blade component that owns all absolute URLs:

{{-- resources/views/components/meta-images.blade.php --}}
@props(['image' => 'resources/images/og-card.jpg'])

<meta property="og:image" content="{{ vite_asset($image) }}">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">

This gives you a single place to swap the image, change dimensions, or add a CDN prefix later.

Transactional email assets. This is the strongest day-to-day use case: mail clients and image proxies cannot resolve relative paths.

class OrderShipped extends Mailable
{
    public function build()
    {
        return $this->view('mail.order-shipped')
            ->with(['logo' => vite_asset('resources/images/logo.png')]);
    }
}

Keep the URL resolution in the Mailable, not the Blade view — views rendered by queue workers should receive a fully-formed string, not depend on request context at render time.

JSON APIs and headless clients. Mobile apps and third-party consumers benefit from absolute URLs the same way:

return new PostResource($post);
// resources:
'cover' => vite_asset('resources/images/placeholder.jpg'),

Sitemaps, RSS, and signed links. Anything consumed outside a browser tab needs absolute URLs; the helper slots in alongside url() and route():

<image>
  <url>{{ vite_asset('resources/images/logo.png') }}</url>
</image>

Wrap it once for CDN switching. If you ever move assets to S3/CloudFront, you want one seam. Define your own helper that delegates:

function cdn_asset(string $path): string
{
    return vite_asset($path);
}

Then later you can change the implementation to asset(Vite::asset($path)) or a signed URL without touching every view.

Testing pattern. In TestCase::setUp() or a base test case:

protected function setUp(): void
{
    parent::setUp();
    $this->withoutVite(); // prevents manifest lookups in feature tests
}

For a test that specifically asserts absolute URLs, create a temporary manifest with Storage::fake()-style setup or point Vite::useManifestFilename() at a fixture. Assert on str_starts_with($url, 'http') rather than a hardcoded host.

Gotchas and Tips

Hot mode leaks localhost. During npm run dev, the Vite dev server is "running hot" and Vite::asset() returns http://localhost:5173/.... If you render an email or an OG tag in that state, you will publish a URL that only works on your machine. Guard it:

function public_asset(string $path): string
{
    return app()->isLocal() && Vite::isRunningHot()
        ? asset($path)          // or a placeholder
        : vite_asset($path);
}

ASSET_URL vs APP_URL vs request host. The absolute host comes from different places depending on implementation. If the helper uses url()/asset(), the host is derived from the current request when ASSET_URL is unset — which means queue workers, artisan commands, and scheduled jobs will produce http://localhost/.... Set ASSET_URL explicitly in production, or call URL::forceRootUrl(config('app.url')) in a service provider boot method.

Trailing slash doubles up. ASSET_URL=https://cdn.example.com/ plus a path beginning with / yields https://cdn.example.com//build/.... Strip trailing slashes in config; most CDNs tolerate it, but some signed-URL and cache-key checks do not.

Manifest entries vs static files. If vite_asset('images/foo.png') throws, the file is almost certainly not in the manifest. Either import it from JS, add it to build.rollupOptions.input, or use plain asset() for files served straight from public/. Mixing the two is the most common source of confusion with this package.

Build ordering in deployment. Run npm run build before php artisan config:cache and before any queue worker restarts, otherwise a worker may hold a stale manifest path in memory. A deploy script line ordering of composer install → npm ci → npm run build → config:cache → queue:restart avoids this.

Subdirectory installs. Apps served from https://example.com/app need the base path honoured by both the manifest lookup and the URL assembly. Verify one OG tag end-to-end after deploying to a subdirectory; relative-path bugs here are invisible locally.

Version compatibility. The package is a thin shim over Illuminate\Foundation\Vite, which has changed signature between Laravel 9, 10, and 11 (most notably around asset() returning absolute paths in newer versions). Pin the package version alongside your Laravel version, and re-test the helper after every Laravel minor upgrade — a framework change can make the wrapper redundant or subtly wrong.

Read the source before adopting broadly. At 30 stars this is a small package with a narrow surface. If you only need absolute URLs in one or two places, url(Vite::asset($path)) in your own helper achieves the same thing with zero dependency. Adopt the package when you want the abstraction to be a named, documented seam — not because the logic is complex.

Debugging tip. When a URL looks wrong, dump the three inputs separately:

dd(
    Vite::asset('resources/js/app.js'), // relative build path
    config('app.asset_url'),            // CDN override
    url('/'),                           // current root used for absolute assembly
);

The mismatch is always in one of those three.

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.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log