{"id":23274,"date":"2015-02-10T21:01:50","date_gmt":"2015-02-10T13:01:50","guid":{"rendered":"https:\/\/www.hongkiat.com\/blog\/?p=23274"},"modified":"2024-07-19T02:00:04","modified_gmt":"2024-07-18T18:00:04","slug":"automate-workflow-with-grunt","status":"publish","type":"post","link":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/","title":{"rendered":"Effective Workflow Automation with Grunt [Step-by-Step Guide]"},"content":{"rendered":"<p>I\u2019m a <strong>huge advocate of automation<\/strong> because it simplifies life significantly. Why spend time on repetitive tasks when you can automate them? This is especially true for web development.<\/p>\n<p>Many development tasks can be tedious. While developing, you may want to compile code, concatenate and minify files, remove development-only resources, and so on. Even relatively simple tasks like deleting a bunch of files or renaming folders <strong>can consume a lot of our time.<\/strong><\/p>\n<p>In this article, I\u2019ll show you how to make your life easier by leveraging the excellent functionality offered by <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/gruntjs.com\">Grunt<\/a>, a JavaScript task runner. I\u2019ll guide you through the entire process, so no worries if you\u2019re not a JavaScript expert!<\/p>\n<p><strong>More on Hongkiat.com:<\/strong><\/p>\n<ul>\n<li><a href=\"https:\/\/www.hongkiat.com\/blog\/css-automation-tool-cssmatic\/\">CSSMatic Makes CSS Easy for Web Designers<\/a><\/li>\n<li><a href=\"https:\/\/www.hongkiat.com\/blog\/automate-folder-actions\/\">Automating Tasks on Mac with Folder Actions<\/a><\/li>\n<li><a href=\"https:\/\/www.hongkiat.com\/blog\/automate-dropbox-files-with-actions\/\">Automate Your Dropbox Files with Actions<\/a><\/li>\n<li><a href=\"https:\/\/www.hongkiat.com\/blog\/apps-to-automate-android\/\">10 Apps to Help Automate Tasks on Your Android Device<\/a><\/li>\n<li><a href=\"https:\/\/www.hongkiat.com\/blog\/auto-backup-website-dropbox\/\">How to Automatically Back Up Your Website to Dropbox<\/a><\/li>\n<\/ul>\n<h2>Installing Grunt<\/h2>\n<p>Installing Grunt is straightforward because it uses the Node Package Manager (npm). This means you may also need to install Node.js. Open a terminal or command prompt (referred to as terminal from now on) and enter <code>npm -v<\/code>.<\/p>\n<p>If you see a version number, you have <code>npm<\/code> installed. If you see a \u201ccommand not found\u201d error, you\u2019ll need to install it by visiting the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/nodejs.org\/en\/download\/\">Node.js downloads page<\/a> and selecting the version you need.<\/p>\n<p>Once Node.js is installed, getting Grunt is a matter of a single command issued in the terminal:<\/p>\n<pre>npm install -g grunt-cli<\/pre>\n<h2>Basic Usage<\/h2>\n<p>You\u2019ll use Grunt on a project-to-project basis since each project has different requirements. Let\u2019s start a project by creating a folder and navigating to it via our terminal.<\/p>\n<p>Two files form the core of Grunt: <code>package.json<\/code> and <code>Gruntfile.js<\/code>. The package file defines all the third-party dependencies your automation will use, while the Gruntfile lets you control <em>how<\/em> these are used. Let\u2019s create a basic package file with the following content:<\/p>\n<pre>\r\n{\r\n  \"name\": \"test-project\",\r\n  \"version\": \"1.0\",\r\n  \"devDependencies\": {\r\n    \"grunt\": \"~0.4.5\"\r\n  }\r\n}\r\n<\/pre>\n<p>The name and version are up to you. The dependencies must include all packages you are using. We\u2019re not doing anything complex at the moment, so we\u2019ll just ensure Grunt itself is added as a dependency.<\/p>\n<p>You might be wondering what the tilde (~) is doing there.<\/p>\n<p>Versions can be specified using the rules from <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.npmjs.com\/misc\/semver\">the semantic versioner for npm<\/a>. In short:<\/p>\n<ul>\n<li>Specify an exact version like <code>4.5.2<\/code><\/li>\n<li>Use greater than\/less than to indicate minimum or maximum version, such as <code>>4.0.3<\/code><\/li>\n<li>The tilde specifies a version block. Using <code>~1.2<\/code> means any version above 1.2.0 but below 1.3<\/li>\n<\/ul>\n<p>There are many more ways to specify versions, but this is sufficient for most needs. The next step is to create a Gruntfile that will perform our automations.<\/p>\n<pre>\r\nmodule.exports = function(grunt) {\r\n  grunt.initConfig({\r\n    pkg: grunt.file.readJSON('package.json')\r\n  });\r\n\r\n  grunt.registerTask('default', []);\r\n};\r\n<\/pre>\n<p>This is the basic structure for a Gruntfile. There are two key areas of interest. The first is inside the <code>initConfig()<\/code> function. This is where all your project configuration goes, including tasks like compiling LESS\/SASS, minifying scripts, and more.<\/p>\n<p>The second area is below that function, where you specify tasks. You can see one task named \u201cdefault.\u201d It is currently empty, so it does nothing, but we\u2019ll expand on it later. <strong>Tasks essentially queue up parts of our project configuration and execute them.<\/strong><\/p>\n<p>For example, a task named \u201cscripts\u201d might concatenate all our scripts, minify the resulting file, and then move it to its final location. These actions are defined in the project configuration but are \u201cpulled together\u201d by the task. If this isn\u2019t clear yet, don\u2019t worry, I\u2019ll show you how it\u2019s done.<\/p>\n<h2>Our First Task<\/h2>\n<p>Let\u2019s create a task that minifies a single JavaScript file for us.<\/p>\n<p>There are four steps we need to follow whenever we want to add a new task:<\/p>\n<ul>\n<li>Install a plugin if necessary<\/li>\n<li>Require it in the Gruntfile<\/li>\n<li>Write the task<\/li>\n<li>Add it to a task group if needed<\/li>\n<\/ul>\n<h3>1. Find and Install Plugin<\/h3>\n<p>The easiest way to find the plugin you need is to type something like this into Google: \u201cminify JavaScript Grunt plugin\u201d. The first result should lead you to the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/gruntjs\/grunt-contrib-uglify\">grunt-contrib-uglify<\/a> plugin, which is exactly what we need.<\/p>\n<p>The GitHub page provides all the necessary information. Installation is a single line in the terminal. Here\u2019s what you need to use:<\/p>\n<pre>\r\nnpm install grunt-contrib-uglify --save-dev\r\n<\/pre>\n<p>You may need to run this with admin privileges. If you encounter an error like <code>npm ERR! Please try running this command again as root\/Administrator.<\/code>, just type <code>sudo<\/code> before the command and enter your password when prompted:<\/p>\n<pre>\r\nsudo npm install grunt-contrib-uglify --save-dev\r\n<\/pre>\n<p>This command updates your <code>package.json<\/code> file, adding the plugin as a dependency, so you don\u2019t need to do it manually.<\/p>\n<h3>2. Require in Gruntfile<\/h3>\n<p>The next step is to add the plugin to your Gruntfile as a requirement. I like to add plugins at the top of the file. Here\u2019s my complete Gruntfile after adding <code>grunt.loadNpmTasks('grunt-contrib-uglify');<\/code>:<\/p>\n<pre>\r\nmodule.exports = function(grunt) {\r\n\r\n  grunt.loadNpmTasks('grunt-contrib-uglify');\r\n\r\n  grunt.initConfig({\r\n    pkg: grunt.file.readJSON('package.json')\r\n  });\r\n\r\n  grunt.registerTask('default', []);\r\n};\r\n<\/pre>\n<h3>3. Create a Task for Minifying Scripts<\/h3>\n<p>As we discussed, this should be done within the <code>initConfig()<\/code> function. The GitHub page for the plugin (and most other plugins) provides plenty of information and examples. Here\u2019s what I used in my test project:<\/p>\n<pre>\r\nuglify: {\r\n  build: {\r\n    src: 'js\/scripts.js',\r\n    dest: 'js\/scripts.min.js'\r\n  }\r\n}\r\n<\/pre>\n<p>This is pretty straightforward. I specified the <code>scripts.js<\/code> file in my project\u2019s <code>js<\/code> directory and the destination for the minified file. There are many ways to specify source files; we\u2019ll explore that later.<\/p>\n<p>For now, let\u2019s look at the complete Gruntfile after this addition to ensure you know how everything fits together:<\/p>\n<pre>\r\nmodule.exports = function(grunt) {\r\n\r\n  grunt.loadNpmTasks('grunt-contrib-uglify');\r\n\r\n  grunt.initConfig({\r\n    pkg: grunt.file.readJSON('package.json'),\r\n\r\n    uglify: {\r\n      build: {\r\n        src: 'scripts.js',\r\n        dest: 'scripts.min.js'\r\n      }\r\n    }\r\n  });\r\n\r\n  grunt.registerTask('default', []);\r\n};\r\n<\/pre>\n<h3>4. Add This Configuration to a Task Group<\/h3>\n<p>Right now, you could go to your terminal and type <code>grunt uglify<\/code>, but we\u2019ll need task groups to run multiple tasks later on. We have the default task empty, just waiting for something to be added, so let\u2019s modify it to the following:<\/p>\n<pre>\r\ngrunt.registerTask('default', ['uglify']);\r\n<\/pre>\n<p>At this stage, you should be able to go to the terminal, type <code>grunt<\/code>, and see the minification take place. Don\u2019t forget to create a <code>scripts.js<\/code> file, of course!<\/p>\n<p>That didn\u2019t take much time to set up, did it? Even if you\u2019re new to all this and it took you some time to work through the steps, the time saved will surpass the time spent on it within a few uses.<\/p>\n<h2>Concatenating Files<\/h2>\n<p>Let\u2019s look at concatenating files and <strong>learn how to specify multiple files as a target<\/strong> along the way.<\/p>\n<p>Concatenation is the process of combining the contents of multiple files into a single file. We\u2019ll need the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/gruntjs\/grunt-contrib-concat\">grunt-contrib-concat<\/a> plugin. Let\u2019s work through the steps:<\/p>\n<p>To install the plugin, use <code>npm install grunt-contrib-concat --save-dev<\/code> in the terminal. Once done, make sure to add it to your Gruntfile just like before using <code>grunt.loadNpmTasks('grunt-contrib-concat');<\/code>.<\/p>\n<p>Next up is the configuration. Let\u2019s combine three specific files. The syntax will be familiar:<\/p>\n<pre>\r\nconcat: {\r\n  dist: {\r\n    src: ['dev\/js\/header.js', 'dev\/js\/myplugin.js', 'dev\/js\/footer.js'],\r\n    dest: 'js\/scripts.js'\r\n  }\r\n}\r\n<\/pre>\n<p>The code above takes the three files given as the source and combines them into the file given as the destination.<\/p>\n<p>This is already pretty powerful, but what if a new file is added? Do we need to come back here every time? Of course not, we can specify a whole folder of files to concatenate:<\/p>\n<pre>\r\nconcat: {\r\n  dist: {\r\n    src: ['dev\/js\/*.js'],\r\n    dest: 'js\/scripts.js'\r\n  }\r\n}\r\n<\/pre>\n<p>Now, any JavaScript file within the <code>dev\/js<\/code> folder will be merged into one big file: <code>js\/scripts.js<\/code>. Much better!<\/p>\n<p>Now it\u2019s time to create a task so we can actually concatenate some files:<\/p>\n<pre>\r\ngrunt.registerTask('mergejs', ['concat']);\r\n<\/pre>\n<p>This is not the default task anymore, so we\u2019ll need to type its name in the terminal when we issue the <code>grunt<\/code> command:<\/p>\n<pre>\r\ngrunt mergejs\r\n<\/pre>\n<h2>Automating Our Automation<\/h2>\n<p>We\u2019ve already made a lot of progress, but there\u2019s more! Right now, when you want to concatenate or minify, you need to go to the terminal and type the appropriate command. It\u2019s time to look at the <code>watch<\/code> command, which will do this for us automatically. We\u2019ll also learn how to execute multiple tasks at once.<\/p>\n<p>To get started, we\u2019ll need to grab <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/gruntjs\/grunt-contrib-watch\">grunt-contrib-watch<\/a>. I\u2019m sure you can install it and add it to the Gruntfile on your own by now, so I\u2019ll start by showing you what I use in my test project:<\/p>\n<pre>\r\nwatch: {\r\n  scripts: {\r\n    files: ['dev\/js\/*.js'],\r\n    tasks: ['concat', 'uglify']\r\n  }\r\n}\r\n<\/pre>\n<p>I named a set of files to watch \u201cscripts\u201d for clarity. Within this object, I have specified the files to watch and the tasks to run. In the previous concatenation example, we combined all the files in the <code>dev\/js<\/code> directory.<\/p>\n<p>In the minification example, we minified this file. It makes sense to watch the <code>dev\/js<\/code> folder for changes and run these tasks whenever there are any.<\/p>\n<p>As you can see, multiple tasks can be called easily by listing them in an array. They will be performed in sequence, first the concatenation, then the minification in this case. This can also be done with task groups, which is the main reason they exist.<\/p>\n<p>We can now modify our default task:<\/p>\n<pre>\r\ngrunt.registerTask('default', ['concat', 'uglify']);\r\n<\/pre>\n<p>Now we have two choices. Whenever you want to concatenate and minify your scripts, you can switch to the terminal and type <code>grunt<\/code>. You can also use the watch command to initiate the watching of your files: <code>grunt watch<\/code>.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/assets.hongkiat.com\/uploads\/automate-workflow-with-grunt\/watch.jpg\" alt=\"Grunt Watch Command\" width=\"30%\"><\/figure>\n<p>It will sit there, waiting for you to modify these files. Once you do, it will perform all the tasks assigned to it. Go ahead, give it a try.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/assets.hongkiat.com\/uploads\/automate-workflow-with-grunt\/watch-result.jpg\" alt=\"Grunt Watch Result\" width=\"100%\"><\/figure>\n<p>That\u2019s much better, no input needed from us. You can now work with your files, and everything will be nicely done for you.<\/p>\n<h2>Overview<\/h2>\n<p>With this basic knowledge of how plugins can be installed and used and how the watch command works, you are all set to become an automation enthusiast. There is a lot more to Grunt than what we discussed, but nothing you can\u2019t handle on your own.<\/p>\n<p>Using commands for <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/gruntjs\/grunt-contrib-sass\">compiling SASS<\/a>, <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/gruntjs\/grunt-contrib-imagemin\">optimizing images<\/a>, <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/nDmitry\/grunt-autoprefixer\">autoprefixing<\/a>, and more is just a matter of following the steps we discussed and reading the syntax the plugin requires.<\/p>\n<p>If you know of some particularly great uses for Grunt, please let us know in the comments. We\u2019re always interested to hear how you use tools like Grunt!<\/p>","protected":false},"excerpt":{"rendered":"<p>I\u2019m a huge advocate of automation because it simplifies life significantly. Why spend time on repetitive tasks when you can automate them? This is especially true for web development. Many development tasks can be tedious. While developing, you may want to compile code, concatenate and minify files, remove development-only resources, and so on. Even relatively&hellip;<\/p>\n","protected":false},"author":143,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3393,352],"tags":[2695,4117],"topic":[4520],"class_list":["entry-content","is-maxi"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v22.8 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Effective Workflow Automation with Grunt [Step-by-Step Guide] - Hongkiat<\/title>\n<meta name=\"description\" content=\"I&#039;m a huge advocate of automation because it simplifies life significantly. Why spend time on repetitive tasks when you can automate them? This is\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Effective Workflow Automation with Grunt [Step-by-Step Guide]\" \/>\n<meta property=\"og:description\" content=\"I&#039;m a huge advocate of automation because it simplifies life significantly. Why spend time on repetitive tasks when you can automate them? This is\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/\" \/>\n<meta property=\"og:site_name\" content=\"Hongkiat\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/hongkiatcom\" \/>\n<meta property=\"article:published_time\" content=\"2015-02-10T13:01:50+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-07-18T18:00:04+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/assets.hongkiat.com\/uploads\/automate-workflow-with-grunt\/watch.jpg\" \/>\n<meta name=\"author\" content=\"Daniel Pataki\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hongkiat\" \/>\n<meta name=\"twitter:site\" content=\"@hongkiat\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Daniel Pataki\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/\"},\"author\":{\"name\":\"Daniel Pataki\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#\\\/schema\\\/person\\\/76d3b3baacd688e9a0d7bd24553519bc\"},\"headline\":\"Effective Workflow Automation with Grunt [Step-by-Step Guide]\",\"datePublished\":\"2015-02-10T13:01:50+00:00\",\"dateModified\":\"2024-07-18T18:00:04+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/\"},\"wordCount\":1572,\"commentCount\":20,\"publisher\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/assets.hongkiat.com\\\/uploads\\\/automate-workflow-with-grunt\\\/watch.jpg\",\"keywords\":[\"Grunt\",\"Javascripts\"],\"articleSection\":[\"Toolkit\",\"Web Design\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/\",\"url\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/\",\"name\":\"Effective Workflow Automation with Grunt [Step-by-Step Guide] - Hongkiat\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/assets.hongkiat.com\\\/uploads\\\/automate-workflow-with-grunt\\\/watch.jpg\",\"datePublished\":\"2015-02-10T13:01:50+00:00\",\"dateModified\":\"2024-07-18T18:00:04+00:00\",\"description\":\"I'm a huge advocate of automation because it simplifies life significantly. Why spend time on repetitive tasks when you can automate them? This is\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/#primaryimage\",\"url\":\"https:\\\/\\\/assets.hongkiat.com\\\/uploads\\\/automate-workflow-with-grunt\\\/watch.jpg\",\"contentUrl\":\"https:\\\/\\\/assets.hongkiat.com\\\/uploads\\\/automate-workflow-with-grunt\\\/watch.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/automate-workflow-with-grunt\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Effective Workflow Automation with Grunt [Step-by-Step Guide]\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/\",\"name\":\"Hongkiat\",\"description\":\"Tech and Design Tips\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#organization\",\"name\":\"Hongkiat.com\",\"url\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/wp-content\\\/uploads\\\/hkdc-logo-rect-yoast.jpg\",\"contentUrl\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/wp-content\\\/uploads\\\/hkdc-logo-rect-yoast.jpg\",\"width\":1200,\"height\":799,\"caption\":\"Hongkiat.com\"},\"image\":{\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/hongkiatcom\",\"https:\\\/\\\/x.com\\\/hongkiat\",\"https:\\\/\\\/www.pinterest.com\\\/hongkiat\\\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/#\\\/schema\\\/person\\\/76d3b3baacd688e9a0d7bd24553519bc\",\"name\":\"Daniel Pataki\",\"description\":\"Daniel is a writer for Hongkiat.com. When not coding or writing, you'll find him playing board games or running with his dog. You can drop him a line on Twitter or visit his personal website.\",\"sameAs\":[\"http:\\\/\\\/danielpataki.com\\\/\"],\"url\":\"https:\\\/\\\/www.hongkiat.com\\\/blog\\\/author\\\/danielpataki\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Effective Workflow Automation with Grunt [Step-by-Step Guide] - Hongkiat","description":"I'm a huge advocate of automation because it simplifies life significantly. Why spend time on repetitive tasks when you can automate them? This is","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/","og_locale":"en_US","og_type":"article","og_title":"Effective Workflow Automation with Grunt [Step-by-Step Guide]","og_description":"I'm a huge advocate of automation because it simplifies life significantly. Why spend time on repetitive tasks when you can automate them? This is","og_url":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/","og_site_name":"Hongkiat","article_publisher":"https:\/\/www.facebook.com\/hongkiatcom","article_published_time":"2015-02-10T13:01:50+00:00","article_modified_time":"2024-07-18T18:00:04+00:00","og_image":[{"url":"https:\/\/assets.hongkiat.com\/uploads\/automate-workflow-with-grunt\/watch.jpg","type":"","width":"","height":""}],"author":"Daniel Pataki","twitter_card":"summary_large_image","twitter_creator":"@hongkiat","twitter_site":"@hongkiat","twitter_misc":{"Written by":"Daniel Pataki","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/#article","isPartOf":{"@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/"},"author":{"name":"Daniel Pataki","@id":"https:\/\/www.hongkiat.com\/blog\/#\/schema\/person\/76d3b3baacd688e9a0d7bd24553519bc"},"headline":"Effective Workflow Automation with Grunt [Step-by-Step Guide]","datePublished":"2015-02-10T13:01:50+00:00","dateModified":"2024-07-18T18:00:04+00:00","mainEntityOfPage":{"@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/"},"wordCount":1572,"commentCount":20,"publisher":{"@id":"https:\/\/www.hongkiat.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/#primaryimage"},"thumbnailUrl":"https:\/\/assets.hongkiat.com\/uploads\/automate-workflow-with-grunt\/watch.jpg","keywords":["Grunt","Javascripts"],"articleSection":["Toolkit","Web Design"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/","url":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/","name":"Effective Workflow Automation with Grunt [Step-by-Step Guide] - Hongkiat","isPartOf":{"@id":"https:\/\/www.hongkiat.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/#primaryimage"},"image":{"@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/#primaryimage"},"thumbnailUrl":"https:\/\/assets.hongkiat.com\/uploads\/automate-workflow-with-grunt\/watch.jpg","datePublished":"2015-02-10T13:01:50+00:00","dateModified":"2024-07-18T18:00:04+00:00","description":"I'm a huge advocate of automation because it simplifies life significantly. Why spend time on repetitive tasks when you can automate them? This is","breadcrumb":{"@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/#primaryimage","url":"https:\/\/assets.hongkiat.com\/uploads\/automate-workflow-with-grunt\/watch.jpg","contentUrl":"https:\/\/assets.hongkiat.com\/uploads\/automate-workflow-with-grunt\/watch.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/www.hongkiat.com\/blog\/automate-workflow-with-grunt\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.hongkiat.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Effective Workflow Automation with Grunt [Step-by-Step Guide]"}]},{"@type":"WebSite","@id":"https:\/\/www.hongkiat.com\/blog\/#website","url":"https:\/\/www.hongkiat.com\/blog\/","name":"Hongkiat","description":"Tech and Design Tips","publisher":{"@id":"https:\/\/www.hongkiat.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.hongkiat.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.hongkiat.com\/blog\/#organization","name":"Hongkiat.com","url":"https:\/\/www.hongkiat.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.hongkiat.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.hongkiat.com\/blog\/wp-content\/uploads\/hkdc-logo-rect-yoast.jpg","contentUrl":"https:\/\/www.hongkiat.com\/blog\/wp-content\/uploads\/hkdc-logo-rect-yoast.jpg","width":1200,"height":799,"caption":"Hongkiat.com"},"image":{"@id":"https:\/\/www.hongkiat.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/hongkiatcom","https:\/\/x.com\/hongkiat","https:\/\/www.pinterest.com\/hongkiat\/"]},{"@type":"Person","@id":"https:\/\/www.hongkiat.com\/blog\/#\/schema\/person\/76d3b3baacd688e9a0d7bd24553519bc","name":"Daniel Pataki","description":"Daniel is a writer for Hongkiat.com. When not coding or writing, you'll find him playing board games or running with his dog. You can drop him a line on Twitter or visit his personal website.","sameAs":["http:\/\/danielpataki.com\/"],"url":"https:\/\/www.hongkiat.com\/blog\/author\/danielpataki\/"}]}},"jetpack_featured_media_url":"https:\/\/","jetpack_shortlink":"https:\/\/wp.me\/p4uxU-63o","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/posts\/23274","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/users\/143"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/comments?post=23274"}],"version-history":[{"count":3,"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/posts\/23274\/revisions"}],"predecessor-version":[{"id":72316,"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/posts\/23274\/revisions\/72316"}],"wp:attachment":[{"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/media?parent=23274"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/categories?post=23274"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/tags?post=23274"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.hongkiat.com\/blog\/wp-json\/wp\/v2\/topic?post=23274"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}