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

Gre*_*eg 5 javascript angularjs gruntjs grunt-contrib-watch

我正在使用grunt,我想按特定顺序连接某个目录中的所有js文件(它是一个角度js应用程序,所以我想首先执行我的模块定义,然后是其他所有内容).我的grunt 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"
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的配置好像应该连接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.
Run Code Online (Sandbox Code Playgroud)

这告诉我它找到了我想要它找到的文件,然后尝试将它们写入(复制?)到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.
Run Code Online (Sandbox Code Playgroud)

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

编辑2

下面马特的解决方案解决了这个问题,下面是我更新的代码:

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;
        }())
    }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*tis 4

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

1)遵循项目github线程上的建议

你并不孤单。grunt-contrib-concat github 项目上有一个关于这个问题的长帖子。cwd这与的工作方式有关dest

那里发布的建议解决方法将该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; });
}())
Run Code Online (Sandbox Code Playgroud)

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

2) 放弃cwd并使用带有 <%= %> 变量语法的静态方法

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

myapp: {
  // configurable paths
  app: "static/javascript/mobile/app/",
  dist: "static/javascript/mobile/app/dist/"
}
Run Code Online (Sandbox Code Playgroud)

...然后您可以删除该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"
    }
}
Run Code Online (Sandbox Code Playgroud)

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

当然:配置属性一开始会因为 <%=%> 的混乱而变得有点难以阅读,但我的编辑器中的一些格式可以改进。而且,其他程序员很容易阅读本文并知道您的意图。

3)使用像usemin这样的插件来为你做这件事

如果您也在进行缩小,您可能会考虑像grunt-usemin这样的插件。

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

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