Grunt:recursion模板如何工作?
我是Grunt的新手,并且在recursion模板方面遇到了一些问题。 下面是一个具体的例子:
var path = require('path'); module.exports = function(grunt) { grunt.initConfig({ // Stash path here so we can reference it from templates. path: path, argPrint: function(arg1, arg2) { return "arg1: " + arg1 + " arg2: " + arg2; }, build: { root_dir: __dirname, build_dir: '<%= path.resolve(build.root_dir, "dev") %>', vendor_dir: '<%= path.resolve(build.build_dir, "vendor") %>', classes_dir: '<%= path.resolve(build.vendor_dir, "classes") %>', test: '<%= argPrint(build.build_dir, "vendor") %>' } }); grunt.registerTask('print_build_dir', 'Prints the build directory.', function() { grunt.log.writeln(grunt.config("build.root_dir")); grunt.log.writeln(grunt.config("build.build_dir")); grunt.log.writeln(grunt.config("build.vendor_dir")); grunt.log.writeln(grunt.config("build.classes_dir")); grunt.log.writeln(grunt.config("build.test")); }); };
将它popup到Gruntfile.js
,运行npm install grunt
,然后运行grunt print_build_dir
。
如果你在/Users/jvilk/Code/grunt-test
,我会希望输出结果是:
$ grunt print_build_dir /Users/jvilk/Code/grunt-test /Users/jvilk/Code/grunt-test/dev /Users/jvilk/Code/grunt-test/dev/vendor /Users/jvilk/Code/grunt-test/dev/vendor/classes arg1: /Users/jvilk/Code/grunt-test/dev arg2: vendor
相反,输出是:
$ grunt print_build_dir /Users/jvilk/Code/grunt-test /Users/jvilk/Code/grunt-test/dev /Users/jvilk/Code/grunt-test//Users/jvilk/Code/grunt-test/dev/vendor /Users/jvilk/Code/grunt-test//Users/jvilk/Code/grunt-test//Users/jvilk/Code/grunt-test/dev/vendor/classes arg1: /Users/jvilk/Code/grunt-test/dev arg2: vendor
这里发生了什么? 从test
configuration属性来看,显然path.resolve
应该接收vendor_dir
属性的正确参数 – 即,它将parsing为path.resolve("/Users/jvilk/Code/grunt-test/dev", "vendor")
– 但是我完全build.root_dir
不清楚为什么它会在build.root_dir
前面添加一个额外的正斜杠。
任何帮助或指导,将不胜感激我和我挣扎的Gruntfile
。 谢谢!
编辑:作为一个先发制人的附录,我意识到我不需要使用模板来实现这个特殊的例子 – 我可以直接使用path.resolve
。 但是,在我的非示例Gruntfile
, Gruntfile
中的一个目录名是一个dynamic设置的属性,需要使用模板。
EDIT2:正如Andrew所指出的,模板扩展在vendor_dir
上的工作方式如下:
'<%= path.resolve(build.build_dir, "vendor") %>' -> path.resolve('<%= path.resolve(build.root_dir, "dev") %>', "vendor") -> '/Users/jvilk/Code/grunt-test/<%= path.resolve(build.root_dir, "dev") %>/vendor' -> '/Users/jvilk/Code/grunt-test//Users/jvilk/Code/grunt-test/vendor'
我的test
属性工作,因为它扩展如下:
'<%= argPrint(build.build_dir, "vendor") %>' -> argPrint('<%= path.resolve(build.root_dir, "dev") %>', "vendor") -> 'arg1: <%= path.resolve(build.root_dir, "dev") %> arg2: vendor' -> 'arg1: /Users/jvilk/Code/grunt-test arg2: vendor'
我不明白他们为什么做这个devise决定,但我可以轻松地模拟我想要的模板语义,把所有这些都包含在一个重复处理string的函数中,直到所有的<%=
消失。
首先让我从一个工作样本开始。
grunt.initConfig({ path: path, argPrint: function(arg1, arg2) { return "arg1: " + arg1 + " arg2: " + arg2; }, resolvePath: function(from, to) { return path.resolve(grunt.config.process(from), to); }, build: { root_dir: __dirname, build_dir: "<%= resolvePath(build.root_dir, 'dev')%>", vendor_dir: "<%= resolvePath(build.build_dir, 'vendor') %>", classes_dir: "<%= resolvePath(build.vendor_dir, 'classes') %>", test: "<%= argPrint(build.build_dir, 'vendor') %>" } }); grunt.registerTask('print_build_dir', 'Prints the build directory.', function() { grunt.log.writeln(grunt.config.get("build.root_dir")); grunt.log.writeln(grunt.config.get("build.build_dir")); grunt.log.writeln(grunt.config.get("build.vendor_dir")); grunt.log.writeln(grunt.config.get("build.classes_dir")); grunt.log.writeln(grunt.config.get("build.test")); }); };
这输出你所期望的:
/用户/ andrewtremblay /开发/咕噜testing
/用户/ andrewtremblay /开发/咕噜,testing/开发
/用户/ andrewtremblay /开发/咕噜,testing/开发/销售商
/用户/ andrewtremblay /开发/咕噜testing的/ dev /供应商/类
arg1:/ Users / andrewtremblay / Development / grunt-test / dev arg2:vendor
当我使用ResolvePath
函数进行testing时,注意到传递给它的值没有被处理。 (而不是使用config.get('build.build_dir')
的输出,它使用了config.getRaw('build.build_dir')
)
我不知道这是否是一个错误,但我认为答案在于path.resolve
以及如何传递可处理variables导致未定义的行为。
从文档 (我的重点):
path.resolve([from ...], to)
如果不是
from
参数的绝对值from
则按从右到左的顺序,直到find绝对path。 如果在使用path中的所有path之后仍然没有find绝对path,那么也使用当前的工作目录。 生成的path被标准化,除非path被parsing到根目录,否则将删除结尾的斜线。
这(加上path.resolve
不处理你的configuration对象)可以解释为什么你的工作目录不断前置。
当Grunt从config
get
,如果它find了模板模式,它将处理这些值。
它看起来像处理模板,直到find一个没有模板模式的string。 所以你的情况每一步都是这样的:
__dirname => '/Users/jvilk/Code/grunt-test' build.build_dir => '<%= path.resolve(build.root_dir, "dev") %> => __dirname + "dev" => '/Users/jvilk/Code/grunt-test/dev' build.vendor_dir => '<%= path.resolve(build.build_dir, "vendor") %>' => '/Users/jvilk/Code/grunt-test/<%= path.resolve(build.root_dir, "dev") %>/vendor' => '/Users/jvilk/Code/grunt-test//Users/jvilk/Code/grunt-test/dev/vendor' build.classes_dir => '<%= path.resolve(build.vendor_dir, "classes") %>' => '/Users/jvilk/Code/grunt-test/<%= path.resolve(build.build_dir, "vendor") %>'/classes' => '/Users/jvilk/Code/grunt-test//Users/jvilk/Code/grunt-test/<%= path.resolve(build.root_dir, "dev") %>/vendor/classes' => '/Users/jvilk/Code/grunt-test//Users/jvilk/Code/grunt-test//Users/jvilk/Code/grunt-test/dev/vendor/classes'
我不知道是否有一个很好的解决办法,除了在运行时手动扩展你的configuration:
grunt.config("build.build_dir", grunt.config("build.build_dir")) grunt.config("build.vendor_dir", grunt.config("build.vendor_dir")) grunt.config("build.classes_dir", grunt.config("build.classes_dir"))