CINXE.COM

Sample Gruntfile - Grunt: The JavaScript Task Runner

<!DOCTYPE html><html lang="en" prefix="og: http://ogp.me/ns#" itemscope itemtype="http://schema.org/WebPage"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Sample Gruntfile - Grunt: The JavaScript Task Runner</title><link rel="stylesheet" href="/css/main.css"><link rel="apple-touch-icon" href="/img/favicons/apple-touch-icon.png" sizes="180x180"><link rel="icon" type="image/png" href="/img/favicons/favicon-32x32.png" sizes="32x32"><link rel="icon" type="image/png" href="/img/favicons/favicon-16x16.png" sizes="16x16"><link rel="manifest" href="/img/favicons/manifest.json"><link rel="mask-icon" href="/img/favicons/safari-pinned-tab.svg" color="#e48632"><link rel="shortcut icon" href="/img/favicons/favicon.ico" type="image/x-icon"><meta name="msapplication-config" content="/img/favicons/browserconfig.xml"><meta name="theme-color" content="#e48632"><meta property="og:title" content="Sample Gruntfile - Grunt: The JavaScript Task Runner"><meta property="og:type" content="website"><meta property="og:url" content="https://gruntjs.com/"><meta property="og:image" content="https://gruntjs.com/img/og.png"><meta property="og:image:type" content="image/png"><meta property="og:image:width" content="256"><meta property="og:image:height" content="256"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:creator" content="@gruntjs"><meta name="twitter:site" content="@gruntjs"><meta name="twitter:title" content="Sample Gruntfile - Grunt: The JavaScript Task Runner"><meta itemprop="name" content="Grunt"><meta itemprop="image" content="/img/og.png"><link href="/rss" rel="alternate" title="Grunt Blog Feed" type="application/atom+xml"></head><body class="page-docs page-secondary"><div class="banner"> <a href="support">V1.6.1 is the current version, and previous versions are not supported. Upgrade to the latest version or consider other support options.</a></div><div class="navbar navbar-inverse"><div class="navbar-inner"><div class="container"><a class="brand" href="/"><span class="logo"></span></a><div class="nav-collapse collapse"><ul class="nav"><li><a href="/getting-started"><i class="icon-arrow-right"></i><span>Getting Started</span></a></li><li><a href="/configuring-tasks"><i class="icon-cog"></i><span>Configuring Tasks</span></a></li><li><a href="/plugins"><i class="icon-power-cord"></i><span>Plugins</span></a></li><li><a href="/documentation"><i class="icon-file-text"></i><span>Documentation</span></a></li><li><a href="/support"><i class="icon-file-text"></i><span>Support</span></a></li></ul><form class="navbar-search pull-right"><input class="search-query" type="text" placeholder="Search"></form></div><!--.nav-collapse--></div></div></div><div class="content"><div class="container sample-gruntfile"><div class="row-fluid"><div class="span9 page"><div class="hero-unit"><h1>Sample Gruntfile</h1><p>In this page we walk you through the creation of a <code>Gruntfile</code> that covers the usual needs of a simple project. If you already know how to set up a <code>Gruntfile</code> and you&#39;re looking for a quick example, here&#39;s one:</p> <pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">grunt</span>) </span>{ grunt.initConfig({ <span class="hljs-attr">jshint</span>: { <span class="hljs-attr">files</span>: [<span class="hljs-string">'Gruntfile.js'</span>, <span class="hljs-string">'src/**/*.js'</span>, <span class="hljs-string">'test/**/*.js'</span>], <span class="hljs-attr">options</span>: { <span class="hljs-attr">globals</span>: { <span class="hljs-attr">jQuery</span>: <span class="hljs-literal">true</span> } } }, <span class="hljs-attr">watch</span>: { <span class="hljs-attr">files</span>: [<span class="hljs-string">'&lt;%= jshint.files %&gt;'</span>], <span class="hljs-attr">tasks</span>: [<span class="hljs-string">'jshint'</span>] } }); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-jshint'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-watch'</span>); grunt.registerTask(<span class="hljs-string">'default'</span>, [<span class="hljs-string">'jshint'</span>]); };</code></pre> <h2><a class="anchor" href="#requirements" id="requirements"></a>Requirements</h2> <p>Every project has its own needs, but most of them have something in common. In this guide we introduce you to a few Grunt plugins to automate basic requirements. The final goal is to teach you how to configure these Grunt plugins so that you can use them in your projects.</p> <p>For the sake of the example, let&#39;s say that you&#39;re creating a JavaScript library. The typical folder structure features the following folders: <code>src</code>, <code>dist</code>, and <code>test</code>. The <code>src</code> folder (sometimes called <code>app</code>) contains the source code of the library as you author it. The <code>dist</code> folder (sometimes called <code>build</code>) contains the distribution, a minified version of the source code. A minified file is one where all unnecessary characters, such as spaces, new lines, comments are removed, without affecting the functionality of the source code. Minified source code is especially useful for users of the project because it reduces the amount of data that needs to be transferred. Finally, the <code>test</code> folder contains the code to test the project. This set up will be used in the next sections when creating the <code>Gruntfile</code> configuration.</p> <p>While developing the library and releasing new versions there are a few tasks that you need to perform on a regular basis. For example, you might want to ensure that the code you write adheres to best practices, or that the code you&#39;ve written doesn&#39;t result in unexpected behaviors. To do that, you can employ a tool called <a href="http://jshint.com/about/">JSHint</a>. Grunt has an official plugin for it called <a href="https://github.com/gruntjs/grunt-contrib-jshint">grunt-contrib-jshint</a> which we&#39;ll adopt in this example. In particular, you might want to ensure that as you modify your code, you don&#39;t break any rules or best practices. So, a good strategy is to check the code at every change you perform. To do that, we&#39;ll cover a Grunt plugin called <a href="https://github.com/gruntjs/grunt-contrib-watch">grunt-contrib-watch</a>. The latter runs predefined tasks, such as <code>grunt-contrib-jshint</code>, whenever files are added, changed, or deleted.</p> <p>Checking that your source code follows best practices is not enough to guarantee that it&#39;s stable and doesn&#39;t contain bugs. To create a robust project, you need to test it. There are several libraries you can adopt such as <a href="https://qunitjs.com/">QUnit</a> or <a href="http://jasmine.github.io/">Jasmine</a>. In this guide, we describe how to configure QUnit, and specifically <a href="https://github.com/gruntjs/grunt-contrib-qunit">grunt-contrib-qunit</a>, to test your code.</p> <p>When it comes to distributing your work, you want to offer a version as small in size as possible. To create a minified version you need a Grunt plugin like <a href="https://github.com/gruntjs/grunt-contrib-uglify">grunt-contrib-uglify</a>. Moreover, unless the project you&#39;re developing is very small, chances are that you&#39;ve split the code in multiple files. While this is a good practice for the developer, you want users to include only one file. So, before minifying the code, you should concatenate the source files to create a single one. To achieve this goal you need a Grunt plugin like <a href="https://github.com/gruntjs/grunt-contrib-concat">grunt-contrib-concat</a>.</p> <p>To sum up, in this guide we&#39;ll use the following five Grunt plugins:</p> <ul> <li><a href="https://github.com/gruntjs/grunt-contrib-uglify">grunt-contrib-uglify</a></li> <li><a href="https://github.com/gruntjs/grunt-contrib-qunit">grunt-contrib-qunit</a></li> <li><a href="https://github.com/gruntjs/grunt-contrib-concat">grunt-contrib-concat</a></li> <li><a href="https://github.com/gruntjs/grunt-contrib-jshint">grunt-contrib-jshint</a></li> <li><a href="https://github.com/gruntjs/grunt-contrib-watch">grunt-contrib-watch</a></li> </ul> <p>If you&#39;re curious about what the final result looks like, the entire <code>Gruntfile</code> can be found at the bottom of this page.</p> <h2><a class="anchor" href="#setting-up-the-gruntfile" id="setting-up-the-gruntfile"></a>Setting up the <code>Gruntfile</code></h2> <p>The first part is the &quot;wrapper&quot; function, which encapsulates your Grunt configuration.</p> <pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">grunt</span>) </span>{ };</code></pre> <p>Within that function we can initialize our configuration object:</p> <pre><code class="lang-js">grunt.initConfig({ });</code></pre> <p>Next, we can store the project settings from the <code>package.json</code> file into the <code>pkg</code> property. This allows us to refer to the values of properties within our <code>package.json</code> file, as we&#39;ll see shortly.</p> <pre><code class="lang-js">pkg: grunt.file.readJSON(<span class="hljs-string">'package.json'</span>)</code></pre> <p>This leaves us with this so far:</p> <pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">grunt</span>) </span>{ grunt.initConfig({ <span class="hljs-attr">pkg</span>: grunt.file.readJSON(<span class="hljs-string">'package.json'</span>) }); };</code></pre> <p>Now we can define a configuration for each of the tasks we mentioned. The configuration object for a plugin lives as a property on the configuration object, that often shares the same name as its plugin. The configuration for <code>grunt-contrib-concat</code> goes in the configuration object under the <code>concat</code> key as shown below:</p> <pre><code class="lang-js">concat: { <span class="hljs-attr">options</span>: { <span class="hljs-comment">// define a string to put between each file in the concatenated output</span> separator: <span class="hljs-string">';'</span> }, <span class="hljs-attr">dist</span>: { <span class="hljs-comment">// the files to concatenate</span> src: [<span class="hljs-string">'src/**/*.js'</span>], <span class="hljs-comment">// the location of the resulting JS file</span> dest: <span class="hljs-string">'dist/&lt;%= pkg.name %&gt;.js'</span> } }</code></pre> <p>Note how in the snippet above we refer to the <code>name</code> property that&#39;s in the JSON file. We access it by using <code>pkg.name</code> as earlier we defined the <code>pkg</code> property to be the result of loading the <code>package.json</code> file, which is then parsed to a JavaScript object. Grunt has a simple template engine to output the values of properties in the configuration object. Here we tell the <code>concat</code> task to concatenate all files that exist within <code>src/</code> and end in <code>.js</code>.</p> <p>Now let&#39;s configure the <code>grunt-contrib-uglify</code> plugin, which minifies the JavaScript code:</p> <pre><code class="lang-js">uglify: { <span class="hljs-attr">options</span>: { <span class="hljs-comment">// the banner is inserted at the top of the output</span> banner: <span class="hljs-string">'/*! &lt;%= pkg.name %&gt; &lt;%= grunt.template.today("dd-mm-yyyy") %&gt; */\n'</span> }, <span class="hljs-attr">dist</span>: { <span class="hljs-attr">files</span>: { <span class="hljs-string">'dist/&lt;%= pkg.name %&gt;.min.js'</span>: [<span class="hljs-string">'&lt;%= concat.dist.dest %&gt;'</span>] } } }</code></pre> <p>This snippet tells <code>grunt-contrib-uglify</code> to create a file within <code>dist/</code> that contains the result of minifying the JavaScript files. Here we use <code>&lt;%= concat.dist.dest %&gt;</code> so uglify will minify the file that the concat task produces.</p> <p>Up to this point, we have configured the plugins to create the distribution version the library. It&#39;s now time to use <code>grunt-contrib-qunit</code> to automate the testing of the code. To do that, we need to give to specify the location of the test runner files, which are the HTML files QUnit runs on. The resulting code is reported below:</p> <pre><code class="lang-js">qunit: { <span class="hljs-attr">files</span>: [<span class="hljs-string">'test/**/*.html'</span>] },</code></pre> <p>Once done, it&#39;s time to set up the configuration to ensure that the code of the project adheres to best practices. JSHint is a tool that can detect issues or potential issues like a high cyclomatic complexity, the use of the equality operator instead of the strict equality operator, and the definition of unused variables and functions.</p> <p>We advise you to analyze with <code>grunt-contrib-jshint</code> all the JavaScript files of your project, including <code>Gruntfile</code> and the test files. An example of configuration of <code>grunt-contrib-jshint</code> is the following:</p> <pre><code class="lang-js">jshint: { <span class="hljs-comment">// define the files to lint</span> files: [<span class="hljs-string">'Gruntfile.js'</span>, <span class="hljs-string">'src/**/*.js'</span>, <span class="hljs-string">'test/**/*.js'</span>], <span class="hljs-comment">// configure JSHint (documented at http://www.jshint.com/docs/)</span> options: { <span class="hljs-comment">// more options here if you want to override JSHint defaults</span> globals: { <span class="hljs-attr">jQuery</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">console</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">module</span>: <span class="hljs-literal">true</span> } } }</code></pre> <p>This plugin takes an array of files and then an object of options. These are all <a href="http://www.jshint.com/docs/">documented on the JSHint site</a>. If you&#39;re happy with the plugin defaults, there&#39;s no need to redefine them in the Gruntfile.</p> <p>The last plugin left to configure is <code>grunt-contrib-watch</code>. We&#39;ll use it to run the <code>jshint</code> and the <code>qunit</code> tasks as soon as a JavaScript file is added, deleted, or modified. When it detects any of the files specified have changed (here, we use the same files we told JSHint to check), it will run the tasks you specify, in the order they appear. This can be run on the command line with <code>grunt watch</code>.</p> <p>Turning the previous description into a configuration for <code>grunt-contrib-watch</code> results in the snippet below:</p> <pre><code class="lang-js">watch: { <span class="hljs-attr">files</span>: [<span class="hljs-string">'&lt;%= jshint.files %&gt;'</span>], <span class="hljs-attr">tasks</span>: [<span class="hljs-string">'jshint'</span>, <span class="hljs-string">'qunit'</span>] }</code></pre> <p>With this snippet, we&#39;ve set up the configuration for all the plugins mentioned in the introduction. The last step to perform is to load in the Grunt plugins we need. All of these should have been previously installed through npm.</p> <pre><code class="lang-js">grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-uglify'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-jshint'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-qunit'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-watch'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-concat'</span>);</code></pre> <p>And finally set up some tasks. The most important of these tasks is the default task:</p> <pre><code class="lang-js"><span class="hljs-comment">// this would be run by typing "grunt test" on the command line</span> grunt.registerTask(<span class="hljs-string">'test'</span>, [<span class="hljs-string">'jshint'</span>, <span class="hljs-string">'qunit'</span>]); <span class="hljs-comment">// the default task can be run just by typing "grunt" on the command line</span> grunt.registerTask(<span class="hljs-string">'default'</span>, [<span class="hljs-string">'jshint'</span>, <span class="hljs-string">'qunit'</span>, <span class="hljs-string">'concat'</span>, <span class="hljs-string">'uglify'</span>]);</code></pre> <p>The default task is executed when you invoke <code>Grunt</code> without specifying a task to execute (<code>grunt</code>).</p> <h2><a class="anchor" href="#the-resulting-gruntfile" id="the-resulting-gruntfile"></a>The resulting <code>Gruntfile</code></h2> <p>If you&#39;ve followed this guide correctly you should have the following <code>Gruntfile</code>:</p> <pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">grunt</span>) </span>{ grunt.initConfig({ <span class="hljs-attr">pkg</span>: grunt.file.readJSON(<span class="hljs-string">'package.json'</span>), <span class="hljs-attr">concat</span>: { <span class="hljs-attr">options</span>: { <span class="hljs-attr">separator</span>: <span class="hljs-string">';'</span> }, <span class="hljs-attr">dist</span>: { <span class="hljs-attr">src</span>: [<span class="hljs-string">'src/**/*.js'</span>], <span class="hljs-attr">dest</span>: <span class="hljs-string">'dist/&lt;%= pkg.name %&gt;.js'</span> } }, <span class="hljs-attr">uglify</span>: { <span class="hljs-attr">options</span>: { <span class="hljs-attr">banner</span>: <span class="hljs-string">'/*! &lt;%= pkg.name %&gt; &lt;%= grunt.template.today("dd-mm-yyyy") %&gt; */\n'</span> }, <span class="hljs-attr">dist</span>: { <span class="hljs-attr">files</span>: { <span class="hljs-string">'dist/&lt;%= pkg.name %&gt;.min.js'</span>: [<span class="hljs-string">'&lt;%= concat.dist.dest %&gt;'</span>] } } }, <span class="hljs-attr">qunit</span>: { <span class="hljs-attr">files</span>: [<span class="hljs-string">'test/**/*.html'</span>] }, <span class="hljs-attr">jshint</span>: { <span class="hljs-attr">files</span>: [<span class="hljs-string">'Gruntfile.js'</span>, <span class="hljs-string">'src/**/*.js'</span>, <span class="hljs-string">'test/**/*.js'</span>], <span class="hljs-attr">options</span>: { <span class="hljs-comment">// options here to override JSHint defaults</span> globals: { <span class="hljs-attr">jQuery</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">console</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">module</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">document</span>: <span class="hljs-literal">true</span> } } }, <span class="hljs-attr">watch</span>: { <span class="hljs-attr">files</span>: [<span class="hljs-string">'&lt;%= jshint.files %&gt;'</span>], <span class="hljs-attr">tasks</span>: [<span class="hljs-string">'jshint'</span>, <span class="hljs-string">'qunit'</span>] } }); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-uglify'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-jshint'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-qunit'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-watch'</span>); grunt.loadNpmTasks(<span class="hljs-string">'grunt-contrib-concat'</span>); grunt.registerTask(<span class="hljs-string">'test'</span>, [<span class="hljs-string">'jshint'</span>, <span class="hljs-string">'qunit'</span>]); grunt.registerTask(<span class="hljs-string">'default'</span>, [<span class="hljs-string">'jshint'</span>, <span class="hljs-string">'qunit'</span>, <span class="hljs-string">'concat'</span>, <span class="hljs-string">'uglify'</span>]); };</code></pre> <div class="end-link">Found an error in the documentation? <a href='https://github.com/gruntjs/grunt-docs/issues'>File an issue</a>.</div></div></div><div class="span3"><div class="well sidebar-nav"><ul class="nav nav-list"><li class="nav-header"><i class="icon-file-text"></i><span>Documentation</span></li><li><a href="/getting-started">Getting Started</a></li><li><a href="/configuring-tasks">Configuring Tasks</a></li><li><a class="active" href="/sample-gruntfile">Sample Gruntfile</a></li><li><a href="/creating-tasks">Creating Tasks</a></li><li><a href="/creating-plugins">Creating Plugins</a></li><li><a href="/using-the-cli">Using the CLI</a></li></ul><ul class="nav nav-list"><li class="nav-header"><span>Advanced</span></li><li><a href="/api">API</a></li><li><a href="/installing-grunt">Installing Grunt</a></li><li><a href="/frequently-asked-questions">Frequently Asked Questions</a></li><li><a href="/project-scaffolding">Project Scaffolding</a></li></ul><ul class="nav nav-list"><li class="nav-header"><span>Community</span></li><li><a href="/support">Support</a></li><li><a href="/help-resources">Help Resources</a></li><li><a href="/who-uses-grunt">Who uses Grunt</a></li><li><a href="/built-with-grunt-badge">Built with Grunt Badge</a></li><li><a href="/contributing">Contributing</a></li><li><a href="/development-team">Development Team</a></li></ul><ul class="nav nav-list"><li class="nav-header"><span>Migration guides</span></li><li><a href="/upgrading-from-0.3-to-0.4">Upgrading from 0.3 to 0.4</a></li><li><a href="/upgrading-from-0.4-to-1.0">Upgrading from 0.4 to 1.0</a></li></ul></div></div></div></div></div><footer class="grunt-footer"><div class="inner"><div class="container"><ul class="pull-right"><li><a href="/blog">Blog</a></li><li><a href="/upgrading-from-0.3-to-0.4">Migration Guides</a></li><li><a href="/contributing">Contributing</a></li><li><a href="/development-team">Development Team</a></li><li class="social"><a href="https://github.com/gruntjs/" title="Grunt on GitHub"><span class="icon-github"></span></a></li><li class="social"><a href="https://twitter.com/gruntjs/" title="Grunt on Twitter"><span class="icon-twitter"></span></a></li><li class="social"><a href="/rss" title="Grunt blog RSS feed"><span class="icon-rss"></span></a></li><li class="openjs"><a href="https://openjsf.org/" title="OpenJS Foundation"><img src="/img/openjsf-color-textw.svg" alt="OpenJS Foundation" width="100" height="31"></a></li></ul></div></div></footer></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10