>

Course Overview

Gulp! Refreshment for Your Frontend Assets

  • 698 students
  • EN Captions
  • EN Script
  • Certificate of Completion

Your Guides

About this course

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.3.3",
        "symfony/symfony": "2.6.*", // v2.6.4
        "doctrine/orm": "~2.2,>=2.2.3", // v2.4.6
        "doctrine/doctrine-bundle": "~1.2", // v1.2.0
        "twig/extensions": "~1.0", // v1.2.0
        "symfony/assetic-bundle": "~2.3", // v2.5.0
        "symfony/swiftmailer-bundle": "~2.3", // v2.3.7
        "symfony/monolog-bundle": "~2.4", // v2.6.1
        "sensio/distribution-bundle": "~3.0", // v3.0.9
        "sensio/framework-extra-bundle": "~3.0", // v3.0.3
        "incenteev/composer-parameter-handler": "~2.0", // v2.1.0
        "hautelook/alice-bundle": "~0.2" // 0.2
    },
    "require-dev": {
        "sensio/generator-bundle": "~2.3" // v2.4.0
    }
}

NOTE We now recommend using Webpack instead of Gulp. And, we have a shiny tutorial all about it: https://knpuniversity.com/screencast/javascript-webpack

We all need to minify and combine our CSS and JS files. And with Gulp, this is not only easy, but it's actually fun to do!

In this tutorial, I'll show you how to setup Gulp in your PHP or Symfony project to do a bunch of things:

  • Minify CSS and JS files
  • Watch files for changes
  • Combine files
  • Use sourcemaps
  • Publish Font files
  • Have page-specific CSS/JS files
  • Cache-bust with versioning

We'll actually use Laravel's Elixir as a guide, but make things work for any PHP project and learn how we can make Gulp do whatever we need.

Yay!

39 Comments

Sort By
Login or Register to join the conversation
Default user avatar Shairyar Baig 5 years ago

Hi,

I understand that gulp puts everything inside `node_modules` directory and I have 3 questions about it.

1) Do we really need everything thats sitting inside `node_modules` directory, reason I am asking this is because its over 34MB, we only installed like 13 plugins of gulp following the tutorial but there are 295 folders which I am assuming are plugins inside `node_modules` folder.
2) Do you need to upload `node_modules` folder on production?
3) Cant we move `node_modules` inside vendor directory that comes with symfony just like `bower_components` directory?

Regards,
Baig

1 | Reply |

Hey Shairyar,

I have worked with npm and can help answer your questions:

1) I would keep everything that is in your node_modules folder. A lot of times when you install something using npm, it will also load any other dependencies that package may require. It's a lot like Composer for the front-end.
2) You don't have to upload the folder. If you have dependencies in the node_modules folder that your project requires, you can install node on your production server and just run `npm install` and all of your dependencies with be installed on your server. Again, this is a lot like Composer. You just need to pay attention to whether or not you link to any assets in your node_modules folder. Usually, I do not use npm for assets. Instead, I use Bower, so I know that I do not have to upload my node_modules folder and I don't have to run `npm install` on my production server. I simply use it for Gulp and that just helps me while in development, not in production.
3) You could move it inside of your vendor folder, but most of the time, all of the things in your node_modules folder are not dependencies, unlike the things in the vendor and bower_components folder. This is more of a personal preference, but I would keep them separated.

1 | Reply |
Default user avatar Shairyar Baig Deric Cain 5 years ago

Hi Deric,

Many thanks for the information. Ya i don't think i will be uploading the node_module either as i am just using gulp to merge and compress files.

I am really beginning to enjoy gulp and bower :)

Regards,
Baig

| Reply |

Hey Baig!

Can I call you Baig - I saw you signed with that this time :)

1) Yep, this directory can get *huge* - it's just how npm is designed. But, it doesn't even need to be deployed (if you build your assets locally first) - you could ignore it from your deploy. And yes, node is famous for having many, many sub-directories. It's kinda crazy :). Btw, make sure you have the latest npm - *some* of this has changed I believe (but I think it's still huge).

