Injecting Bower Dependencies into HTML Pages

October 13th 2016 Cordova Gulp Visual Studio

As described in a recent blog post, I selected Bower as the package manager for client-side JavaScript libraries in my Cordova project. I already took care of copying the required JavaScript files to a folder that will be packaged into the application. However, to use the scripts, they also need to be referenced from the HTML page(s). Although I probably won't be adding new libraries to the project all that often, I still don't want to do it manually if I can automate the process.

I'm sure, there are many ways, how this could be done, but since I'm already copying the JavaScript files with Gulp, it makes sense to also use it for injecting the references to the copied files. Of course, there is a plugin available for that. I'll start by installing it:

npm install gulp-inject --save-dev

Now, I can include it in my gulpfile.js and define a new task that will inject the script references:

var gulp = require("gulp");
var mainBowerFiles = require('gulp-main-bower-files');

gulp.task("inject-bower-files", function() {
  return gulp.src("./www/index.html")
    .pipe(inject(gulp.src(["./www/scripts/lib/**/*.js"], 
      { read: false }), { name: "bower", relative: true }))
    .pipe(gulp.dest("./www"));
});

Even for Gulp newbies like me, the configuration is not too difficult to understand:

  • The task will modify index.html from www folder and write it back to the same folder.
  • The list of scripts will be determined by scanning www/scripts/lib - that's the folder I copy the distribution files of my Bower packages to. To make the process faster, Gulp won't read the file contents.
  • The references will be injected into a section named bower, using relative paths to the scripts.

The above mentioned section needs to be defined in my index.html file:

<body>
  <!-- page content -->
  <!-- Cordova references -->
  <script src="cordova.js"></script>
  <script src="scripts/platformOverrides.js"></script>
  <!-- placeholder for Bower references -->
  <!-- bower:js -->
  <!-- endinject -->
  <!-- bundled application code -->
  <script src="scripts/appBundle.js"></script>
</body>

Running the Bower task will inject the script references at the designated placeholder:

<!-- bower:js -->
<script src="scripts/lib/angular/angular.js"></script>
<script src="scripts/lib/angular-route/angular-route.js"></script>
<!-- endinject -->

Since my Cordova app will be a SPA (single page application), I only need to inject the scripts into the root HTML page.

There's one more step left, to have Visual Studio run this task as part of its build process. I need to create a composite task, consisting of my original task for copying the Bower JavaScript files to the distribution folder and my newly created task for injecting references to these files:

gulp.task("process-bower-files", [
  "copy-bower-files", 
  "inject-bower-files"]);

By modifying the comment at the top of my gulpfile.js, I can instruct Visual Studio to run this new task instead of the original one:

/// <binding BeforeBuild='process-bower-files' />

That's it. Adding new JavaScript libraries couldn't be simpler now. I only need to install the corresponding Bower package and Gulp will take care of the rest: copy the required files to the right folder and reference them from the HTML page.

Copyright
Creative Commons License