Search code examples
javascriptangularjsgruntjsgrunt-contrib-concat

Most efficient way to Grunt concat directories files?


I apologize for the very awkward question title, if anyone can think of a better way to phrase this question I'll change it immediately.

I'm building an app with Angular and RequireJS and to try to optimize performance, dependencies and lazy-loading I'm looking to build a file structure like this:

/app
----/regisitration
--------_registration.module.js
--------registration.ctrl.js
--------registration.svc.js
--------registration.directive.js
----/courses
--------_courses.module.js
--------courses.directive.js
--------courses.controller.js
--------courses.service.js
--------/course
------------course.controller.js
----/admin
--------_admin.module.js
--------admin.controller.js

Where I set up my routing, I want to be able to have a user who goes to any /registration/ view load the entirety of _registration.module.js which would be the concatenation of all the other .js files within the /registraion directory (and any sub directories) so that my team isn't bogged down by needing to include several and possibly duplicate dependencies as well as serve the entirety of the site "section" to the user in one shot. Hopefully the sample above shows why I wouldn't want to just front-load all the files, because most users will never hit the admin section of the site. I'm trying to figure out the most efficient way to achieve this with grunt, but so far I'm working very manually with code like this:

grunt.initConfig({
  concat: {
    app: {
      files: [
        {
            src: ['..app/registration/*.js', '!..app/registraion/*.module.js'], 
            dest: '..app/registration/_registration.module.js'
        },
        {
            src: ['..app/courses/*.js', '!..app/courses/*.module.js'], 
            dest: '..app/courses/_courses.module.js'
        },
        {
            src: ['..app/admin/*.js', '!..app/admin/*.module.js'], 
            dest: '..app/admin/_admin.module.js'
        }
      ],
    }
  },
});

I think there must be a more efficient and less manual way to do what I'm trying to achieve. Does anyone have any suggestions?


Solution

  • Remember that you can still execute JavaScript within your Gruntfile.

    grunt.initConfig({
      concat: {
        app: {
          files: grunt.file.expand({ cwd: 'app', filter: 'isDirectory' }, '*')
          .map(function(ngModule) {
            return { 
              src: ['app/' + ngModule + '/*.js', '!app/' + ngModule + '/*.module.js'],
              dest: 'app/' + ngModule + '/_' + ngModule + '.module.js'
            };
          })
        }
      },
    });
    

    With this, you should be able to create new modules without needing to remember to update a config entry for them.