2) Nope - well, not if you build your css/js first (which I do). If you do that, you can just deploy those generated css/js files and completely ignore the node_modules directory

3) A quick googling makes this unclear, surprisingly. But, I would keep it anyways - it helps other people understand your project more quickly - many people understand what will live in node_modules. I sometimes move the bower directory because I want it in my web directory (and btw, it seems bower is being used less and less, and things like npm + browserify are being used instead: https://lincolnloop.com/blo.... But, I haven't switched over just yet :).

Cheers!

| Reply |
Default user avatar Shairyar Baig weaverryan 5 years ago

Hi Ryan,

Yes you can call me Baig :)

Thanks for getting back to me. Sad to hear that gulp is being used less as i just learnt it :)

Are you planning to create a tutorial on npm + browserify?

Baig

| Reply |

Hi Shairyar,

if you use bower, then your packages will get updated automatically on new package installation, which is pain. Solution is eaither use npm to manage packages or use git to keep track. It does not work like composer.

for this reason and many other, people are moving to webpack.

| Reply |

Yep, webpack and browserify are "competitors" - though I just read an article today that said that webpack seems to be winning.

However, I'm not sure that "gulp" is necessarily going away - browserify/webpack can be used *inside* of gulp - i.e. https://webpack.github.io/d.... If you read the first comment there, there's some discussion about this :).

Anyways, yes, I'd like to make a "2.0" version of this tutorial - the JS world moves so quickly :). But I have a few other tutorials that need to get done first.

Cheers!

1 | Reply |
Default user avatar Shairyar Baig Basit 5 years ago

thanks for sharing the information, that really sounds like a pain.

| Reply |

Is there any slideshow library to create a slideshow with photos from the database?

| Reply |

Hey @majk!

Hmm, not exactly for Symfony. What you would do is:

A) Find a JavaScript library that is able to create a slideshow
B) Use Symfony/Twig to render the images that you want in a way that the JavaScript library requires.

By the way, next week we'll be starting a tutorial about file uploading, in case it's useful: https://symfonycasts.com/sc...

Cheers!

| Reply |
Default user avatar Hitesh Vaghela 5 years ago

Hi Ryan,
I started using Gulp after competing the course and its awesome. But I started the same problem reported by Shairyar Baig. I noticed mainly two problems.
1. Sometimes it isn't able to create manifest file.
2. Most times mapping entries are not available in manifest file.
and it is annoying now to run the gulp al least 7-8 times to achieve the task. and that just because of 1-2 this small problem. Please suggest some solution.
And ya It happens most times when starting gulp and some times during watch.

| Reply |

Hey Hitesh Vaghela

Have you tried Basit's solution? https://knpuniversity.com/s...

Cheers!

| Reply |
Default user avatar Hitesh Vaghela MolloKhan 5 years ago

Nop as he is not 100% sure. So temporarily I found a workaround. I am maintaining two different manifest files for css and js and reading them from same function via parameter. I know its not the best solution but it works for me. At least for this project.

| Reply |

Yo Hitesh Vaghela!

Yea, it's a good workaround. There's an annoying race condition I believe, between multiple pipelines (e.g. js & css) all trying to write to the manifest. I thought I had fixed this before recording the tutorial, but apparently not :/. I believe it's a bug in the manifest library itself, as it's supposed to not do this. Basit's solution makes a lot of sense (running the tasks in parallel, but since he says it still happens sometimes, it sounds like there's yet another race condition somewhere. Very annoying - I apologize. I'm not sure what the solution is. I now use Webpack in place of Gulp in my day-to-day.

Cheers!

| Reply |
Default user avatar Hitesh Vaghela weaverryan 5 years ago

Haven't yet tried Webpack. Is it better than Gulp? And will we get a web series on that?

| Reply |

Hey Hitesh,

Yep, it's trendier and definitely better. Actually, it has a different approach - it allows you *requiring* JS files like you did in PHP. And yes, we already have! The course has been even completely released, check it out here: https://knpuniversity.com/s...

