2

私は Grunt が初めてで、再帰的なテンプレートに問題があります。具体的で最小限の例を次に示します。

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"));
  });
};

Gruntfile.jsそれを a 、 run npm install grunt、そしてrun にポップします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明らかです-つまり、解決されます-しかし、プロパティの値の前に追加のスラッシュを追加する理由について完全に混乱しています。path.resolvevendor_dirpath.resolve("/Users/jvilk/Code/grunt-test/dev", "vendor")build.root_dir

私と私の苦労の両方に、どんな助けや指導も大歓迎Gruntfileです。ありがとう!

編集:先制的な補遺として、この特定の例を実現するためにテンプレートを使用する必要がないことを認識しています-path.resolve直接使用できます。ただし、私の非例Gruntfileでは、ディレクトリ名の 1 つがpath.resolve動的に設定されるプロパティであり、テンプレートを使用する必要があります。

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'

彼らがこの設計上の決定を下した理由はわかりませんが、すべて<%=がなくなるまで文字列を繰り返し処理する関数にこれらすべてをラップすることで、必要なテンプレート セマンティクスを簡単にエミュレートできます。

4

2 に答える 2

2

まず、実際のサンプルから始めましょう。

  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"));
  });
};

これはあなたが期待するものを出力します:

/Users/andrewtremblay/開発/grunt-test

/Users/andrewtremblay/Development/grunt-test/dev

/Users/andrewtremblay/Development/grunt-test/dev/vendor

/Users/andrewtremblay/Development/grunt-test/dev/vendor/classes

arg1: /Users/andrewtremblay/Development/grunt-test/dev arg2: ベンダー

関数でこれをテストしたときに気付いたResolvePathのは、渡された値がfrom処理されていないことでした。( の出力を使用する代わりにconfig.get('build.build_dir')、 の結果を使用していましたconfig.getRaw('build.build_dir'))

これがバグかどうかはわかりませんが、答えはpath.resolve処理可能な変数を渡すと未定義の動作につながると思います。

ドキュメントから(強調して):

path.resolve([from ...], to)

toまだ絶対パスがない場合はfrom、絶対パスが見つかるまで、右から左の順に先頭に追加されます。すべての from パスを使用しても絶対パスが見つからない場合は、現在の作業ディレクトリも使用されます。結果のパスは正規化され、パスがルート ディレクトリに解決されない限り、末尾のスラッシュは削除されます。

それ(および構成path.resolveオブジェクトを処理していなかったという事実)は、作業ディレクトリが先頭に追加され続けた理由を説明できます。

于 2014-01-14T21:40:21.143 に答える
0

Grunt がgetfrom を実行するconfigと、テンプレート パターンが見つかった場合に値が処理されます。

テンプレートパターンのない文字列が見つかるまでテンプレートを処理しているようです。したがって、状況の各ステップは次のようになります。

__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'

実行時に構成を手動で展開する以外に、これを回避する良い方法があるかどうかはわかりません。

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"))
于 2014-01-14T21:19:02.847 に答える