Grunt: Access Sequence/list Data From External Yaml File
Solution 1:
Below are a couple of solutions to consider. However, firstly let's understand what using grunt.file.readYAML() to parse your _config.yml file does. It essentially produces the following object:
{
  computer: {
    parts: [
      {
        name: 'brand1',
        type: 'cpu'
      },
      {
        name: 'brand2',
        type: 'gpu'
      },
      {
        name: 'brand3',
        type: 'hd'
      }
    ]
  }
}
Note how the value of parts is an array of objects.
Solution 1:
Given that you want to utilize grunt templates (i.e. <%= %>) to obtain the different name and type values, consider configuring your concat task in your Gruntfile.js as follows:
Gruntfile.js
module.exports = function (grunt) {
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.initConfig({
    external: grunt.file.readYAML('_config.yml'),
    concat: {
      dist: {
        options: {
          // ...
        },
        src: [
          'htdocs/<%= external.computer.parts[0].type %>/<%= external.computer.parts[0].name %>/*.js',
          'htdocs/<%= external.computer.parts[1].type %>/<%= external.computer.parts[1].name %>/*.js',
          'htdocs/<%= external.computer.parts[2].type %>/<%= external.computer.parts[2].name %>/*.js'
        ],
        dest: 'htdocs/output.js'
      }
    }
    // ...
  });
  grunt.registerTask('default', [ 'concat' ]);
};
Notes:
The value of the
externalproperty of the object passed into thegrunt.initConfigmethod is essentially the aforementioned object, i.e. it's the result of utiizinggrunt.file.readYAML()to parse your_config.yml.The value of the
srcproperty of thedisttarget, (which is associated with theconcattask), is an array. Each item of this array is where we utilize the<% ... %>notation to reference the parts from your.ymlfile.Note how we reference each object in the
external.computer.partsarray by it's index, i.e.[0],[1],[2]'htdocs/<%= external.computer.parts[0].type %>/<%= external.computer.parts[0].name %>/*.js' ^ ^
Solution 2:
Another way to achieve your requirement is to not utilize grunt templates, i.e. <% ... %>, at all. Consider the following solution:
Gruntfile.js
module.exports = function (grunt) {
  grunt.loadNpmTasks('grunt-contrib-concat');
  var external = grunt.file.readYAML('_config.yml');
  grunt.initConfig({
    concat: {
      dist: {
        options: {
          // ...
        },
        src: external.computer.parts.map(function(part) {
          return'htdocs/' + part.type + '/' + part.name + '/*.js'
        }),
        dest: 'htdocs/output.js'
      }
    }
    // ...
  });
  grunt.registerTask('default', [ 'concat' ]);
};
Notes:
This time we assign the result of parsing your
_config.ymlfile to a variable namedexternal:var external = grunt.file.readYAML('_config.yml');The value of the
srcproperty is computed by utilizing themap()method. Here we create a new array of glob patterns.src: external.computer.parts.map(function(part) { return'htdocs/' + part.type + '/' + part.name + '/*.js' }),
Benefits:
One of the key benefits that Solution 2 has over Solution 1 is:
If we need to add a new part (name and tyoe) to _config.yml. For example:
computer:parts:-name:brand1type:cpu-name:brand2type:gpu-name:brand3type:hd-name:brand4<-------type:foo<-------With Solution 1 we will need to add it to the src configuration in the Gruntfile.js. For example:
src: [
  'htdocs/<%= external.computer.parts[0].type %>/<%= external.computer.parts[0].name %>/*.js',
  'htdocs/<%= external.computer.parts[1].type %>/<%= external.computer.parts[1].name %>/*.js',
  'htdocs/<%= external.computer.parts[2].type %>/<%= external.computer.parts[2].name %>/*.js',
   // Newly added...'htdocs/<%= external.computer.parts[3].type %>/<%= external.computer.parts[3].name %>/*.js'
],
With Solution 2 we don't have to change the src configuration in the Gruntfile.js at all.
Edit:
If you're using a fairly recent version of node.js then you can also refactor Solution 2 as follows:
Gruntfile.js
module.exports = function (grunt) {
  grunt.loadNpmTasks('grunt-contrib-concat');
  const { computer: { parts } } = grunt.file.readYAML('_config.yml');
  grunt.initConfig({
    concat: {
      dist: {
        options: {
          // ...
        },
        src: parts.map(({ type, name }) =>`htdocs/${type}/${name}/*.js`),
        dest: 'htdocs/output.js'
      }
    }
    // ...
  });
  grunt.registerTask('default', [ 'concat' ]);
};
Please ignore StackOverflow's inability to syntax highlight the above example correctly.
Notes:
This refactored version utilizes some ES6 features as follows:
Object destructuring is used to unpack the
partsproperty/value from the parsed_config.yml, into apartsvariable:var { computer: { parts } } = grunt.file.readYAML('_config.yml');The value of the
srcproperty is computed using an Arrow function with themap()method, and Template Literals are used instead of the plus operator (+) for string concatenation.src: parts.map(({ type, name }) =>`htdocs/${type}/${name}/*.js`),
Post a Comment for "Grunt: Access Sequence/list Data From External Yaml File"