Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
325 views
in Technique[技术] by (71.8m points)

gruntjs - Using grunt to concat many files from many dirs into single renamed file in new directory

I have an Angular project with potentially many modules. Each module has it's own directory with subdirectories for controllers, directives, services, etc. Something like this:

src
|-- js
    |-- modules
        |-- moduleOne
            | module.js
            |-- controllers
                | listController.js
                | detailController.js
            |-- directives
                | listItem.js
                | summaryWidget.js
            |-- filters
            |-- services
                | moduleService.js

My build essentially bundles and compiles files from src/ and puts into dev/, then minifies the files in dev/ and moves into prod/. During dev, the server points to the dev/ folder and in production, the server points to the prod/ folder (also why the files are ending in .min.js even though they are only compiled/concated). This process is working well.

Currently, my concat task is grabbing all the files in moduleOne/ and creating a single moduleOne.js file in my dev directory. This is what I want to happen, but more dynamically:

concat: {
    modules: {
        files: {
            "dev/js/modules/moduleOne.min.js": [
                "src/js/modules/moduleOne/*.js",
                "src/js/modules/moduleOne/**/*.js"
            ],
            "dev/js/modules/moduleTwo.min.js": [
                "src/js/modules/moduleTwo/*.js",
                "src/js/modules/moduleTwo/**/*.js"
            ]
        } 
    }
}

The problem is that I have to do this for every module, but don't think I would need to.

I tried doing the following because it's sort of what I want to do:

concat: {
    modules: {
        files: [{
            expand: true,
            cwd: "src/js/modules",
            src: "**/*.js",
            dest: "dev/js/modules",
            ext: ".min.js"
        }]
    }
}

But the result was all my files and directory structure moved over from src/ to dev/. I basically used concat to do a copy, not helpful.

I'd like to do something like this:

concat: {
    modules: {
        files: [{
            expand: true,
            cwd: "src/js/modules",
            src: "**/*.js",
            dest: "dev/js/modules/<foldername>.min.js",  <- how do I achieve this?
        }]
    }
}

I've been reading a lot, but it seems that I only get close to finding the answer and am having trouble putting the concepts together. A lot of what I find is just single files into a new directory, with a rename. I'd like multiple files to single file into new directory with a rename. Cuz that's how I roll :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So, I found the answer I was looking for.

This SO post was basically the same question with a good answer. Unfortunately it didn't come up when I was creating my question or else you wouldn't be reading this.

There was a slight tweak to my needs. I needed to do it dynamically per module instead of just one compile.js file so my final code is as follows, placed just after my initConfig():

grunt.registerTask("prepareModules", "Finds and prepares modules for concatenation.", function() {

    // get all module directories
    grunt.file.expand("src/js/modules/*").forEach(function (dir) {

        // get the module name from the directory name
        var dirName = dir.substr(dir.lastIndexOf('/')+1);

        // get the current concat object from initConfig
        var concat = grunt.config.get('concat') || {};

        // create a subtask for each module, find all src files
        // and combine into a single js file per module
        concat[dirName] = {
            src: [dir + '/**/*.js'],
            dest: 'dev/js/modules/' + dirName + '.min.js'
        };

        // add module subtasks to the concat task in initConfig
        grunt.config.set('concat', concat);
    });
});

// the default task
grunt.registerTask("default", ["sass", "ngtemplates", "prepareModules", "concat", "uglify", "cssmin"]);

This essentially makes my concat task look like it did when I was hand coding it, but just a little simpler (and scalable!).

concat: {
    ...
    moduleOne: {
        src: "src/js/modules/moduleOne/**/*.js",            
        dest: "dev/js/modules/moduleOne.min.js"
    },
    moduleTwo:{
        src: "src/js/modules/moduleTwo/**/*.js",
        dest: "dev/js/modules/moduleTwo.min.js"
    }
}

Another deviation I made from the SO post was that I chose not to have prepareModules run concat on it's own when it was done. My default task (which watch is setup to run during dev) still does all my processing.

This leaves me with the following structure, ready for minification into prod/:

| dev
    | js
        | modules
            |-- moduleOne.min.js
            |-- moduleTwo.min.js

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...