Grunt: доступ к последовательности / списку данных из внешнего файла YAML - PullRequest
1 голос
/ 24 апреля 2020

Я пытаюсь получить доступ к значениям из внешнего файла YAML в моем Gruntfile, используя:

external = grunt.file.readYAML('_config.yml');

Файл _config.yml содержит следующие данные примера:

computer:
  parts:
    - name: brand1
      type: cpu
    - name: brand2
      type: gpu
    - name: brand3
      type: hd

I ' мы пытались получить доступ к многоуровневым данным YAML, используя <%= %> grunt-шаблоны для получения различных значений имени и типа.

module.exports = {
  concat: {
    src: ['htdocs/<%= external.computer.parts['type'] %>/<%= external.computer.parts['name'] %>/*.js'],
    dest: 'htdocs/output.js'
  }
};

Основная цель состояла в том, чтобы объединить файлы из разных каталогов таким образом в один , но я не могу получить доступ к данным из файла _config.yml за пределами external.computer.parts. К вашему сведению, структура файла _config.yml должна остаться неизменной.

Как получить доступ к последовательности / списку с различными свойствами таким образом?

1 Ответ

0 голосов
/ 24 апреля 2020

Ниже приведено несколько решений для рассмотрения. Однако сначала давайте разберемся, что делает grunt.file.readYAML() для анализа вашего _config.yml файла. По сути, он создает следующий объект:

{
  computer: {
    parts: [
      {
        name: 'brand1',
        type: 'cpu'
      },
      {
        name: 'brand2',
        type: 'gpu'
      },
      {
        name: 'brand3',
        type: 'hd'
      }
    ]
  }
}

Примечание , как значение parts представляет собой массив объектов.


Решение 1:

Учитывая, что вы хотите использовать шаблоны grunt (то есть <%= %>) для получения различных значений name и type, рассмотрите возможность настройки задачи concat в вашем Gruntfile . js следующим образом:

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' ]);

};

Примечания:

  1. Значение свойства external объекта, переданного в метод grunt.initConfig, по сути является вышеупомянутым объектом, т.е. это результат использования grunt.file.readYAML() для анализа вашего _config.yml.

  2. Значение свойства src цели dist target (которая связана с задачей concat ), это массив. В каждом элементе этого массива мы используем обозначение <% ... %> для ссылки на части из вашего файла .yml.

    Обратите внимание, как мы ссылаемся на каждый объект в массиве external.computer.parts по его индексу, то есть [0], [1], [2]

    'htdocs/<%= external.computer.parts[0].type %>/<%= external.computer.parts[0].name %>/*.js'
                                        ^                                      ^
    

Решение 2:

Еще один способ удовлетворить ваши требования - вообще не использовать шаблонов grunt, то есть <% ... %>. Рассмотрим следующее решение:

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' ]);

};

Примечания:

  1. На этот раз мы присваиваем результат анализа вашего _config.yml файла переменной external:

    var external = grunt.file.readYAML('_config.yml');
    
  2. Значение свойства src вычисляется с использованием map() метод. Здесь мы создаем новый массив шаблонов глобуса .

    src: external.computer.parts.map(function(part) {
      return 'htdocs/' + part.type + '/' + part.name + '/*.js'
    }),
    

Преимущества:

Одно из ключевых преимуществ Решение 2 имеет более Решение 1 :

Если нам нужно добавить новую деталь (name и tyoe) к _config.yml. Например:

computer:
  parts:
    - name: brand1
      type: cpu
    - name: brand2
      type: gpu
    - name: brand3
      type: hd
    - name: brand4      <-------
      type: foo         <-------

С Решение 1 нам нужно добавить его в конфигурацию src в Gruntfile. js. Например:

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'
],

С Решение 2 нам не нужно изменять конфигурацию src в Gruntfile. js вообще.


Редактировать:

Если вы используете довольно свежую версию node.js, вы также можете выполнить рефакторинг Solution 2 следующим образом:

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' ]);

};

Пожалуйста, игнорируйте невозможность синтаксиса StackOverflow, выделите приведенный выше пример правильно.

Примечания:

В этой переработанной версии некоторые функции ES6 используются следующим образом:

  • Уничтожение объектов используется для распаковки свойства / значения parts из проанализированного _config.yml в переменную parts:

    var { computer: { parts } } = grunt.file.readYAML('_config.yml');
    
  • Значение свойства src вычисляется с использованием функции Arrow с метод map() и литералы шаблона используются вместо оператора плюс (+) для объединения строк.

    src: parts.map(({ type, name }) => `htdocs/${type}/${name}/*.js`),
    
...