Generating AngularJS production files with Gulp

Marijus Plančiūnas
4 min readOct 14, 2015

--

AngularJS is one the most powerful and widely used JavaScript frameworks at the moment. Whenever you browse through it’s documentation, you get to a question about code quality and “how to do it right”. Surprisingly, instead of having it’s own style guide, Google is pointing to external, hosted on GitHub.

One of the rules there — separate your classes into files. It’s logical: makes your code more readable, however — unusual to older JavaScript coders, which tend to have one big script.js or main.js file instead. It’s obvious, that separating your functions / classes into files will cause additional HTTP requests to retrieve them once you’re including <script> tags in the document head. To avoid this, we use process automation systems like Gulp to generate production-ready files, by combining separate files into one.

Following Angular Style Guide above, let’s create a gulpfile.js, which would generate production ready files. I’ve picked up required plugins by my own personal preference, but of course — you can replace them to the ones you like.

Let’s define:

  • we have a public/app directory, where we place our AngularJS code;
  • we have a public/src directory, where we want final file to be generated.

Concatenating sources

We will need to:

  • Grab all source files, in correct order: core file (let’s say it’s app.js), modules, then the rest. We will use simple gulp.src() for this.
  • Concatenate them. gulp-concat is great candidate, however — I like to override their default new line option.
  • As we’re lazy, but strict, let’s automatically annotate our code where required. gulp-ng-annotate does the job correctly.
  • Write our output to one file.

Side note: Gulp runs on Node, which is sensitive for errors. To avoid our script from crashing, let’s use gulp-plumber, until new Gulp versions will have error handling built-in natively.

There — we’ll have public/src/app.js file, which can be included in development environment in one <script> call.

Important: that’s a subtask, which will be used in further scripts as well, as a dependency. It’s important to use return statement in function for such cases — otherwise it will be executed in parallel.

Minifying and making it production ready

Before moving to distribution, we need to prepare our sources. Let’s outline our tasks:

  • Minify code — and of course, gulp-uglify is a king here. But, how about checking it’s performance as well through gulp-bytediff?
  • And we’ll need to use one of renaming packages to avoid overwriting our original source.
  • Surely, this task depends on the one we’ve created before — so let’s put a dependency to it.

Now we have public/src/app.min.js file, which we already can use in production.

Optional: you can use gulp-sourcemaps to generate source maps for minified file. But, as we’re using non-minified version for development, unless you’re chasing a production-specific bug, this is not necessary.

Creating a watcher

In development, instead of launching gulp for specific task every time you change something, we’re using watchers. Let’s create one, using scripts we have already.

As you can see, we have a default task (launched automatically, unless you provide specific task name for gulp command line), which launches app and watch tasks.

gulp.watch() function is used to check for any changes in JavaScript files, and in case there are any — prod task is launched.

As an additional note, we also launch app task at the beginning to regenerate our sources (this is optional of course — but I like fresh start), also it’s being launched as a dependency before prod task.

One pitfall: unfortunatelly, there’s no “normal” way to check for newly created files; watchers will monitor only ones which existed on launch. You will have to terminate gulp with CTRL+C (or Command+C) and launch it again, so watcher can re-scan your directories.

Deploying in production

Here, we have couple of choices:

  • we can use package gulp-cachebust to generate unique file names (thanks Juan), or
  • we can let back-end to handle this.

If you’re using auto-renaming plugin in gulp, you won’t have a static name at the end — so use file system scanning functions, like glob in PHP, to include files in your document.

If you’re using package, like Laravel Assets Versioning, it is capable of handling naming by itself. For latter, your Blade code would look similar to this:

@if ( App::environment('local') )
<script src="{{ Asset::v('src/app.js') }}"></script>
@else
<script src="{{ Asset::v('src/app.min.js') }}"></script>
@endif

Conclusion

Writing gulp scripts simple, but needs some preparation before. My general advice would be:

  • Separate your tasks.
  • Outline your goals.
  • Combine packages where required.
  • Don’t use one system to rule them all.

--

--