使用globbing模式时grunt-contrib-concat的奇怪行为

时间:2014-02-01 09:15:22

标签: javascript angularjs gruntjs grunt-contrib-watch

我正在使用grunt,我想按特定顺序连接某个目录中的所有js文件(它是一个角度js应用程序,所以我想首先执行我的模块定义,然后是其他所有内容)。我的笨蛋concat目标看起来像:

concat: {

    mobile: {
        expand: true,
        cwd: "static/javascript/mobile/app/",
        src: ["main-module.js", "**/*-module.js", "**/*.js", "!static/javascript/mobile/dist/*"],
        dest: "static/javascript/mobile/app/dist/ngmobile.concat.js"
    }
}

以上配置似乎它应该连接main-module.js,然后是所有其他module.js文件,然后是其他所有内容,省略dist文件夹中的所有内容。但是,当使用--verbose运行grunt时,结果如下:

Running "concat:mobile" (concat) task
Verifying property concat.mobile exists in config...OK
Files: static/javascript/mobile/app/main-module.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/main-module.js
Files: static/javascript/mobile/app/clients/clients-module.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/clients/clients-module.js
Files: static/javascript/mobile/app/reports/reports-module.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/reports/reports-module.js
Files: static/javascript/mobile/app/schedules/schedules-module.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/schedules/schedules-module.js
Files: static/javascript/mobile/app/services/services-module.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/services/services-module.js
Files: static/javascript/mobile/app/clients/addclient-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/clients/addclient-ctrl.js
Files: static/javascript/mobile/app/clients/clientprofile-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/clients/clientprofile-ctrl.js
Files: static/javascript/mobile/app/clients/clients-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/clients/clients-ctrl.js
Files: static/javascript/mobile/app/clients/clients-service.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/clients/clients-service.js
Files: static/javascript/mobile/app/common/directives.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/common/directives.js
Files: static/javascript/mobile/app/common/filters.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/common/filters.js
Files: static/javascript/mobile/app/common/header-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/common/header-ctrl.js
Files: static/javascript/mobile/app/common/navbarcollapse-directive.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/common/navbarcollapse-directive.js
Files: static/javascript/mobile/app/dist/ngmobile.concat.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/dist/ngmobile.concat.js
Files: static/javascript/mobile/app/main-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/main-ctrl.js
Files: static/javascript/mobile/app/main-service.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/main-service.js
Files: static/javascript/mobile/app/reports/reports-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/reports/reports-ctrl.js
Files: static/javascript/mobile/app/schedules/schedules-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/schedules/schedules-ctrl.js
Files: static/javascript/mobile/app/schedules/schedules-service.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/schedules/schedules-service.js
Files: static/javascript/mobile/app/services/addservice-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/services/addservice-ctrl.js
Files: static/javascript/mobile/app/services/serviceprofile-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/services/serviceprofile-ctrl.js
Files: static/javascript/mobile/app/services/services-ctrl.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/services/services-ctrl.js
Files: static/javascript/mobile/app/services/services-service.js -> static/javascript/mobile/app/dist/ngmobile.concat.js/services/services-service.js
Options: separator="\n", banner="", footer="", stripBanners=false, process=false
Reading static/javascript/mobile/app/main-module.js...OK
Writing static/javascript/mobile/app/dist/ngmobile.concat.js/main-module.js...ERROR
Warning: Unable to write "static/javascript/mobile/app/dist/ngmobile.concat.js/main-module.js" file (Error code: ENOTDIR). Use --force to continue.

Aborted due to warnings.

这告诉我它找到了我想要它找到的文件,然后尝试将它们写入(复制?)到 dest 中指定的文件路径。我怎么会得到这么可怕的错误? :)如果有人足够关心我头上的最后几根头发,我真的很感激我在这里做错了什么输入。我想将 src 中的所有文件连接到 dest 文件中。

修改

如果我删除了 expand 属性,则输出如下所示:

