5

I'm using grunt, and I would like to concat all js files in a certain directory, in a specific order (It's an angular js app, so I want to do my module definitions first, followed by everything else). My grunt concat target looks like:

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

The above configuration seems like it should concat main-module.js, followed by all other module.js files, followed by everything else, omitting everything in the dist folder. However, the result, when running grunt with --verbose is something like:

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.

This tells me that it's finding the files I want it to find, and then attempting to write (copy?) them to the file path specified in dest. How did I get this so horribly wrong? :) If anyone cares enough to save the last few hairs on my head I would really appreciate some input as to what I'm doing wrong here. I want to concat all the files in src into the dest file.

Edit

If I remove the expand property, the output looks like:

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.

Notice, the third line in the snipped above "Files: ..." lists all the files I wanted it to find, but then says the source file isn't found.

EDIT 2

Matt's solution below takes care of the issue, below is my updated code:

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;
        }())
    }
}
4

2 回答 2

4

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

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

我认为缺点是在 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"
    }
}

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

诚然:配置属性开始变得有点难以阅读,因为所有 <%=%> 杂乱无章,但我的编辑器中的一些格式可以改进。此外,其他程序员很容易阅读并知道您的意图。

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

如果你也在做缩小,你可以考虑一个像grunt-usemin这样的插件。

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

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

于 2014-02-01T14:27:08.920 回答
0

如果设置了 'cwd',grunt-contrib-concat 只会复制文件,而不是 concat。这个问题有一个棘手的解决方案。只需添加“重命名”属性并返回“目标”名称,如下所示。

rename: function (dest) {
              return dest;
        },
于 2016-08-04T07:58:50.247 回答