CINXE.COM
Upgrading from 0.3 to 0.4 - 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>Upgrading from 0.3 to 0.4 - 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="Upgrading from 0.3 to 0.4 - 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="Upgrading from 0.3 to 0.4 - 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 upgrading-from-0.3-to-0.4"><div class="row-fluid"><div class="span9 page"><div class="hero-unit"><h1>Upgrading from 0.3 to 0.4</h1><blockquote> <p>Versions 0.4 and older are no longer maintained. Find out more and see additional support options <a href="/support">here</a>.</p> </blockquote> <p><em>Note that even if you are familiar with grunt, it would be worthwhile to read the new <a href="/getting-started/">Getting started</a> guide.</em></p> <p>Grunt is now split into three parts: <code>grunt</code>, <code>grunt-cli</code> and <code>grunt-init</code>.</p> <ol> <li>The npm module <code>grunt</code> should be installed locally to your project. It contains the code and logic for running tasks, loading plugins, etc.</li> <li>The npm module <code>grunt-cli</code> should be installed globally. It puts the <code>grunt</code> command in your PATH so you can execute it anywhere. By itself, it doesn't do anything; its job is to load and run the Grunt that has been installed locally to your project, regardless of the version. For more information about why this has changed, please read <a href="http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation">npm 1.0: Global vs Local installation</a>.</li> <li>The <code>init</code> task has been broken into its own npm module, <code>grunt-init</code>. It should be installed globally with <code>npm install -g grunt-init</code> and run with the <code>grunt-init</code> command. In the coming months, <a href="http://yeoman.io/">Yeoman</a> will completely replace grunt-init. See the <a href="https://github.com/gruntjs/grunt-init">grunt-init project page</a> for more information.</li> </ol> <h2><a class="anchor" href="#grunt-0.3-notes" id="grunt-0.3-notes"></a>Grunt 0.3 Notes</h2> <p>If you are upgrading from Grunt 0.3, make sure to uninstall global <code>grunt</code>:</p> <pre><code class="lang-shell">npm uninstall -g grunt</code></pre> <p><em>Note that for 0.3.x, plugin names and task configuration options may be different than those shown in "The Gruntfile" section.</em></p> <p><em>This file was named <code>grunt.js</code> for 0.3.x versions of Grunt.</em></p> <h2><a class="anchor" href="#pre-existing-tasks-and-plugins" id="pre-existing-tasks-and-plugins"></a>Pre-existing tasks and plugins</h2> <p>All <code>grunt-contrib-*</code> series plugins are Grunt 0.4 ready. However, it is highly unlikely that third party plugins written for Grunt 0.3 will continue to work with 0.4 until they have been updated. We are actively working with plugin authors to ensure this happens as swiftly as possible.</p> <p><em>A forthcoming Grunt release will be focused on decoupling grunt's architecture so that plugins are not affected by future updates.</em></p> <h2><a class="anchor" href="#requirements" id="requirements"></a>Requirements</h2> <ul> <li>Grunt now requires Node.js version <code>>= 0.8.0</code></li> </ul> <h2><a class="anchor" href="#the-gruntfile" id="the-gruntfile"></a>The Gruntfile</h2> <ul> <li>The "Gruntfile" has changed from <code>grunt.js</code> to <code>Gruntfile.js</code>.</li> <li>CoffeeScript is supported in your <code>Gruntfile.coffee</code> project <code>Gruntfile</code> or <code>*.coffee</code> task files (transpiling to JS happens automatically).</li> </ul> <p>See the "The Gruntfile" section of the <a href="/getting-started/">Getting started</a> guide for more information.</p> <h2><a class="anchor" href="#core-tasks-are-now-grunt-plugins" id="core-tasks-are-now-grunt-plugins"></a>Core Tasks are now Grunt Plugins</h2> <p>The eight core tasks that were included in Grunt 0.3 are now separate Grunt plugins. Each is a discrete npm module that must be installed as a plugin per the "Loading Grunt plugins and tasks" section of the <a href="/getting-started/">Getting started</a> guide.</p> <ul> <li>concat → <a href="https://github.com/gruntjs/grunt-contrib-concat">grunt-contrib-concat</a> plugin</li> <li>init → stand-alone <a href="https://github.com/gruntjs/grunt-init">grunt-init</a> utility</li> <li>lint → <a href="https://github.com/gruntjs/grunt-contrib-jshint">grunt-contrib-jshint</a> plugin</li> <li>min → <a href="https://github.com/gruntjs/grunt-contrib-uglify">grunt-contrib-uglify</a> plugin</li> <li>qunit → <a href="https://github.com/gruntjs/grunt-contrib-qunit">grunt-contrib-qunit</a> plugin</li> <li>server → <a href="https://github.com/gruntjs/grunt-contrib-connect">grunt-contrib-connect</a> plugin</li> <li>test → <a href="https://github.com/gruntjs/grunt-contrib-nodeunit">grunt-contrib-nodeunit</a> plugin</li> <li>watch → <a href="https://github.com/gruntjs/grunt-contrib-watch">grunt-contrib-watch</a> plugin</li> </ul> <p>Some task names and options have changed. Be sure to see each plugin's documentation as linked above for the latest configuration details.</p> <h2><a class="anchor" href="#configuration" id="configuration"></a>Configuration</h2> <p>The configuration format for Grunt 0.4 tasks has been standardized and greatly enhanced. See the <a href="/configuring-tasks/">Configuring tasks</a> guide, as well as individual plugin documentation for more information.</p> <ul> <li>File globbing (wildcard) patterns may now be negated to exclude matched files.</li> <li>Tasks now support a standard <code>options</code> object.</li> <li>Tasks now support a standard <code>files</code> object.</li> </ul> <p><code><% %></code> style template strings specified as config data inside the <code>Gruntfile</code> are automatically expanded, see the <a href="/grunt.template/">grunt.template</a> documentation for more information.</p> <p><strong>Directives have been removed</strong>, but their functionality has been retained. These replacements can be made:</p> <ul> <li><code>'<config:prop.subprop>'</code> → <code>'<%= prop.subprop %>'</code></li> <li><code>'<json:file.json>'</code> → <code>grunt.file.readJSON('file.json')</code></li> <li><code>'<file_template:file.js>'</code> → <code>grunt.template.process(grunt.file.read('file.js'))</code></li> </ul> <p>Instead of specifying a banner in a file list with <code>'<banner>'</code> or <code>'<banner:prop.subprop>'</code>, the <a href="https://github.com/gruntjs/grunt-contrib-concat">grunt-contrib-concat</a> and <a href="https://github.com/gruntjs/grunt-contrib-uglify">grunt-contrib-uglify</a> plugins each have a <code>banner</code> option.</p> <p>Instead of stripping banners from files individually with <code>'<file_strip_banner:file.js>'</code>, the <a href="https://github.com/gruntjs/grunt-contrib-concat">grunt-contrib-concat</a> and <a href="https://github.com/gruntjs/grunt-contrib-uglify">grunt-contrib-uglify</a> plugins each have an option to strip/preserve banners.</p> <h2><a class="anchor" href="#alias-task-changes" id="alias-task-changes"></a>Alias task changes</h2> <p>When specifying an alias task, the list of tasks to run must now be specified as an array.</p> <pre><code class="lang-js"><span class="hljs-comment">// v0.3.x (old format)</span> grunt.registerTask(<span class="hljs-string">"default"</span>, <span class="hljs-string">"jshint nodeunit concat"</span>); <span class="hljs-comment">// v0.4.x (new format)</span> grunt.registerTask(<span class="hljs-string">"default"</span>, [<span class="hljs-string">"jshint"</span>, <span class="hljs-string">"nodeunit"</span>, <span class="hljs-string">"concat"</span>]);</code></pre> <h2><a class="anchor" href="#task-arguments-may-now-contain-spaces" id="task-arguments-may-now-contain-spaces"></a>Task arguments may now contain spaces</h2> <p>The aforementioned alias task change (task lists must be specified as an array) makes this possible. Just be sure to surround task arguments containing spaces with quotes when specifying them on the command line, so they can be properly parsed.</p> <pre><code class="lang-shell">grunt my-task:argument-without-spaces <span class="hljs-string">"other-task:argument with spaces"</span></code></pre> <h2><a class="anchor" href="#character-encodings" id="character-encodings"></a>Character encodings</h2> <p>The <a href="/grunt.file#wiki-grunt-file-defaultencoding">file.defaultEncoding</a> method was added to normalize character encodings, and all <code>grunt.file</code> methods have been updated to support the specified encoding.</p> <h2><a class="anchor" href="#helpers" id="helpers"></a>Helpers</h2> <p>Grunt's helper system has been removed in favor of node <code>require</code>. For a concise example on how to share functionality between Grunt plugins, please see <a href="https://github.com/gruntjs/grunt-lib-legacyhelpers">grunt-lib-legacyhelpers</a>. Plugin authors are encouraged to upgrade their plugins.</p> <h2><a class="anchor" href="#api" id="api"></a>API</h2> <p>The Grunt API saw substantial changes from 0.3 to 0.4.</p> <ul> <li><a href="/grunt">grunt</a><ul> <li>Removed <code>grunt.registerHelper</code> and <code>grunt.renameHelper</code> methods.</li> </ul> </li> <li><a href="/grunt.config">grunt.config</a><ul> <li>Changed <a href="/grunt.config#wiki-grunt-config-get">config.get</a> method to automatically recursively expand <code><% %></code> templates.</li> <li>Added <a href="/grunt.config#wiki-grunt-config-getraw">config.getRaw</a> method that will retrieve raw (unexpanded) config data.</li> <li>Changed <a href="/grunt.config#wiki-grunt-config-process">config.process</a> method to now process a value as if it had been retrieved from the config, expanding templates recursively. This method is called internally inside of <code>config.get</code>, but <em>not</em> inside of <code>config.getRaw</code>.</li> </ul> </li> <li><a href="/grunt.event">grunt.event</a> added so that tasks may emit events.</li> <li><a href="/grunt.fail">grunt.fail</a><ul> <li>Won't emit a beep if <code>--no-color</code> option specified.</li> <li>Added <code>fail.code</code> exit code map.</li> <li>Removed <code>fail.warnAlternate</code> method.</li> </ul> </li> <li><a href="/grunt.file">grunt.file</a><ul> <li>Tasks are no longer automatically loaded from <code>~/.grunt/tasks/</code> directory (install them locally to your project!).</li> <li>Added <a href="/grunt.file#wiki-grunt-file-defaultencoding">file.defaultEncoding</a> method for normalizing character encoding across all <code>grunt.file</code> methods.</li> <li>Added <a href="/grunt.file#wiki-grunt-file-delete">file.delete</a> method.</li> <li>Added relatively self-explanatory <a href="/grunt.file#wiki-grunt-file-exists">file.exists</a>, <a href="/grunt.file#wiki-grunt-file-isdir">file.isDir</a>, <a href="/grunt.file#wiki-grunt-file-isfile">file.isFile</a>, <a href="/grunt.file#wiki-grunt-file-islink">file.isLink</a>, <a href="/grunt.file#wiki-grunt-file-ispathcwd">file.isPathCwd</a>, <a href="/grunt.file#wiki-grunt-file-ispathincwd">file.isPathInCwd</a>, <a href="/grunt.file#wiki-grunt-file-doespathcontain">file.doesPathContain</a>, <a href="/grunt.file#wiki-grunt-file-arepathsequivalent">file.arePathsEquivalent</a> testing methods.</li> <li>Added <a href="/grunt.file#wiki-grunt-file-match">file.match</a> and <a href="/grunt.file#wiki-grunt-file-ismatch">file.isMatch</a> methods to facilitate matching wildcard patterns against file paths.</li> <li>Added <a href="/grunt.file#wiki-grunt-file-expandmapping">file.expandMapping</a> method for use in generating 1-to-1 src-dest file mappings.</li> <li>Added <a href="/grunt.file#wiki-grunt-file-readyaml">file.readYAML</a> method.</li> <li>Changed <a href="/grunt.file#wiki-grunt-file-findup">file.findup</a> to use the <a href="https://github.com/cowboy/node-findup-sync">findup-sync</a> module.</li> <li>Changed <a href="/grunt.file#wiki-grunt-file-glob">file.glob</a> to use the <a href="https://github.com/isaacs/node-glob">glob</a> module.</li> <li>Added <a href="/grunt.file#wiki-grunt-file-minimatch">file.minimatch</a> which exposes the <a href="https://github.com/isaacs/minimatch">minimatch</a> module.</li> <li>Removed <code>file.userDir</code> method (moved into <a href="https://github.com/gruntjs/grunt-init">grunt-init</a>).</li> <li>Removed <code>file.clearRequireCache</code> method.</li> <li>Removed <code>file.expandFiles</code> and <code>file.expandDirs</code> methods, use the <code>filter</code> option of <code>file.expand</code> instead.</li> <li>Removed <code>file.expandFileURLs</code> method. Don't specify URLs where files should be specified (eg. the qunit task now allows for a <code>urls</code> option).</li> </ul> </li> <li><a href="/grunt#wiki-grunt-task">grunt.task</a><ul> <li>Tasks registered with both <a href="/grunt.task#wiki-grunt-task-registertask">task.registerTask</a> and <a href="/grunt.task#wiki-grunt-task-registermultitask">task.registerMultiTask</a> get a <code>this.options</code> method.</li> <li>Added <a href="/grunt.task#wiki-grunt-task-normalizemultitaskfiles">task.normalizeMultiTaskFiles</a> method to facilitate the normalization of multi task <code>files</code> objects into the <code>this.file</code> property.</li> <li>Removed <code>task.registerHelper</code> and <code>task.renameHelper</code> methods.</li> <li>Removed <code>task.searchDirs</code> property.</li> <li>Removed <code>task.expand</code> <code>task.expandDirs</code> <code>task.expandFiles</code> <code>task.getFile</code> <code>task.readDefaults</code> methods (moved into <a href="https://github.com/gruntjs/grunt-init">grunt-init</a>).</li> </ul> </li> <li><a href="/grunt#wiki-grunt-package">grunt.package</a> reflects the metadata stored in grunt's <code>package.json</code>.</li> <li><a href="/grunt#wiki-grunt-version">grunt.version</a> is the current version of Grunt as a string.</li> <li><a href="/grunt.template">grunt.template</a><ul> <li>Added <a href="/grunt.template#wiki-grunt-template-adddelimiters">template.addDelimiters</a> method to add new template delimiters.</li> <li>Added <a href="/grunt.template#wiki-grunt-template-setdelimiters">template.setDelimiters</a> method to select template delimiters.</li> <li>The <code>init</code> and <code>user</code> template delimiters have been removed, but you can add them in again if you need to with <code>template.addDelimiters</code> (<a href="https://github.com/gruntjs/grunt-init">grunt-init</a> uses this to enable the <code>{% %}</code> template delimiters).</li> </ul> </li> <li><a href="/grunt.util">grunt.util</a> replaces the now-removed <code>grunt.utils</code>.<ul> <li>Changed <code>util._</code> to use <a href="http://lodash.com/">Lo-Dash</a></li> <li>Added the <a href="/grunt.util#wiki-grunt-util-callbackify">util.callbackify</a> method.</li> <li>Changed the <a href="/grunt.util#wiki-grunt-util-spawn">util.spawn</a> method to be much better behaved and pass more consistent arguments into its callback.</li> </ul> </li> </ul> <h2><a class="anchor" href="#task-plugin-authors" id="task-plugin-authors"></a>Task / plugin authors</h2> <p><strong>Plugin authors, please indicate clearly on your repository README which version number of your Grunt plugin breaks compatibility with Grunt 0.3.</strong></p> <h3><a class="anchor" href="#tasks" id="tasks"></a>Tasks</h3> <ul> <li>Multi tasks<ul> <li>Multiple src-dest file mappings may now be specified per target in a <code>files</code> object (this is optional).</li> </ul> </li> <li><a href="/grunt.task#wiki-this-files">this.files / grunt.task.current.files</a><ul> <li>The <code>this.files</code> property is an array of src-dest file mapping objects to be iterated over in your multi task. It will always be an array, and you should always iterate over it, even if the most common use case is to specify a single file.</li> <li>Each src-dest file mapping object has a <code>src</code> and <code>dest</code> property (and possibly others, depending on what the user specified). The <code>src</code> property is already expanded from whatever glob pattern the user may have specified.</li> </ul> </li> <li><a href="/grunt.task#wiki-this-filessrc">this.filesSrc / grunt.task.current.filesSrc</a><ul> <li>The <code>this.filesSrc</code> property is a reduced, uniqued array of all files matched by all specified <code>src</code> properties. Useful for read-only tasks.</li> </ul> </li> <li><a href="/grunt.task#wiki-this-options">this.options / grunt.task.current.options</a><ul> <li>The <code>this.options</code> method may be used within tasks to normalize options. Inside a task, you may specify options defaults like: <code>var options = this.options({option: 'defaultvalue', ...});</code></li> </ul> </li> </ul> <h3><a class="anchor" href="#plugins" id="plugins"></a>Plugins</h3> <ul> <li>An updated <code>gruntplugin</code> template has been created for Grunt 0.4-compatible plugins, and is available in the standalone <a href="https://github.com/gruntjs/grunt-init">grunt-init</a>.</li> </ul> <h2><a class="anchor" href="#troubleshooting" id="troubleshooting"></a>Troubleshooting</h2> <ul> <li>If you had previously installed a development version of Grunt 0.4 or any grunt-contrib plugins, be sure to flush your npm cache with <code>npm cache clean</code> first to ensure that you are pulling the final version of Grunt and grunt-contrib plugins.</li> </ul> <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 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 class="active" 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>