{"id":1128,"date":"2014-10-22T15:15:53","date_gmt":"2014-10-22T12:15:53","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=1128"},"modified":"2014-10-22T15:09:53","modified_gmt":"2014-10-22T12:09:53","slug":"multi-module-javascript-project-with-grunt","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/","title":{"rendered":"Multi module JavaScript project with Grunt"},"content":{"rendered":"<p>Writing blog post how I managed to configure multi module JavaScript project with <strong>Grunt <\/strong>for my spare time project. It is using <strong>Protractor<\/strong> for end-to-end testing, but I believe that this multi module approach would be easily portable onto <strong>non-Angular<\/strong> <strong>stack<\/strong>.<\/p>\n<p>In my spare time I work on pet project based on EAN stack (Express, Angular, Node.JS). (Project doesn\u2019t need DB, that\u2019s why MongoDB is missing from famous MEAN stack). Initial draft of the project was scaffolded by <strong>Yeoman<\/strong> with usage of <a title=\"angular-fullstack\" href=\"https:\/\/github.com\/DaftMonk\/generator-angular-fullstack\" target=\"_blank\">angular-fullstack<\/a> generator. Build is based on <strong>Grunt. <\/strong>Apart from that generator was using <strong>Grunt<\/strong>, I chose it<strong> over Gulp<\/strong>, because it would be probably more mature. Also <strong>Grunt vs Gulp<\/strong> battle seem to me similar as <strong>Maven vs Gradle<\/strong> one in Java world. I never had a need to move away from <strong>Maven. <\/strong>Also don\u2019t like idea of creating\u00a0 some custom algorithms in build system (bad Bash and Ant experience in the past). <strong>Grunt<\/strong> is similar to <strong>Maven<\/strong> in terms of configuration approach. I can very easily understand any build in <strong>Maven<\/strong> and expect similar build consistency from <strong>Grunt<\/strong>.<\/p>\n<p>Nearly immediately I started to feel that <strong>Node.JS<\/strong> and <strong>Express<\/strong> back-end build concerns (<strong>Mocha<\/strong> based test suite) are pretty different to concerns of <strong>Angular<\/strong> front-end build (minification, <strong>Require.js<\/strong> optimalization, <strong>Karma<\/strong> based test suite, \u2026). There was clear distinction between these two.<\/p>\n<p>My main problem was having separate test suites. <strong>Karma<\/strong> makes generation of unit test code coverage very easy. Slightly tricky was setting up generation of code coverage stats for <strong>Mocha<\/strong> based server unit test suite. I managed to do that with <strong>Instanbul<\/strong>. So far so good. But when I wanted to send my stats to <a title=\"Coveralls\" href=\"https:\/\/coveralls.io\/\" target=\"_blank\">Coveralls<\/a> server I could do that only for one suite. Coveralls support one stat per project. Combining stat files didn\u2019t work nicely for me.<\/p>\n<h2>Multi module JavaScript project<\/h2>\n<p>So I felt a need for splitting the projects. As I\u2019m developer with Java background, this situation reminded me <strong>Maven multi module project<\/strong>. In this concept you can have various separated projects\/sub-modules that can evolve independently. These can be grouped\/integrated together via special multi module project. This way you can build large enterprise and also modular application.<\/p>\n<p>So I said to myself, that I wouldn\u2019t give a try to this stack until I figure out how to configure multi module project. I separated main repository called <strong>primediser<\/strong> into two:<\/p>\n<ul>\n<li><a title=\"primediser-server-blog-2014-05-19-multi-module-project\" href=\"https:\/\/github.com\/lkrnac\/primediser-server\/tree\/blog-2014-05-19-multi-module-project\" target=\"_blank\">primediser-server<\/a><\/li>\n<li><a title=\"primediser-client-blog-2014-05-19-multi-module-project\" href=\"https:\/\/github.com\/lkrnac\/primediser-client\/tree\/blog-2014-05-19-multi-module-project\" target=\"_blank\">primediser-client<\/a><\/li>\n<\/ul>\n<p>(Notice I created branch <strong>blog-2014-05-19-multi-module-project <\/strong>to to have code consistent with blog post)<\/p>\n<p>So now I am able to set up Continuous Integration for each project and submit coverage stats separately. But how to integrate these two together? I created umbrella project, that doesn\u2019t contain any JavaScript production code (similar to multi module project in Maven world). It will contain only <strong>Protractor<\/strong> E2E tests and grunt file for integration two modules.\u00a0 This project is located in separate Github repository called <a title=\"primediser-blog-2014-05-19-multi-module-project\" href=\"https:\/\/github.com\/lkrnac\/primediser\/tree\/blog-2014-05-19-multi-module-project\" target=\"_blank\">primediser.<\/a><\/p>\n<p>It uses various <strong>Grunt plugins<\/strong> and one conditional trick to do the integration:<\/p>\n<h2>grunt-git<\/h2>\n<p>This plugin is used to clone mentioned sub-projects from Github:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">gitclone: {\r\n      cloneServer: {\r\n        options: {\r\n          repository: 'https:\/\/github.com\/lkrnac\/&lt;%= dirs.server %&gt;',\r\n          directory: '&lt;%= dirs.server %&gt;'\r\n        },\r\n      },\r\n      cloneClient: {\r\n        options: {\r\n          repository: 'https:\/\/github.com\/lkrnac\/&lt;%= dirs.client %&gt;',\r\n          directory: '&lt;%= dirs.client %&gt;'\r\n        },\r\n      },\r\n    },<\/pre>\n<p>I could use grunt-shell plugin for this (I am using it anyway if you read further), but this one seems to be platform independent. Grunt-shell obviously isn\u2019t.<\/p>\n<h2>Conditional cloning<\/h2>\n<p>Git can clone repository only once. Second attempt fails. Therefore we need to clone sub-projects only when they don\u2019t exist. It is obviously up to developer to<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">var cloneIfMissing = function (subTask) {\r\n    var directory = grunt.config.get('gitclone')&#x5B;subTask].options.directory;\r\n    var exists = fs.existsSync(directory);\r\n    if (!exists) {\r\n      grunt.task.run('gitclone:' + subTask);\r\n    }\r\n  };\r\n\r\n  grunt.registerTask('cloneSubprojects', function () {\r\n    cloneIfMissing('cloneClient');\r\n    cloneIfMissing('cloneServer');\r\n  });<\/pre>\n<p>My setup expects that developer would update sub-projects as needed. Also expects that Continuous Integration system that throws away entire workspace after the build. If you would be using <strong>Jenkins<\/strong>, you could use similar conditional trick in conjunction with gitupdate maven task that <strong>grunt-git<\/strong> provides.<\/p>\n<h2>grunt-shell<\/h2>\n<p>After cloning, we need to install dependencies for both sub-projects. Unfortunately I didn\u2019t find any platform independent way of doing this (Have to be honest I didn\u2019t look very deeply though).<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">  shell: {\r\n      npmInstallServer: {\r\n        options: {\r\n          stdout: true,\r\n          stderr: true\r\n        },\r\n        command: 'cd &lt;%= dirs.server %&gt; &amp;&amp; npm install &amp;&amp; cd ..'\r\n      },\r\n      npmInstallClient: {\r\n        options: {\r\n          stdout: true,\r\n          stderr: true\r\n        },\r\n        command: 'cd &lt;%= dirs.client %&gt; &amp;&amp; npm install &amp;&amp; bower install &amp;&amp; cd ..'\r\n      }\r\n    },<\/pre>\n<h2>grunt-hub<\/h2>\n<p>Next step is to kick off builds of sub-projects via <strong>grunt-hub<\/strong> plugin:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">hub: {\r\n      client: {\r\n        src: &#x5B;'&lt;%= dirs.client %&gt;\/Gruntfile.js'],\r\n        tasks: &#x5B;'build'],\r\n      },\r\n      server: {\r\n        src: &#x5B;'&lt;%= dirs.server %&gt;\/Gruntfile.js'],\r\n        tasks: &#x5B;'build'],\r\n      },\r\n    },<\/pre>\n<h2>Tasks configurations<\/h2>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">grunt.registerTask('npmInstallSubprojects', &#x5B;\r\n    'shell:npmInstallServer',\r\n    'shell:npmInstallClient'\r\n  ]);\r\n\r\n  grunt.registerTask('buildSubprojects', &#x5B;\r\n    'hub:server',\r\n    'hub:client'\r\n  ]);\r\n\r\n  grunt.registerTask('coverage', &#x5B;\r\n    'clean:coverageE2E',\r\n    'copy:coverageStatic',\r\n    'instrument',\r\n    'copy:coverageJsServer',\r\n    'copy:coverageJsClient',\r\n    'express:coverageE2E',\r\n    'protractor_coverage:chrome',\r\n    'makeReport',\r\n    'express:coverageE2E:stop'\r\n  ]);\r\n\r\n  grunt.registerTask('default', &#x5B;\r\n    'cloneSubprojects',\r\n    'npmInstallSubprojects',\r\n    'buildSubprojects',\r\n    \/\/'build',\r\n    'coverage'\r\n  ]);<\/pre>\n<p>As you can see there is one task I didn\u2019t mention called\u00a0<strong>coverage: <\/strong><\/p>\n<ul>\n<li>This one gatheres builds of sub-projects into dedicated sub-direcotory<\/li>\n<li>Instrument the files<\/li>\n<li>Run the <strong>Express<\/strong> back-end<\/li>\n<li>Kicks <strong>Protractor<\/strong> end to end tests<\/li>\n<li>and measures front end test coverage<\/li>\n<\/ul>\n<p>Main driver in this task is <a title=\"grunt-protractor-coverage\" href=\"https:\/\/github.com\/r3b\/grunt-protractor-coverage\" target=\"_blank\"><strong>grunt-protractor-coverage<\/strong><\/a> plugin. <a title=\"Measuring code coverage by Protractor end-to-end tests\" href=\"http:\/\/lkrnac.net\/blog\/2014\/04\/measuring-code-coverage-by-protractor\/\" target=\"_blank\">I already wrote blog post about this plugin.<\/a> That blog post was done at stage when there wasn\u2019t multi module configuration in place, so you can expect differences (There is also branch dedicated for that blog post also). Backbone should be the same though.<\/p>\n<p>Maybe you are asking now: What\u2019s Continuous Integration story? It is very nice and include <strong>drone.io<\/strong> and <strong>Sauce Labs<\/strong>. <a title=\"JavaScript multi module project \u2013 Continous Integration\" href=\"http:\/\/lkrnac.net\/blog\/2014\/05\/ci-for-javascript-multi-module-project\/\" target=\"_blank\">But this is topic for another blog post<\/a>.<\/p>\n<p>That is pretty much it. If you have any suggestions how can I enhance\/simplify this build process, please let me know. I would also love to hear if similar stuff is easily doable in <strong>Gulp<\/strong>.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/lkrnac.net\/blog\/2014\/05\/multi-module-javascript-project\/\">Multi module JavaScript project with Grunt<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/wcg\/\">WCG partner<\/a> Lubos Krnac at the <a href=\"http:\/\/lkrnac.net\/blog\/\">Lubos Krnac Java blog<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Writing blog post how I managed to configure multi module JavaScript project with Grunt for my spare time project. It is using Protractor for end-to-end testing, but I believe that this multi module approach would be easily portable onto non-Angular stack. In my spare time I work on pet project based on EAN stack (Express, &hellip;<\/p>\n","protected":false},"author":19,"featured_media":912,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[45],"class_list":["post-1128","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript","tag-grunt"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Multi module JavaScript project with Grunt - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Writing blog post how I managed to configure multi module JavaScript project with Grunt for my spare time project. It is using Protractor for end-to-end\" \/>\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.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Multi module JavaScript project with Grunt - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Writing blog post how I managed to configure multi module JavaScript project with Grunt for my spare time project. It is using Protractor for end-to-end\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2014-10-22T12:15:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Lubos Krnac\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/luboskrnac\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lubos Krnac\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/\"},\"author\":{\"name\":\"Lubos Krnac\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/b97949165d80813cf674daef2917541e\"},\"headline\":\"Multi module JavaScript project with Grunt\",\"datePublished\":\"2014-10-22T12:15:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/\"},\"wordCount\":1040,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg\",\"keywords\":[\"Grunt\"],\"articleSection\":[\"JavaScript\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/\",\"name\":\"Multi module JavaScript project with Grunt - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg\",\"datePublished\":\"2014-10-22T12:15:53+00:00\",\"description\":\"Writing blog post how I managed to configure multi module JavaScript project with Grunt for my spare time project. It is using Protractor for end-to-end\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JavaScript\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Multi module JavaScript project with Grunt\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/b97949165d80813cf674daef2917541e\",\"name\":\"Lubos Krnac\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/de54fe70007a5ff7a805ec6c874812ec129162cb080f66e7a14a05df13da44d1?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/de54fe70007a5ff7a805ec6c874812ec129162cb080f66e7a14a05df13da44d1?s=96&d=mm&r=g\",\"caption\":\"Lubos Krnac\"},\"description\":\"Lubos is a Java\/JavaScript developer\/Tech Lead and Automation enthusiast. His religion is to constantly improve his developments skills and learn new approaches. He believes TDD drives better design and nicely decoupled code. Past experience includes C++, Assembler and C#.\",\"sameAs\":[\"http:\/\/lkrnac.net\/blog\/\",\"http:\/\/www.linkedin.com\/pub\/lubos-krnac\/27\/21a\/b2\",\"https:\/\/x.com\/https:\/\/twitter.com\/luboskrnac\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/lubos-krnac\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Multi module JavaScript project with Grunt - Web Code Geeks - 2026","description":"Writing blog post how I managed to configure multi module JavaScript project with Grunt for my spare time project. It is using Protractor for end-to-end","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.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/","og_locale":"en_US","og_type":"article","og_title":"Multi module JavaScript project with Grunt - Web Code Geeks - 2026","og_description":"Writing blog post how I managed to configure multi module JavaScript project with Grunt for my spare time project. It is using Protractor for end-to-end","og_url":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2014-10-22T12:15:53+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg","type":"image\/jpeg"}],"author":"Lubos Krnac","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/luboskrnac","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Lubos Krnac","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/"},"author":{"name":"Lubos Krnac","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/b97949165d80813cf674daef2917541e"},"headline":"Multi module JavaScript project with Grunt","datePublished":"2014-10-22T12:15:53+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/"},"wordCount":1040,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg","keywords":["Grunt"],"articleSection":["JavaScript"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/","url":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/","name":"Multi module JavaScript project with Grunt - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg","datePublished":"2014-10-22T12:15:53+00:00","description":"Writing blog post how I managed to configure multi module JavaScript project with Grunt for my spare time project. It is using Protractor for end-to-end","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/gruntjs-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/javascript\/multi-module-javascript-project-with-grunt\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"JavaScript","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/"},{"@type":"ListItem","position":3,"name":"Multi module JavaScript project with Grunt"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/b97949165d80813cf674daef2917541e","name":"Lubos Krnac","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/de54fe70007a5ff7a805ec6c874812ec129162cb080f66e7a14a05df13da44d1?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/de54fe70007a5ff7a805ec6c874812ec129162cb080f66e7a14a05df13da44d1?s=96&d=mm&r=g","caption":"Lubos Krnac"},"description":"Lubos is a Java\/JavaScript developer\/Tech Lead and Automation enthusiast. His religion is to constantly improve his developments skills and learn new approaches. He believes TDD drives better design and nicely decoupled code. Past experience includes C++, Assembler and C#.","sameAs":["http:\/\/lkrnac.net\/blog\/","http:\/\/www.linkedin.com\/pub\/lubos-krnac\/27\/21a\/b2","https:\/\/x.com\/https:\/\/twitter.com\/luboskrnac"],"url":"https:\/\/www.webcodegeeks.com\/author\/lubos-krnac\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/1128","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=1128"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/1128\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/912"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=1128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=1128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=1128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}