duellsy's avatar

elixir in production / development

Hey all, I am running into issues when running elixir and my staging / production servers are using the elixir() helper to serve assets from the build directories.

In my view i have this:

@if($app->environment('local','staging'))
    <link href="{!! asset('css/all.css') !!}" rel="stylesheet">
@else
    <link href="{!! elixir('css/all.css') !!}" rel="stylesheet">
@endif

The problem is:

  • elixir versioned files are in public/build/css/
  • local files are in public/css/

any img or asset i reference in the stylesheet will 404 as its directory depth has changed.

for reference here is my gulp file:

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

elixir(function (mix) {
    
    mix.sass([
        'main.scss'
    ]);

    mix.styles([
        'main.css',
        '../../bower_components/slick-carousel/slick/slick.css'
    ]);

    mix.scripts([
        '../../bower_components/jquery/dist/jquery.js',
        '../../bower_components/jquery-bez/jquery.bez.min.js',
        '../../bower_components/jquery.cookie/jquery.cookie.js',
        '../../bower_components/jquery.placeholder/jquery.placeholder.js',
        '../../bower_components/fastclick/lib/fastclick.js',
        '../../bower_components/foundation/js/foundation/foundation.js',
        '../../bower_components/foundation/js/foundation/foundation.offcanvas.js',
        '../../bower_components/foundation/js/foundation/foundation.magellan.js',
        '../../bower_components/foundation/js/foundation/foundation.interchange.js',
        '../../bower_components/foundation/js/foundation/foundation.clearing.js',
        '../../bower_components/foundation/js/foundation/foundation.topbar.js',
        '../../bower_components/foundation/js/foundation/foundation.tab.js',
        '../../bower_components/greensock/src/minified/TimelineMax.min.js',
        '../../bower_components/greensock/src/minified/TweenMax.min.js',
        'foundation.equalizer.js',
        '../../bower_components/slick-carousel/slick/slick.js',
        'DrawSVGPlugin.js',
        'jquery.simple-text-rotator.min.js',
        'svg-icons.js',
        'main.js'
    ]);

    mix.version([
        'public/js/all.js',
        'public/css/all.css'
    ]);

});

Cheers all!

0 likes
16 replies
michaeldyrynda's avatar

What are the contents of the rev-manifest.json file? Why are you using asset() only in local and staging? Just use elixir() all the time.

The only real difference between production and any other environment, is that the build files will be minified in production.

duellsy's avatar

@deringer you are correct the reason why I was using asset is so I can use live reload locally.

bashy's avatar

I'm not sure why there's another folder for versioned files, why not just have them in the same location but with the ending... (that's towards elixir)

1 like
michaeldyrynda's avatar

@duellsy public/css/all.css is still being regenerated when you run elixir, can't you live reload based off of that?

@bashy I'm pretty sure it's the way gulp-rev handles versioning the files - because it versions an existing file, it doesn't do it on the fly?

bashy's avatar

@deringer Yeah gulp-rev. Just seems weird because you have to set the path for images differently depending on if you're going to version the file (since there's another level created).

michaeldyrynda's avatar

It's a tedious process (gulp) and the general lack of feedback / errors is enough to drive you mad. I spent about half an hour yesterday trying to figure out why it wasn't combining an off-the-shelf stylesheet with my compiled less.

JeffreyWay's avatar

Hey, guys. Going to put some energy into better error feedback for Elixir this week.

If you were using regular Gulp, you wouldn't have any feedback either (like, if the file didn't exist at that path), but we can do some things to help with this.

3 likes
bashy's avatar

Yeah would be nice - save a lot of debugging :P

I also find it weird that it sends a notification for every SASS file compiled (array of them).

[00:10:59] Starting 'sass'...
[00:11:00] gulp-notify: [Laravel Elixir]
[00:11:00] gulp-notify: [Laravel Elixir]
[00:11:00] gulp-notify: [Laravel Elixir]
[00:11:00] gulp-notify: [Laravel Elixir]
JeffreyWay's avatar

@bashy - Are you compiling multiple Sass files? Really, it should just be one:

mix.sass('app.scss');
bashy's avatar

I would if I could :P it's for a CMS so I have different ones for front/back and also for admin login (don't want all of the CSS visible to guests).

.sass([
    'backend-noauth.scss',
    'backend.scss',
    'main.scss',
    'fa/font-awesome.scss',
], 'public/assets/css')
deshiknaves's avatar

I often do this between production and development environments. I have a helper function to handle which function it should use.

if ( ! function_exists('elixir_source')) {
    function elixir_source($file) {
        if (env('APP_ENV') == 'production') {
            return elixir($file);
        }

        return asset($file);
    }
}
2 likes
jcottrell's avatar

For Laravel 5, I installed font-awesome from npm npm install font-awesome and then edited the resources/assets/sass/app.scss to add the path to font-awesome similar to bootstrap: @import "node_modules/font-awesome/scss/font-awesome.scss"; I then modified my gulpfile.js to .copy the fonts to the build directory, apparently where .version is expecting them:

elixir(function(mix) {
    'use strict';
    mix.sass('app.scss')
        .copy('node_modules/font-awesome/fonts', 'public/build/fonts')
        .styles([
            './public/css/app.css',
            'offsite.css'
        ]).version('css/all.css');
});
pilat's avatar

Not sure if that addresses the issue directly, but I have the following in my view files: {{ asset(elixir('my/resource.ext')) }}

elixir() on a "stripped" file path would find versioned filename, while asset() would add the necessary "/web/folder/" to it.

ejdelmonico's avatar

@pilat you are incorrectly using the helpers. If you are using versioning, use elixir('your-asset'). If not, use asset('your-asset'). The helpers were never designed for using both. The url's produced will be corrupted. The difference between the two are that the elixir helper will read the manifest file to determine the correct path to inject and asset will not read the file and use whatever you give it.

pilat's avatar

@ejdelmonico actually, I'm doing this for a reason. elixir() would only map asset's filename to the "cache-busted" one, in accordance to manifest file. It won't prefix "web-dir" to the final asset URL, however — this is what `asset does.

So, let say I have a shared hosting with non-changeable server setup that serves HTTP from the $HOME/public_html directory. It can't be re-routed to WHATEVER/public. In this case, I simply put my entire Laravel content into $HOME/public_html and access the site via /public/ URI (instead of just /).

If I use elixir() alone, I'll get assets URIs like /js/myscript-qwe43re.js, which would not be found by browser. asset(elixir()) would do the trick and make the proper URI of /public/js/myscript-qwe43re.js.

Moreover: if I have another copy of site (let say, local copy, served with Valet or Homestead), accessible via web-root / — I don't need to change my code. I just make sure that all local links are made with `url and all assets are referenced with `asset (with or without elixir()) and it handles my current web-dir properly.

P.S.: it would probably be better if elixir() did both: added web-dir and mapped to versioned file. But, maybe, not… You know, I mean that "do one thing, but do it the best!" philosophy.

Please or to participate in this conversation.