Insert Script Tags Automatically Using Grunt

Introducing the File Blocks Grunt Task

During development on a web project I like to keep all of my JavaScript files separate. This keeps files organized in the debugger and makes it easy to find code that I’m interested in. I only concatenate the files when I’m ready to deploy the project. In order to accomplish this I need to add individual script tags for each script file. Since I don’t like doing any repetitive task manually I wanted a tool to do this for me.

In this post I’ll show you how to use the Grunt plugin grunt-file-blocks to manage these script tags automatically. This task uses globbing (file matching) patterns to identify a list of files in a project. For each identified file a line of content will be inserted into a source file. I’m assuming that you already know the basics of Grunt: The JavaScript Task Runner. If you aren’t familiar with this tool read the getting started guide before continuing.

Note: I wrote grunt-file-blocks in conjunction with a large project at my day job.

The tutorial will use the AngularJS code from the TodoMVC project. The code is structured as seen below. Our goal is to add a script tag to index.html for each of the JavaScript files below the js directory.

To being we need to install the module by typing the following at a command prompt.

Simple Configuration

We’ll start by adding the grunt-file-blocks task to our project’s Gruntfile.js. The task configuration will include just one target named todos.

Next we need to specify the file that will be modified by the task. The file being modified is called the source file.

Now we can add a file block that includes rules on how to identify JavaScript files. For this simple example we will use a single file block named app. Files are matched by using globbing patterns. The pattern below will match all files with the .js extension that are in or below the js directory.

The final configuration step requires us to declare the file block in the source file. Blocks are marked by using comments that serve as anchors. One anchor marks the beginning of the block and another marks the end of the block. Two comment types are recognized. For HTML files use an HTML comment <!– –> and for JavaScript or TypeScript files use the /* */ syntax. All content inside the block is managed by the plugin.

If we examine the index.html file in the sample code we find the script tags near the end of the file. We’ll replace the last five script tags with comment anchors.

The text fileblock and endfileblock are keywords that identify a starting anchor and ending anchor respectively. The word app must match the name that we gave our block in the previous step. The word directly following the colon in the starting tag specifies the template. The plugin provides four built-in templates. We will use the js template to insert a script tag. The token ${file} will be replaced by the path and file name that was matched by our globbing pattern.

Templates

js
<script src=”${file}”></script>
css
<link href=”${file}” rel=”stylesheet” />
ref
/// <reference path=”${file}” />
raw
${file}

Our simple configuration is now complete. Let’s try running the task and review the results.

Intermediate Configuration

In the simple configuration you may have noticed that the order of the scripts was slightly different than the original. If this causes problems you have several options. The easiest fix is to simply change the order of the script tags manually. By default the task only inserts new lines but does not remove lines for files that are no longer found. The fileblocks task will preserve the order of previously inserted lines.

A better option is to use additional globbing patterns to be more specific about the order of matched files. In this configuration the src property on the block configuration was changed from a string to an array of strings. The order of the globbing patterns is significant as they will be applied in order. Using this set of patterns the app.js file will be first followed by the files in the services directory. The last pattern, our original one, will match any remaining scripts that haven’t already been added.

If you need even more control over the process you can add multiple file blocks within the source file each with their own globbing patterns.

Advanced Configuration

The fileblocks task is very flexible and can accommodate complex configurations.  We will take a look at two of these options that are quite useful. In the previous examples we modified a single source file. In the next configuration the Grunt target has been altered to modify two source files. The first file is the HTML file from our simple example. The second file is a TypeScript references file that will contain reference comments for other TypeScript files.

Finally we will create a custom template. If you aren’t happy with the provided templates or you need your own you can specify them in the task configuration. In the following configuration the default js template has been overridden and a custom template jsdata has been defined.

Combining Other Grunt Tasks

We are pretty close to achieving our original goal of automatically inserting script tags into our HTML file. One notable exception is that we have been executing the Grunt task on the command line each time we wanted to update the source file. Ideally this would be done every time we added or removed a JavaScript file. We can accomplish this by adding the grunt-contrib-watch task. The watch task can trigger the fileblocks task any time there is a file added, modified, or deleted.

The new configuration includes the watch task. The configuration of the watch task is pretty straightforward. Any time a file is modified (including being added or deleted) that matches the globbing pattern the fileblocks:todos task will be run. Notice the small change in the configuration of the watch task. The removeFiles option has been set. This allows the watch task to remove lines in the block after a file has been deleted.

Another great combination is using the fileblocks task with grunt-usemin. The usemin task is a great way to handle the build and packaging process for a JavaScript project. One or more file blocks can be combined inside a usemin build block as seen below.

Conclusion

Useful tools are a great way to automate slow, manual and error prone tasks. The fileblocks Grunt task can be used to automatically insert a line of content into a source file for any files found using globbing patterns. It is easy to configure for simple projects but offers a great deal of flexibility for more complex scenarios. I hope you find this article, and the task that inspired it, to be useful. Feel free to offer feedback on the fileblocks task at the Github repository.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">