Cheers!

| Reply |
Default user avatar Dimitar Ivanov 5 years ago

I love to use Gulp in my projects. Check out my blog post on task automation with gulp.js: http://zinoui.com/blog/task...

| Reply |
Default user avatar Basit 5 years ago

Hi Ryan,

For versioning you have used gulp-rev and made your own asset twig extension to read and load. Wouldn't it be better to just use symfony assetic features to do compiling and versioning automatically as standard way, rather then doing extra customisations on gulp.

What are your thoughts on this? :)

| Reply |

Hi Basit!

I think you could push more work into Symfony / Assetic if you wanted to, but let's think how that might work. If you didn't combine the files in gulp (just processed sass to CSS etc), you could create an Assetic tag that included the processed filenames. I think that would work. But Assetic doesn't have any versioning. Symfony has a versioning feature but out of the box, it's global: you change the version on a configuration file and it changes the version for all assets. Assetic does have the ability to create a random output filename if you don't give it one, but iirc, this was not meant for versioning.

Was this along what you were thinking?

Cheers!

| Reply |

Thanks. I have decided to go with your version, which covers everything. Just one question I had. You haven't mention about how to make sure clean is done first, before others function start running.

since everything required on promise and clean does not have such. I have just return true on clean task, would it work fine with return true, to make sure clean is run first and then others.

btw, if you add requireJs also on this tutorial. It will complete the set. but for those who were interested in requirejs to complete the set, following is link for slideshow by Ryan http://www.slideshare.net/w...

| Reply |

Hey Basit!

Great! Let me know how you like things!

About clean. I believe what you're saying is that the "clean" task does not return a promise, so there's no guarantee that it will clean will finish before the other tasks start. Your logic is correct, however, the clean task (I believe) is special because I use the "del.sync" - which deletes things *synchronously*. In other words, unlike everything else that gulp is doing, each line in clean waits to finish before it goes to the next line. The result is that the clean function doesn't actually finish until all of its tasks are actually done. This means that it will finish before the others start.

If you're seeing something different, let me know! But it's very good of you to notice that this function appears to behave different than the others :).

Cheers!

| Reply |
Default user avatar Tyler Steimle 5 years ago

Yes! So happy to see the Gulp series. It's my favorite task runner already. Can't wait to dig in, I'm sure you have some things I missed. :)

| Reply |

Hey Ryan!

Do you plan to add any tutorial about search engines like ElasticSearch or any other? There are a great bundle FOSElasticaBundle that integrate Elasticsearch in Symfony2 projects but I am interested in your cool examples )

| Reply |

Yea, I *do* have Elastic specifically in mind. I need to integrate it anyways with our search to make it a lot more awesome. When I do that, I'll put a tut on it :)

1 | Reply |
Default user avatar Shairyar Baig 5 years ago

I have been using this technique since i saw this tutorial 5 months ago, the concept is neat however I do come across a situation occasionally where "rev-manifest.json" does not include either css and js file name in it when i run gulp command, i have to then several times stop the recompile and this becomes annoying after a while. I did not make any change to the code just changed the css and js files that are being compiled plus the location of "rev-manifest.json" is in AppBundle/Resources/public/asset folder.

Is anyone running into the same issue occasionally? is this the excepted behaviour once in a while? when the "rev-manifest.json" does not include one of the files, i do cross check if these files were actually created and they were as i can see them in css and js folder. I also do not see any error in console either.

Here is my gulp.js https://gist.github.com/sha...

| Reply |

I'm using same technique, have same problem.

You can overcome by providing finish condition on each task, so don't run other until first is finished, then dont run third, until second is finished.