Running "concat:mobile" (concat) task
Verifying property concat.mobile exists in config...OK
Files: main-module.js, clients/clients-module.js, reports/reports-module.js, schedules/schedules-module.js, services/services-module.js, clients/addclient-ctrl.js, clients/clientprofile-ctrl.js, clients/clients-ctrl.js, clients/clients-service.js, common/directives.js, common/filters.js, common/header-ctrl.js, common/navbarcollapse-directive.js, dist/ngmobile.concat.js, main-ctrl.js, main-service.js, reports/reports-ctrl.js, schedules/schedules-ctrl.js, schedules/schedules-service.js, services/addservice-ctrl.js, services/serviceprofile-ctrl.js, services/services-ctrl.js, services/services-service.js -> static/javascript/mobile/app/dist/ngmobile.concat.js
Options: separator="\n", banner="", footer="", stripBanners=false, process=false
>> Source file "main-module.js" not found.
>> Source file "clients/clients-module.js" not found.
>> Source file "reports/reports-module.js" not found.
>> Source file "schedules/schedules-module.js" not found.
>> Source file "services/services-module.js" not found.
>> Source file "clients/addclient-ctrl.js" not found.
>> Source file "clients/clientprofile-ctrl.js" not found.
>> Source file "clients/clients-ctrl.js" not found.
>> Source file "clients/clients-service.js" not found.
>> Source file "common/directives.js" not found.
>> Source file "common/filters.js" not found.
>> Source file "common/header-ctrl.js" not found.
>> Source file "common/navbarcollapse-directive.js" not found.
>> Source file "dist/ngmobile.concat.js" not found.
>> Source file "main-ctrl.js" not found.
>> Source file "main-service.js" not found.
>> Source file "reports/reports-ctrl.js" not found.
>> Source file "schedules/schedules-ctrl.js" not found.
>> Source file "schedules/schedules-service.js" not found.
>> Source file "services/addservice-ctrl.js" not found.
>> Source file "services/serviceprofile-ctrl.js" not found.
>> Source file "services/services-ctrl.js" not found.
>> Source file "services/services-service.js" not found.
Writing static/javascript/mobile/app/dist/ngmobile.concat.js...OK
File "static/javascript/mobile/app/dist/ngmobile.concat.js" created.

注意,剪切上面的第三行“Files:...”列出了我想要它找到的所有文件,但后来说找不到源文件。

编辑2

Matt的解决方案可以解决这个问题,下面是我更新的代码:

concat: {
    mobile: {
        dest: "static/javascript/mobile/app/dist/ngmobile-concat.js",
        src: (function () {
            var cwd = "static/javascript/mobile/app/";
            var files = ["*-module.js", "**/*-module.js", "**/*.js"];

            files = files.map(function (file) {
                return cwd + file;
            });

            files.push("! static/javascript/mobile/app/dist");

            return files;
        }())
    }
}

2 个答案:

答案 0 :(得分:4)

我自己使用角度应用程序遇到了这个问题,我考虑了三个选项:

1)按照项目github线程

的建议

你并不孤单。有关此问题的grunt-contrib-concat github项目有一个long thread。这与cwddest合作的方式有关。

A suggested workaround发布在那里将cwd属性移动到一个函数中,然后产生预期的结果而不是ENOTDIR错误。

src: (function() {
  var cwd = 'src/js/';
  var arr = [];
  // determine file order here and concat to arr
  return arr.map(function(file) { return cwd + file; });
}())

我认为缺点是在gruntfile中添加了一个函数,这通常非常简单。如果你不是维护应用程序的唯一人,那可能会让人感到困惑。

2)抛弃cwd并使用静态方法<%=%>变量语法

如果您的srcdest目录在整个gruntfile中是一致的,您可以定义srcdest目录,执行以下操作:

myapp: {
  // configurable paths
  app: "static/javascript/mobile/app/",
  dist: "static/javascript/mobile/app/dist/"
}

...然后您可以删除cwd属性并将其配置为更“静态”:

concat: {

    mobile: {
        expand: true,
        src: ["<%= myapp.app %>/main-module.js", "<%= myapp.app %>/**/*-module.js", "<%= myapp.app %>/**/*.js", "!<%= myapp.dist %>/*"],
        dest: "<%= myapp.dist %>/ngmobile.concat.js"
    }
}

对于我的大部分项目来说,这已足够。当我稍后回来并需要进行更改时,它很简单,干燥且易于理解。

授予:首先使用&lt;%=%&gt;所有的配置属性更难阅读杂乱,但在我的编辑器中有一些可以改进的格式。此外,其他程序员很容易阅读并了解您的意图。

3)使用像您这样做的用户插件

如果您也在进行缩小,可以考虑使用grunt-usemin之类的插件。

此选项的缺点很明显:usemin增加了复杂性,因为您现在有另一个插件来管理和配置,您需要格式化HTML以使用usemin功能。 Usemin配置一开始可能会让人感到困惑,如果您正在与团队合作,那么修改usemin配置或HTML注释usemin需要的程序员或设计人员很容易破坏事物。

好处是usemin将直接从HTML生成grunt的复制,连接和缩小配置。因此,如果您添加/删除脚本或更改HTML中的加载顺序,您将不必在grunt配置中执行任何操作,因为usemin将选择它。

答案 1 :(得分:0)

如果&#39; cwd&#39;设置,grunt-contrib-concat只复制文件,而不是concat。 这个问题有一个棘手的解决方案。只需添加&#39;重命名&#39;财产和回报&#39; dest&#39;名称如下。

rename: function (dest) {
              return dest;
        },