Skip to content
Laravel-BackpackPublic

About

Better asset helpers for Laravel apps.

Resources

Contributing

Stars

208 stars

Watchers

6 watching

Forks

Repository files navigation

Basset 🐶 - the better asset() helper for Laravel

Latest Version on Packagist Total Downloads StyleCI

Easily use your CSS/JS/etc assets from wherever they are, not just your public directory:

{{-- if you're used to Laravel's asset helper: --}}
<link href="{{ asset('path/to/public/file.css') }}">

{{-- just change asset() to basset() and you can point to non-public files too, for example: --}}
<script src="{{ basset(storage_path('file.js')) }}">
<script src="{{ basset(base_path('vendor/org/package/assets/file.js')) }}">
<script src="{{ basset('https://cdn.com/path/to/file.js') }}">

That's all you need to do. Basset will download the file to the predefined disk, then output that disk path to your asset.

Using Basset, you easily internalize and use:

  • files from external URLs (like CDNs)
  • files from internal, but non-public URLs (like the vendor directory)
  • entire archives from external URLs (like GitHub)
  • entire directories from local, non-public paths (like other local projects)

No more publishing package files. No more NPM bloat, just to download some files. It's a simple yet effective solution in the age of HTTP/2 and HTTP/3.

Installation

composer require backpack/basset
php artisan basset:install

To check that Basset is running correctly, please run:

# recommended - this will tell you if anything is wrong & what to do:
php artisan basset:check

Optionally, you can also publish the config file to make changes in how Basset works:

# optional
php artisan vendor:publish --provider="Backpack\Basset\BassetServiceProvider"

Storage Symlink

The default disk remains basset, which lives under storage/app/public. Run php artisan storage:link so the cached assets are reachable from public/. The installer keeps the command in your composer scripts.

If you prefer to keep cached files under public/ instead of storage/, switch to the public_basset disk (BASSET_DISK=public_basset) and commit or ignore public/basset according to your workflow.

Disk Options

Disk Where files live Pros Cons
basset (default) storage/app/public/basset Clean git tree; downloads happen on deploy; matches previous defaults Needs php artisan storage:link;
public_basset public/basset Assets are ready to serve after deploy; can be versioned Git noise unless ignored;

If you move to public_basset, re-run php artisan basset:install --git-ignore (or edit the file yourself) when you want the installer to append public/basset to .gitignore.

Usage

The basset() Helper

You can just use the basset() helper instead of Laravel's asset() helper, and point to CDNs and non-public files too. Use Laravel's path helpers to construct the absolute path to your file, then Basset will take care of the rest.

For local from CDNs:

{{-- instead of --}}
<link href="{{ asset('path/to/public/file.css') }}">

{{-- you can do --}}
<link href="{{ basset('path/to/public/file.css') }}">
<link href="{{ basset('https://cdn.com/path/to/file.css') }}">
<link href="{{ basset(base_path('vendor/org/package/assets/file.css')) }}">
<link href="{{ basset(storage_path('file.css')) }}">

Basset will:

  • copy that file from the vendor directory to the basset disk (if needed)
  • use the internalized file on all requests

The @basset() Directive

For known asset types like CSS, JS, images and videos, among others, Basset makes it even shorter to load assets. No need to write the HTML for your + @endBassetBlock()">

+   @bassetBlock('path/or/name-i-choose-to-give-this')
    
+   @endBassetBlock()