gulp.task('styles', ['fonts'], function...

gulp.task('scripts', ['styles'], function()

gulp.task('watch', ['styles', 'scripts'],...

This will help you a lot, but it is still not 100% accurate, because I do get still problem time to time.

2 | Reply |
Default user avatar Shairyar Baig Basit 5 years ago edited

Thanks Basit I will give this idea a try.

| Reply |

Hey Shairyar!

It sounds like the "race condition" we talk about here: https://knpuniversity.com/s...

Does it happen during the "watch" task? I mean, if you run gulp, does it compile correctly at first, but then *later* the rev-manifest.json becomes broken after you update some CSS or JS files? Or, does it happen only when initially running gulp? My guess is that there's still a race condition somewhere... Also, make sure you have the merge: true option on the manifest (I'm guessing you do, else you would see this problem constantly).

Let me know what you see!

| Reply |
Default user avatar Shairyar Baig weaverryan 5 years ago

It happens randomly, if i open up a project and run the command gulp first time there is a chance that it will be successful but then there are times even the first gulp command does not work, i have to keep trying it 7 to 8 times to get it to work.

The same happens if i am in the middle of the project and make a change to the css or js file there are times the manifest does not get updated then i have to manually stop and run gulp again which takes 7 to 8 times to get going again or if i am lucky the first try will work.

| Reply |

Hey Shairyar!

Oh wow, that just sounds buggy :/. With the "merge: true", the manifest plugin should only *update* the file, and not override it. And with the pipeline, we should not have race conditions if you have multiple CSS or JS files. I do wonder if Shairyar Baig recommendation will help here - the only thing I can think of is a race condition between the CSS and JS processes themselves. If that *does* help, I'd love to know.

Cheers!

| Reply |
Default user avatar Shairyar Baig weaverryan 5 years ago

ya, i will try that and see if that helps.

| Reply |
Default user avatar Mark33684 5 years ago

hey there, thanks for the fantastic tutorial. it really helped me understanding a lot more in gulp. i just got stuck at chache bursting..i dont get how to tell twig where there php extension is and how to load the filter ...i got also confused by the yml file..do i have to install something else to make it work? thanks a lot for ur help.

| Reply |

Hey Mark!

Yep, you'll need 2 things for the Twig extension, and both (as you probably already know) are on this page: https://knpuniversity.com/s...

1) You'll need the finished, AssetVersionExtension class itself - check out the code-blocks
2) You'll need to "steal" the YAML code from the services.yml file and put it into *your* services.yml file. That code is also on the linked page, but I just realized that we're "hiding" the good parts. I'll fix that right now - but you can find the services.yml on that page and click the little errors to expand and see the entire file.

If you're new to registering things as services, and this "tags" thing, I encourage you to check out http://knpuniversity.com/sc... and http://knpuniversity.com/sc... - those will really help you feel comfortable :).

Cheers!

| Reply |

Thanks a lot for ur quick reply Ryan,

thats what i was wondering, since i dont have a services.yml file...i guess i need to install symfony to the gulp project folder to make it work?. i will try to figure it out. i am working on a gulp project that outputs html and/or craft templates..so i dont have to migrate the site to craft afterwards..if u are interested i will post it once i am done...if i get lost with the yml file and sznfony i will get back to u ..thanks again :)

| Reply |

Hey Mark!

Ah, I see! So you certainly don't need Symfony to do this - this was just the approach if you *are* in Symfony :). Basically, one way or another, you just need some dynamic code (e.g. PHP) that's able to read that rev-manifest.json file and map each file name (e.g. main.css) to its current revision filename (e.g. main-123abcd.css).

Let me know how I can help - and of course it's always great when people are able to share their solutions! I look forward to it.

Cheers!

| Reply |
Default user avatar Shairyar Baig 5 years ago

Great tutorial, finally understand the gulp now :)

| Reply |
Default user avatar Tamurai 5 years ago

Hi Ryan,
Nice tutorial, please update the "Minify" video script to use "gulp-clean-css" as "gulp-minify-css" is deprecated.

Regards,
Tamer

| Reply |

Yes, the frontend world moves so fast!

| Reply |

I Agree soo much with Ryan on this. Angular 3 is coming out soon. No? well wait and check again lol. No really. once you done learning one thing, there is new thing that replaced the thing you learned lolz.

| Reply |

Delete comment?

Share this comment

astronaut with balloons in space

"Houston: no signs of life"
Start the conversation!