Grunt:从外部 YAML 文件访问 Sequence/List 数据
Grunt: Access Sequence/List Data from External YAML File
我正在尝试使用以下方法从我的 Gruntfile 中的外部 YAML 文件访问值:
external = grunt.file.readYAML('_config.yml');
_config.yml
文件具有以下示例数据:
computer:
parts:
- name: brand1
type: cpu
- name: brand2
type: gpu
- name: brand3
type: hd
我一直在尝试使用 <%= %>
grunt 模板访问多级 YAML 数据以获取不同的名称和类型值。
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
文件的结构必须保持不变。
如何通过这种方式访问具有不同属性的 sequence/list?
下面是一些可供考虑的解决方案。但是,首先让我们了解使用 grunt.file.readYAML()
来解析 _config.yml
文件的作用。它本质上产生以下对象:
{
computer: {
parts: [
{
name: 'brand1',
type: 'cpu'
},
{
name: 'brand2',
type: 'gpu'
},
{
name: 'brand3',
type: 'hd'
}
]
}
}
注意 parts
的值是一个对象数组。
解决方案一:
鉴于您希望利用 grunt templates(即 <%= %>
)获得不同的 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' ]);
};
备注:
传入grunt.initConfig
方法的对象的external
属性的值本质上就是上述对象,即利用grunt.file.readYAML()
来解析你的 _config.yml
.
src
属性dist
target, (which is associated with the concat
task)的值是一个数组。该数组的每一项都是我们使用 <% ... %>
符号来引用您的 .yml
文件中的部分的地方。
请注意我们如何通过索引引用 external.computer.parts
数组中的每个对象,即 [0]
、[1]
、[2]
'htdocs/<%= external.computer.parts[0].type %>/<%= external.computer.parts[0].name %>/*.js'
^ ^
方案二:
实现您的要求的另一种方法是完全不使用 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' ]);
};
备注:
这次我们将解析您的 _config.yml
文件的结果分配给一个名为 external
:
的变量
var external = grunt.file.readYAML('_config.yml');
src
属性的值是利用map()
method. Here we create a new array of glob patterns.
计算出来的
src: external.computer.parts.map(function(part) {
return 'htdocs/' + part.type + '/' + part.name + '/*.js'
}),
好处:
解决方案 2 优于 解决方案 1 的主要优势之一是:
如果我们需要向 _config.yml
添加新部分(name
和 tyoe
)。例如:
computer:
parts:
- name: brand1
type: cpu
- name: brand2
type: gpu
- name: brand3
type: hd
- name: brand4 <-------
type: foo <-------
对于解决方案 1,我们需要将其添加到 Gruntfile.js 中的 src
配置中。例如:
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 我们不必更改 Gruntfile.js 中的 src
配置全部.
编辑:
如果您使用的是 node.js 的较新版本,那么您还可以重构 解决方案 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' ]);
};
请忽略 Whosebug 无法正确突出显示上述示例的语法。
备注:
此重构版本利用了一些 ES6 功能,如下所示:
Object destructuring用于将解析后的_config.yml
parts
property/value解压成parts
变量:
var { computer: { parts } } = grunt.file.readYAML('_config.yml');
src
属性 的值是使用 Arrow function with the map()
method, and Template Literals 计算的,而不是用于字符串连接的加号运算符 (+
) .
src: parts.map(({ type, name }) => `htdocs/${type}/${name}/*.js`),
我正在尝试使用以下方法从我的 Gruntfile 中的外部 YAML 文件访问值:
external = grunt.file.readYAML('_config.yml');
_config.yml
文件具有以下示例数据:
computer:
parts:
- name: brand1
type: cpu
- name: brand2
type: gpu
- name: brand3
type: hd
我一直在尝试使用 <%= %>
grunt 模板访问多级 YAML 数据以获取不同的名称和类型值。
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
文件的结构必须保持不变。
如何通过这种方式访问具有不同属性的 sequence/list?
下面是一些可供考虑的解决方案。但是,首先让我们了解使用 grunt.file.readYAML()
来解析 _config.yml
文件的作用。它本质上产生以下对象:
{
computer: {
parts: [
{
name: 'brand1',
type: 'cpu'
},
{
name: 'brand2',
type: 'gpu'
},
{
name: 'brand3',
type: 'hd'
}
]
}
}
注意 parts
的值是一个对象数组。
解决方案一:
鉴于您希望利用 grunt templates(即 <%= %>
)获得不同的 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' ]);
};
备注:
传入
grunt.initConfig
方法的对象的external
属性的值本质上就是上述对象,即利用grunt.file.readYAML()
来解析你的_config.yml
.src
属性dist
target, (which is associated with theconcat
task)的值是一个数组。该数组的每一项都是我们使用<% ... %>
符号来引用您的.yml
文件中的部分的地方。请注意我们如何通过索引引用
external.computer.parts
数组中的每个对象,即[0]
、[1]
、[2]
'htdocs/<%= external.computer.parts[0].type %>/<%= external.computer.parts[0].name %>/*.js' ^ ^
方案二:
实现您的要求的另一种方法是完全不使用 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' ]);
};
备注:
这次我们将解析您的
的变量_config.yml
文件的结果分配给一个名为external
:var external = grunt.file.readYAML('_config.yml');
计算出来的src
属性的值是利用map()
method. Here we create a new array of glob patterns.src: external.computer.parts.map(function(part) { return 'htdocs/' + part.type + '/' + part.name + '/*.js' }),
好处:
解决方案 2 优于 解决方案 1 的主要优势之一是:
如果我们需要向 _config.yml
添加新部分(name
和 tyoe
)。例如:
computer:
parts:
- name: brand1
type: cpu
- name: brand2
type: gpu
- name: brand3
type: hd
- name: brand4 <-------
type: foo <-------
对于解决方案 1,我们需要将其添加到 Gruntfile.js 中的 src
配置中。例如:
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 我们不必更改 Gruntfile.js 中的 src
配置全部.
编辑:
如果您使用的是 node.js 的较新版本,那么您还可以重构 解决方案 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' ]);
};
请忽略 Whosebug 无法正确突出显示上述示例的语法。
备注:
此重构版本利用了一些 ES6 功能,如下所示:
Object destructuring用于将解析后的
_config.yml
parts
property/value解压成parts
变量:var { computer: { parts } } = grunt.file.readYAML('_config.yml');
src
属性 的值是使用 Arrow function with themap()
method, and Template Literals 计算的,而不是用于字符串连接的加号运算符 (+
) .src: parts.map(({ type, name }) => `htdocs/${type}/${name}/*.js`),