Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

JeffreyWay's avatar

The basic process for extending Elixir is pretty easy. Here's an example of a 'move' task that simply accepts an array of files, and moves them all to a destination directory.

elixir.extend('files', function(src, output) {

    gulp.task('move', function() {
        gulp.src(src).pipe(gulp.dest(output));
    });

    return this.queueTask('move');

});

This allows you to do:

elixir(function(mix) {
    mix.files('foo.txt', 'dest');
});

To set this up, you could either include a file that contains your custom tasks...

// Gulpfile.js

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

require('./my-tasks');

Or, you could even create an npm module, so that others can use it by doing:

npm install laravel-elixir-stylus --save-dev

In fact, that Stylus extension already exists. So, if you grab that, you can use it, like so:

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

require('laravel-elixir-stylus');

elixir(function(mix) {
    mix.stylus("main.styl");
});
5 likes
santacruz's avatar

Great work, Jeffrey! Is there a way to use an ingredient multiple times to generate more than one combined js file for example?

mix.scripts(['one.js', 'two.js'], 'resources/assets/scripts/', 'public/js/first.min.js')
   .scripts(['three.js', 'four.js'], 'resources/assets/scripts/', 'public/js/second.min.js');
2 likes
JeffreyWay's avatar

@santacruz - Not right now. If you need that, you can overwrite the scripts task in your Gulpfile to do what you need it to.

Valorin's avatar

Purely a cosmetic suggestion, but have you thought about making a blade helper to either replace, or sit alongside the elixir() function?

I'm not a huge fan of custom global functions like elixir(), so would prefer to do something like @elixir() in my blade templates. Plus, it would fit nicely alongside the other helpers like @lang().

1 like
santacruz's avatar

@JeffreyWay - Thanks for the feedback. I cannot get it to work though... Can you give an example on how to override it for this purpose? Also, elixir.extend() does not work, I always get the following error:

elixir.extend('languages', function() { ... });

Object #<Object> has no method 'languages'

And gulp watch is not working for me when using versioned files. It re-runs all the tasks in an infite loop. If I remove the version part, it works as expected. These are my watchers:

{ default: 
   { sass: 'resources/assets/sass/**/*.+(sass|scss)',
     scripts: 'resources/assets/scripts/**/*.js',
     version: 
      [ 'public/css/app.backend.css',
        'public/css/app.frontend.css',
        'public/js/app.min.js',
        'public/js/app.lang.de.js',
        'public/js/app.lang.en.js' 
      ] }
}

And one more:


this.registerWatcher(taskName, output + '/**/*.' + type);

in Config.js should be:

this.registerWatcher(taskName, baseDir + '/**/*.' + type);
JeffreyWay's avatar

@santacruz -

It would help to see your Gulpfile. Are you making sure that you put elixir.extend before your main elixir() call?

Also, JS scripts shouldn't go in your resources directory. Put those in public/js.

randomor's avatar

@JeffreyWay Thanks for the amazing work! I'd love to see bower and gulp-include support too. But before that become reality, would you show me how to create a simple gulp-include task that could be chained with the other existing elixir tasks? I tried the following and it doesn't work somehow.

elixir.extend('includeFiles', function(src, baseDir, output) {

  gulp.task('include', function() {
    return gulp.src(src)
      .pipe(include())
  });

  return this.combine('js', src, baseDir, output, 'include');

});
JeffreyWay's avatar

@randomor - What happens when you try to do mix.includeFiles()? Are you adding that snippet of code before the main elixir() function in your Gulpfile?

randomor's avatar

@JeffreyWay I just did another iteration and it is generating files with file included, but in public/js directory as exampleFile.coffee, not as a js file. I'm still trying to get the following task to be able to be chained with the rest of the elixir tasks like this:

mix.sass("app.scss")
    .includeFiles('app.coffee')
    .coffee('app.coffee');

My current task:

elixir.extend('includeFiles', function(src, output) {

  var baseDir = this.preprocessors.baseDir + 'coffee/';

  src = this.buildGulpSrc(src, baseDir, '**/*.coffee');

  gulp.task('include', function() {
    return gulp.src(src)
      .pipe(include());
      .pipe(gulp.dest(output || config.jsOutput));
  });

  return this.queueTask('include');
});
nfauchelle's avatar

I think having a lint/validation on the script ingredient would be a good addition. The sass ingredient outputs errors so it'd be nice if the script one did as well (or maybe we have a script-validation ingredient....