Basset will:

  • create a file with that JS code in your basset directory (aka. internalize the code)
  • on all requests, use the local file (using ">
    // card.blade.php
    
    
    Lorem ipsum

And you load that blade file multiple times per page (eg. include card.blade.php multiple times per page), you'll end up with that script tag being loaded multiple times, on the same page. To avoid that, Larvel 8 provides the @once directive, which will echo the thing only once, no matter how many times that blade file loaded:

// card.blade.php

Lorem ipsum
@once @endonce

But what if your script.js file is not only loaded by card.blade.php, but also by other blade templates (eg. hero.blade.php, loaded on the same page? If you're using the @once directive, you will have the same problem all over again - that same script loaded multiple times.

That's where this package comes to the rescue. It will load the asset just ONCE, even if it's loaded from multiple blade files.

FAQ

Basset is not working, what may be wrong?

Before making any changes, you can run the command php artisan basset:check. It will perform a basic test to initialize, write, and read an asset, giving you better insights into any errors.

The most common reasons for Basset to fail are:

  1. Incorrect APP_URL in the .env file.
    Ensure that APP_URL in your .env matches your server configuration, including the hostname, protocol, and port number. Incorrect settings can lead to asset loading issues.

  2. Improperly configured disk.
    By default, Basset uses the Laravel public disk. For new Laravel projects, the configuration is usually correct. If you're upgrading a project and/or changed the public disk configuration, it's advised that you change the basset disk in config/backpack/basset.php to basset. The basset disk is a copy of the original Laravel public with working configurations.

  3. Missing or broken storage symlink.
    If you use the default public disk, Basset requires that the symlink between the storage and the public accessible folder to be created with php artisan storage:link command. During installation, Basset attempts to create the symlink. If it fails, you will need to manually create it with php artisan storage:link. If you encounter issues (e.g., after moving the project), recreating the symlink should resolve them.

Note for Homestead users: the symlink can't be created inside the virtual machine. You should stop your instance with: vagrant down, create the symlink in your local application folder and then vagrant up to bring the system back up.

Where are cached assets stored?

Basset provides a few options out-of-the-box:

  • basset disk - inside the storage directory (eg. storage/app/basset) [DEFAULT]
    • PROs: the Git history is clean - because your cached assets will NOT be tracked by Git;
    • CONs: you have to run php artisan basset:cache in your deploy script, which adds seconds to your deploy time; plus, it opens up a corner case on deployment - because assets are being re-cached upon deployment, if a CDN is down during deployment, the system will not be able to internalize it; if will however internalize it when the CDN is back on, and the page that loads the file gets accessed; we consider the tradeoffs minor and unlikely, which is why this is the DEFAULT;
    • The .basset cache map file is stored privately at storage/app/basset/.basset (not publicly accessible).
    • How to enable: do nothing, or do BASSET_DISK=basset in your .env file;
  • public_basset disk - inside the public directory (eg. public/basset)
    • PROs: you are certain the same assets you have on localhost will be in production, because the assets are commited to Git;
    • CONs: your Git history will be dirtier, because it will contain changes to libraries of CSS/JS files;
    • How to enable: do BASSET_DISK=public_basset in your .env file or config/backpack/basset.php config file;
  • custom - you can completely customize what disk is used to store the assets - just change it in the config file; most common customizations:
    • store assets on a S3 bucket (using a custom disk);
    • store assets in public_basset disk, but add public/basset to .gitignore;

Can I track the assets in git, just like my source code? (aka NOT gitignore CSS and JS assets)

Yes, you can track the assets in your application repository and avoid downloading them on each deployment (aka. have them in git). The easiest way to do that is to set the BASSET_DISK=public_basset in your .ENV, or in the basset config file. This will store the assets in the public/basset directory by default and they will now be committed to git alongside the rest of your application code. But note that this has both PROs and CONs:

  • PROs: This is advantageous as you know what assets are in your application right when you deploy, avoiding issues like a CDN being down at the deployment time and breaking your application production.
  • CONs: As a downside, you must be 100% sure all assets are internalized on localhost, and commited to git. Otherwise, when a page is accessed in production, Basset will internalize that file in production alone (it always prioritizes having production in a working state), which means you'll have uncommitted changes in your production code. You will then have to fix merge conflicts in production, or do a git reset before each deployment.

To summarize - if you're 100% sure that php artisan basset:cache is pulling all assets your application needs, you can safely commit your assets to git. If not, you are exposing yourself to conflicts in production (which can be managed as well).

Events

If you require customized behavior after each asset is cached, you can set up a listener for the BassetCachedEvent in your EventServiceProvider. This event will be triggered each time an asset is cached.

Upgrading from v1 to v2

To upgrade Basset:

  • Step 1. Run php artisan basset:install --git-ignore to refresh composer hooks and optionally ignore the public cache folder.
  • Step 2. Decide on BASSET_DISK (basset + storage symlink, or public_basset + git rule) before deploying.
  • Step 3. Replace any custom @loadOnce usage with @basset or @bassetBlock; the old directive now proxies the new ones.
  • Step 4. Ensure deploy scripts warm the cache (basset:cache or basset:fresh) so your public folder is ready when the app boots.

Change log

Please see the releases tab for more information on what has changed recently.

Testing

$ composer test

Contributing

Please see contributing.md for details and a todolist.

Security

If you discover any security related issues, please email hello@backpackforlaravel.com instead of using the issue tracker.

Credits

License

MIT. Please see the license file for more information.

About

Better asset helpers for Laravel apps.

Resources

Contributing

Stars

208 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages