Bundling web projects with Gulp 01-24-2017, 07:15 PM
#1
Massive libraries like jQuery and Bootstrap depend on tons of different libraries as a base for their code, and they have to be able to squeeze it all into one file (or two, if there's some CSS involved) for it to work properly in production without having their users include loads of other files, possibly in a specific order. That's where tools like Gulp and Grunt come in! I haven't learned much about Grunt (though I'm planning to soon enough), but from my experience with Gulp, I can say it's super easy to use, plugins are a breeze, and you won't have to spend hours trying to get things to work properly.
Before we get Gulp up and running, we need to install a few things. The packages we need consist of gulp itself, a plugin loader, and a few plugins to go with it. The plugin loader requires a package.json file, so we need to go and create one of those before running the following command.
The --save-dev option specifies that we want to save these packages as development dependencies, meaning they will be installed alongside the package unless the user specifies the --production option (which I think is true by default if the package is a dependency itself).
A tricky thing about Gulp is that it needs to be installed local to the package that requires it, meaning that a system-wide executable is not created for using its CLI. To solve this problem, you can put the following alias in your bashrc. If you're running Windows, you're SOL here and you'll have to execute it through the local path.
Edit: I found that you can have a global as well as local gulp installation, so you can use the global binary without conflict (thus all the above crap isn't needed, but it works)
While you can run gulp straight from a file, the package provides a CLI for running tasks (that's the reason we made that alias earlier). Let's make a simple hello world task in a new file called gulpfile.js
We can now execute our gulp task by running "gulp hi" in the command line.
For reference, the default task is a requirement of Gulp that executes when you run the CLI with no arguments.
Before we minify all our code, we need to load our Gulp plugins. As I said earlier, gulp plugins are a breeze. All we need to do is require our plugin loader, pass it a few parameters, and we're done!
Now we have all of our plugins loaded in the "plugins" object.
Now that we know how to write tasks and load plugins, let's write a plugin to concatenate and minify all of our project's JavaScript in one file. We do this by finding the files we want (in this case all files in any directory inside the src directory. If you don't understand why, read up on globbing), then piping the stream to our plugins, and finally to a "dist" directory that we need to create beforehand.
The css is slightly different, but no more difficult.
Now we can include only the bundle.js and bundle.css files in our html files instead of whatever they were originally. Speaking of HTML, we can make a task for that, too.
Since we don't want to deal with running three commands, we can update our default task to run our other ones.
Gulp has another awesome function: directory watching. In one line, you can listen for changes to any files in a glob path and trigger tasks when the event fires. Here's a quick one for our tasks.
Obviously, this isn't all you can do with Gulp. With the hundreds of plugins available, possibilities are nearly endless for things you can accomplish. As a sibling to this thread, I made a github repo with instructions for installation and usage, as well as some goodies like a live server.
https://github.com/inoriy/gulp-tutorial
Installation
Before we get Gulp up and running, we need to install a few things. The packages we need consist of gulp itself, a plugin loader, and a few plugins to go with it. The plugin loader requires a package.json file, so we need to go and create one of those before running the following command.
Code:
npm install --save-dev gulp gulp-load-plugins gulp-uglify gulp-concat gulp-rename gulp-clean-css
The --save-dev option specifies that we want to save these packages as development dependencies, meaning they will be installed alongside the package unless the user specifies the --production option (which I think is true by default if the package is a dependency itself).
A tricky thing about Gulp is that it needs to be installed local to the package that requires it, meaning that a system-wide executable is not created for using its CLI. To solve this problem, you can put the following alias in your bashrc. If you're running Windows, you're SOL here and you'll have to execute it through the local path.
Code:
# linux
alias gulp='./node_modules/.bin/gulp'
# windows
node_modules\.bin\gulp [args]
Edit: I found that you can have a global as well as local gulp installation, so you can use the global binary without conflict (thus all the above crap isn't needed, but it works)
Code:
npm install --global gulp
Our first Gulp task
While you can run gulp straight from a file, the package provides a CLI for running tasks (that's the reason we made that alias earlier). Let's make a simple hello world task in a new file called gulpfile.js
Code:
var gulp=require('gulp'); // require the gulp package
gulp.task('hi',function(){
// print to console
console.log('Hello, world!');
});
// default gulp task (required)
gulp.task('default',['hi']);
We can now execute our gulp task by running "gulp hi" in the command line.
Code:
C:\Users\inori\Desktop\code\minify
λ node_modules\.bin\gulp hi
[11:23:39] Using gulpfile ~\Desktop\code\minify\gulpfile.js
[11:23:39] Starting 'hi'...
Hello, world!
[11:23:39] Finished 'hi' after 143 μs
For reference, the default task is a requirement of Gulp that executes when you run the CLI with no arguments.
Loading plugins
Before we minify all our code, we need to load our Gulp plugins. As I said earlier, gulp plugins are a breeze. All we need to do is require our plugin loader, pass it a few parameters, and we're done!
Code:
// plugin loader
var plugins=require('gulp-load-plugins')({
pattern: ['gulp.*','gulp-*'],
replaceString: /\bgulp[\-.]/
});
Bundling our code
Now that we know how to write tasks and load plugins, let's write a plugin to concatenate and minify all of our project's JavaScript in one file. We do this by finding the files we want (in this case all files in any directory inside the src directory. If you don't understand why, read up on globbing), then piping the stream to our plugins, and finally to a "dist" directory that we need to create beforehand.
Code:
// js minify task
gulp.task('js',function(){
gulp.src('src/**/*.js') // get the files we want via globbing
.pipe(plugins.concat('bundle.js')) // concatenate all of it to 'bundle.js'
.pipe(plugins.uglify()) // minify the code
.pipe(gulp.dest('dist')); // write the bundle file to dist dir
});
The css is slightly different, but no more difficult.
Code:
// css minify task
gulp.task('css',function(){
gulp.src('src/**/*.css') // glob files
.pipe(plugins.concat('bundle.css')) // concat to 'bundle.css'
.pipe(plugins.cleanCss()) // minify the file
.pipe(gulp.dest('dist')); // write to dist
});
Now we can include only the bundle.js and bundle.css files in our html files instead of whatever they were originally. Speaking of HTML, we can make a task for that, too.
Code:
// html copy task
gulp.task('html',function(){
gulp.src('src/**/*.html') // glob files
.pipe(gulp.dest('dist')); // copy files to dist w/ folder structure
});
Since we don't want to deal with running three commands, we can update our default task to run our other ones.
Code:
// default gulp task (required)
gulp.task('default',['js','css','html']);
Directory watching
Gulp has another awesome function: directory watching. In one line, you can listen for changes to any files in a glob path and trigger tasks when the event fires. Here's a quick one for our tasks.
Code:
// file watching task
gulp.task('watch',function(){
gulp.watch('src/**/*.js',['js']); // watch for js file changes
gulp.watch('src/**/*.css',['css']); // watch for css file changes
gulp.watch('src/**/*.html',['html']); // watch for html file changes
});
Epilogue
Obviously, this isn't all you can do with Gulp. With the hundreds of plugins available, possibilities are nearly endless for things you can accomplish. As a sibling to this thread, I made a github repo with instructions for installation and usage, as well as some goodies like a live server.
https://github.com/inoriy/gulp-tutorial
(This post was last modified: 01-24-2017, 07:25 PM by Inori.)
It's often the outcasts, the iconoclasts ... those who have the least to lose because they
don't have much in the first place, who feel the new currents and ride them the farthest.
don't have much in the first place, who feel the new currents and ride them the farthest.