Also like @santacruz it'd be good to run these multiple times. I have a bunch of scripts I want to combine into an admin.js and then another set I want for the frontend. I don't want to combine them all into one as 99% of front end people wont see admin area.

randomor's avatar

@JeremyWay I finally got what I needed using the following custom task:

elixir.extend('includeFiles', function(src, output) {

  var baseDir = this.preprocessors.baseDir + 'coffee/';

  src = this.buildGulpSrc(src, baseDir, '**/*.coffee');

  gulp.task('include', function() {
    return gulp.src(src)
      .pipe(include())
      .pipe(gulp.dest(output || 'resources/assets/coffee/processed'));
  });

  this.registerWatcher('include', baseDir + '/**/*');

  return this.queueTask('include');
});

But as you can see, I'm creating an temporary directory inside resources/assets/coffee for it to be picked up by mix.coffee(), and this won't work for scss or css either, although out of the box scss does support @import. Sorry about spamming your inbox and hijack this thread. I've created a gist for those interested in recommend better ways of doing this. Thanks!

JeffreyWay's avatar

@nfauchelle - Okay, you can do that now.

mix.scripts(['js/one.js', 'js/two.js']).scripts(['js/three.js', 'js/four.js']);

That'll give you two separate concatenated files.

@randomor - Will look at your situation later tonight.

nfauchelle's avatar

@JeffreyWay Thanks!

In my previous message I mentioned about including some js validation / linter in the script. I think what could be done instead is errors from uglify displayed.

Currently if you have the elixir watching, and you add in some broken js the scripts command will error out and terminate the watch;

[11:10:21] Starting 'scripts'...

stream.js:94
      throw er; // Unhandled stream error in pipe.
            ^
Error
    at new JS_Parse_Error (/...../node_modules/gulp-uglify/node_modules/uglify-js/lib/parse.js:189:18)

so maybe those could be displayed, like the sass errors are.

Barryvdh's avatar

I'm not sure if this is (easily) possible with Elixr yet, but I usually create 2 versions, 1 minified and 1 development version (just combined).

return gulp.src('assets/less/style.less')
    .pipe(less({
        sourceMap: true,
        outputSourceFiles: true
    })
    .pipe(gulp.dest('public/assets/css'))
    .pipe(rename({suffix: '.min'}))
    .pipe(minifycss())
    .pipe(gulp.dest('public/assets/css'));

This way the dev-version can include sourcemaps and original css/js. (And I just reference the correct assets depending on the value of app.debug, style.css of style.min.css)

1 like
TimVanDijck's avatar

Just started digging into Elixir today. Looks great. Good job!!

schel4ok's avatar

I cannot understand how to extend elixir with the other gulp functions. The code below is not working. So when I execute command gulp in terminal imagemin is not performed with the other commands. So I need to execute gulp imagemin What I did wrong?

[code] var elixir = require('laravel-elixir'); var gulp = require('gulp'); var imagemin = require('gulp-imagemin');

elixir.extend('imagemin', function() { gulp.task('imagemin', function() { return gulp.src('resources/assets/img/*.jpg') .pipe(imagemin({ progressive: true })) .pipe(gulp.dest('public/img')); }); });

elixir(function(mix) { mix .less('app.less') .scripts() .imagemin()

});[/code]

patton517's avatar

PHPDoc would be nifty, but honestly that should be pretty easy to set up manually.

devartpro's avatar

Is it possible to combine scss compiled css files with vendor css files with Elixir? So on frontend I want one css file, which contains bootstrap and custom files compiled from scss and for example colorbox.css or other vendor files.

davorminchorov's avatar

Yeah, it is possible. You have to compile the scss file first and after that you combine the vendor css files with your custom css file.

devartpro's avatar

@Ruffles, yes but the question is how? I tried with styles and stylesIn with no success...

davorminchorov's avatar

@devartpro Like this:

.styles([
                '/bower_components/angular-ui-notification/dist/angular-ui-notification.min.css',
                '../public/css/main.css'

        ], 'public/css/all.css', 'resources');

I import all of the vendor scss files and my custom scss files in main.scss so they compile together in main.css After that, I mix my main.css file with vendor css files (in this case, Angular UI Notification css).

Just make sure you write the right paths, that might cause problems.

elit-internet's avatar

@JeffreyWay : Thing is, tasks created by extend() run after all regular elixir tasks are done, which makes it impossible to chain them and have some desired sequence of actions.

elit-internet's avatar

@schel4ok : You forgot trailing return this.queueTask('taskName'); inside your extend() function - check docs carefully.

Please or to participate in this conversation.