javascript - 使用 Grunt (Yeoman) 的多个构建文件夹(多个客户端、多任务、多个目标)

标签 javascript node.js cordova gruntjs yeoman

我现在正在构建一个项目,它将是一个 web 应用程序(可在浏览器上运行)和一个 Phonegap 应用程序(iOS 和 Android)。尽管从理论上讲,我的项目可以使用与我的 Yeoman 相同的 dist 文件夹。 生成, Grunt 通过运行 grunt build 任务 build 生产就绪代码。我想运行类似 grunt build_webgrunt build_iosgrunt build_android 的程序,分别为每个平台构建生产代码。或者 grunt build:webgrunt build:iosgrunt build:android。这样,我就可以自定义一些加载的脚本、图像等,每个脚本、图像等都有自己的构建指令。

那么,我是否应该通过 distbuild 指令负责任地完成我的 Gruntfile 复制和粘贴?或者,对此有最佳实践吗?(试过了,没用)

Yeoman 伙计们,这可能吗?

这是我当前的 Gruntfile.js 以备不时之需。

'use strict';
var LIVERELOAD_PORT = 35729;
var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT});
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {
    // show elapsed time at the end
    require('time-grunt')(grunt);
    // load all grunt tasks
    require('load-grunt-tasks')(grunt);

    // configurable paths
    var yeomanConfig = {
        app: 'app',
        dist: '../www'
    };

    grunt.initConfig({
        yeoman: yeomanConfig,
        watch: {
            coffee: {
                files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
                tasks: ['coffee:dist']
            },
            coffeeTest: {
                files: ['test/spec/{,*/}*.coffee'],
                tasks: ['coffee:test']
            },
            compass: {
                files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
                tasks: ['compass:server', 'autoprefixer']
            },
            styles: {
                files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
                tasks: ['copy:styles', 'autoprefixer']
            },
            livereload: {
                options: {
                    livereload: LIVERELOAD_PORT
                },
                files: [
                    '<%= yeoman.app %>/*.html',
                    '.tmp/styles/{,*/}*.css',
                    '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
                    '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
                ]
            }
        },
        connect: {
            options: {
                port: 9000,
                // change this to '0.0.0.0' to access the server from outside
                hostname: 'localhost'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, yeomanConfig.app)
                        ];
                    }
                }
            },
            test: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test'),
                            mountFolder(connect, yeomanConfig.app)
                        ];
                    }
                }
            },
            dist: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, yeomanConfig.dist)
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://localhost:<%= connect.options.port %>'
            }
        },
        clean: {
            options: {
                force: true
            },
            dist: {
                files: [{
                    dot: true,
                    src: [
                        '.tmp',
                        '<%= yeoman.dist %>/*',
                        '!<%= yeoman.dist %>/.git*'
                    ]
                }]
            },
            server: '.tmp'
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            all: [
                'Gruntfile.js',
                '<%= yeoman.app %>/scripts/{,*/}*.js',
                '!<%= yeoman.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://localhost:<%= connect.options.port %>/index.html']
                }
            }
        },
        coffee: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>/scripts',
                    src: '{,*/}*.coffee',
                    dest: '.tmp/scripts',
                    ext: '.js'
                }]
            },
            test: {
                files: [{
                    expand: true,
                    cwd: 'test/spec',
                    src: '{,*/}*.coffee',
                    dest: '.tmp/spec',
                    ext: '.js'
                }]
            }
        },
        compass: {
            options: {
                sassDir: '<%= yeoman.app %>/styles',
                cssDir: '.tmp/styles',
                generatedImagesDir: '.tmp/images/generated',
                imagesDir: '<%= yeoman.app %>/images',
                javascriptsDir: '<%= yeoman.app %>/scripts',
                fontsDir: '<%= yeoman.app %>/styles/fonts',
                importPath: '<%= yeoman.app %>/bower_components',
                httpImagesPath: '/images',
                httpGeneratedImagesPath: '/images/generated',
                httpFontsPath: '/styles/fonts',
                relativeAssets: false
            },
            dist: {
                options: {
                    generatedImagesDir: '<%= yeoman.dist %>/images/generated'
                }
            },
            server: {
                options: {
                    debugInfo: true
                }
            }
        },
        autoprefixer: {
            options: {
                browsers: ['last 1 version']
            },
            dist: {
                files: [{
                    expand: true,
                    cwd: '.tmp/styles/',
                    src: '{,*/}*.css',
                    dest: '.tmp/styles/'
                }]
            }
        },
        // not used since Uglify task does concat,
        // but still available if needed
        /*concat: {
            dist: {}
        },*/
        requirejs: {
            dist: {
                // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js
                options: {
                    // `name` and `out` is set by grunt-usemin
                    baseUrl: yeomanConfig.app + '/scripts',
                    optimize: 'none',
                    // TODO: Figure out how to make sourcemaps work with grunt-usemin
                    // https://github.com/yeoman/grunt-usemin/issues/30
                    //generateSourceMaps: true,
                    // required to support SourceMaps
                    // http://requirejs.org/docs/errors.html#sourcemapcomments
                    preserveLicenseComments: false,
                    useStrict: true,
                    wrap: true
                    //uglify2: {} // https://github.com/mishoo/UglifyJS2
                }
            }
        },
        rev: {
            dist: {
                files: {
                    src: [
                        '<%= yeoman.dist %>/scripts/{,*/}*.js',
                        '<%= yeoman.dist %>/styles/{,*/}*.css',
                        '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp}',
                        '<%= yeoman.dist %>/styles/fonts/{,*/}*.*'
                    ]
                }
            }
        },
        useminPrepare: {
            options: {
                dest: '<%= yeoman.dist %>'
            },
            html: '<%= yeoman.app %>/index.html'
        },
        usemin: {
            options: {
                dirs: ['<%= yeoman.dist %>']
            },
            html: ['<%= yeoman.dist %>/{,*/}*.html'],
            css: ['<%= yeoman.dist %>/styles/{,*/}*.css']
        },
        imagemin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>/images',
                    src: '{,*/}*.{png,jpg,jpeg}',
                    dest: '<%= yeoman.dist %>/images'
                }]
            }
        },
        svgmin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>/images',
                    src: '{,*/}*.svg',
                    dest: '<%= yeoman.dist %>/images'
                }]
            }
        },
        cssmin: {
            // This task is pre-configured if you do not wish to use Usemin
            // blocks for your CSS. By default, the Usemin block from your
            // `index.html` will take care of minification, e.g.
            //
            //     <!-- build:css({.tmp,app}) styles/main.css -->
            //
            // dist: {
            //     files: {
            //         '<%= yeoman.dist %>/styles/main.css': [
            //             '.tmp/styles/{,*/}*.css',
            //             '<%= yeoman.app %>/styles/{,*/}*.css'
            //         ]
            //     }
            // }
        },
        htmlmin: {
            dist: {
                options: {
                    /*removeCommentsFromCDATA: true,
                    // https://github.com/yeoman/grunt-usemin/issues/44
                    //collapseWhitespace: true,
                    collapseBooleanAttributes: true,
                    removeAttributeQuotes: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true*/
                },
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>',
                    src: '*.html',
                    dest: '<%= yeoman.dist %>'
                }]
            }
        },
        // Put files not handled in other tasks here
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= yeoman.app %>',
                    dest: '<%= yeoman.dist %>',
                    src: [
                        '*.{ico,png,txt}',
                        '.htaccess',
                        'images/{,*/}*.{webp,gif}',
                        'styles/fonts/{,*/}*.*'
                    ]
                }]
            },
            styles: {
                expand: true,
                dot: true,
                cwd: '<%= yeoman.app %>/styles',
                dest: '.tmp/styles/',
                src: '{,*/}*.css'
            }
        },
        modernizr: {
            devFile: '<%= yeoman.app %>/bower_components/modernizr/modernizr.js',
            outputFile: '<%= yeoman.dist %>/bower_components/modernizr/modernizr.js',
            files: [
                '<%= yeoman.dist %>/scripts/{,*/}*.js',
                '<%= yeoman.dist %>/styles/{,*/}*.css',
                '!<%= yeoman.dist %>/scripts/vendor/*'
            ],
            uglify: true
        },
        concurrent: {
            server: [
                'compass',
                'coffee:dist',
                'copy:styles'
            ],
            test: [
                'coffee',
                'copy:styles'
            ],
            dist: [
                'coffee',
                'compass',
                'copy:styles',
                'imagemin',
                'svgmin',
                'htmlmin'
            ]
        },
        bower: {
            options: {
                exclude: ['modernizr']
            },
            all: {
                rjsConfig: '<%= yeoman.app %>/scripts/main.js'
            }
        }
    });

    grunt.registerTask('server', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'open', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
            'concurrent:server',
            'autoprefixer',
            'connect:livereload',
            'open',
            'watch'
        ]);
    });

    grunt.registerTask('test', [
        'clean:server',
        'concurrent:test',
        'autoprefixer',
        'connect:test',
        'mocha'
    ]);

    grunt.registerTask('build', [
        'clean:dist',
        'useminPrepare',
        'concurrent:dist',
        'autoprefixer',
        'requirejs',
        'concat',
        'cssmin',
        'uglify',
        'modernizr',
        'copy:dist',
        'rev',
        'usemin'
    ]);

    grunt.registerTask('default', [
        'jshint',
        'test',
        'build'
    ]);
};

最佳答案

除了为 PG 3 推荐的内容之外,确实没有最佳实践。对于多个客户端,您可能需要修改您的 gruntjs。这是我的项目结构,其中 Assets 文件夹包含不同客户的数据:

enter image description here

这是我的 gruntjs 文件。它使用 ImageMagik 创建所有必要的启动器图标。为无线安装构建和部署。你明白了……

/***
 * Package script for MobileStore
 ***/

'use strict';

// require package.json:
/*
{
  "name": "MobileStore",
  "version": "1.0.1",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-jshint": "~0.6.0",
    "grunt-contrib-clean": "~0.4.1",
    "grunt-contrib-copy": "~0.4.1",
    "grunt-contrib-concat": "~0.3.0",
    "grunt-exec": "~0.4.2",
    "grunt-string-replace": "~0.2.4",
    "grunt-image-resize": "~0.2.0"
  }
}
*/
module.exports = function(grunt) {
    var isMacOS = grunt.file.isDir('/etc');

    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var myConfig = {
        dest: 'out/',
        platforms: ['ios', 'android'], 
        chains: [11,52,75,119,129,224,229,235],
        chainConfig: {},
        baseDir: __dirname + '/'
    };
    var chainid = grunt.option('chainid');
    if (chainid) {
        myConfig.chains = [chainid];
    }

    // set up grunt
    var gruntConfig = {
        clean: {
          build: ['out', 'beta-assets']
        },
        copy: {},
        exec: {},
        "string-replace": {},
        image_resize: {}
    };

    // first thing to do is clean
    var packageConfig = ['clean'];

    // duplicate source to the chain
    // copy from platforms/(android/ios) to out/chainid/(android/ios)
    myConfig.chains.forEach(function(chain) {
        myConfig.platforms.forEach(function(platform) {
            var key = 'setup_' + platform + chain;

            // any platform is fine, we're just preping chainConfig
            if (platform == 'android')
            {
                myConfig.chainConfig[chain] = require('./YourCompany.Mobile/assets/' + chain + '/build.json');
            }

            gruntConfig.copy[key] = {
                files: [
                  {
                    expand: true,
                    cwd: 'YourCompany.Mobile/platforms/' + platform + '/', 
                    src: ['./**'], 
                    dest: 'out/' + chain + '/' + platform + '/'
                  }
                ]
            };

            packageConfig.push('copy:' + key);
        });
    });

    // override the device resource (icon, splash, etc..)
    // copy from assets/chainid/device/(android/ios) to out/chainid/(android/ios)
    myConfig.chains.forEach(function(chain) {
        myConfig.platforms.forEach(function(platform) {
            var key = 'device_resource_' + platform + chain;
            var srcArt = 'YourCompany.Mobile/assets/' + chain + '/device/AndroidArtwork.png';

            var dest = 'out/' + chain + '/' + platform + '/MobileStore/';
            if (platform == 'android') 
            {
                dest += 'res/';
            }
            else if (platform == 'ios') {
                dest += 'MobileStore/';
            }

            gruntConfig.copy[key] = {
                files: [
                  {
                    expand: true,
                    cwd: 'YourCompany.Mobile/assets/' + chain + '/device/' + platform + '/', 
                    src: ['./**'], 
                    dest: dest
                  }
                ]
            };

            packageConfig.push('copy:' + key);

            // do image manipulations
            // Use AnroidArtwork.png
            if (platform == 'android') {
                gruntConfig.image_resize[key + '_36'] = {
                        options: {
                            width: 36,     
                            height: 36,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest  + 'drawable-ldpi/icon.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_36');

                gruntConfig.image_resize[key + '_48'] = {
                        options: {
                            width: 48, 
                            height: 48,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest  + 'drawable-mdpi/icon.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_48');

                gruntConfig.image_resize[key + '_72'] = {
                        options: {
                            width: 72, 
                            height: 72,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest  + 'drawable-hdpi/icon.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_72');

                gruntConfig.image_resize[key + '_96'] = {
                        options: {
                            width: 96,  
                            height: 96,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest  + 'drawable-xhdpi/icon.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_96');

                gruntConfig.image_resize[key + '_default'] = {
                        options: {
                            width: 96,  
                            height: 96,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest + 'drawable/icon.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_default');
            }
            else if (platform == 'ios') {
                gruntConfig.image_resize[key + '_57'] = {
                        options: {
                            width: 57,  
                            height: 57,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest + 'Resources/icons/Icon.png'
                        }]
                };

                packageConfig.push('image_resize:' + key + '_57');

                gruntConfig.image_resize[key + '_114'] = {
                        options: {
                            width: 114,  
                            height: 114,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest + 'Resources/icons/Icon@2x.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_114');

                gruntConfig.image_resize[key + '_72'] = {
                        options: {
                            width: 72, 
                            height: 72,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest + 'Resources/icons/Icon-72.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_72');

                gruntConfig.image_resize[key + '_144'] = {
                        options: {
                            width: 144,  
                            height: 144,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest + 'Resources/icons/Icon-72@2x.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_144');

                gruntConfig.image_resize[key + '_29'] = {
                        options: {
                            width: 29,  
                            height: 29,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest + 'Resources/icons/Icon-Small.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_29');

                gruntConfig.image_resize[key + '_58'] = {
                        options: {
                            width: 58, 
                            height: 58,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest  + 'Resources/icons/Icon-Small@2x.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_58');

                gruntConfig.image_resize[key + '_50'] = {
                        options: {
                            width: 50,  
                            height: 50,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest  + 'Resources/icons/Icon-Small-50.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_50');

                gruntConfig.image_resize[key + '_100'] = {
                        options: {
                            width: 100,   
                            height: 100,
                            overwrite: true
                        },
                        files: [{
                            src: srcArt,
                            dest: dest  + 'Resources/icons/Icon-Small-50@2x.png'
                        }]
                };
                packageConfig.push('image_resize:' + key + '_100');

                gruntConfig.image_resize[key + '_1024'] = {
                    options: {
                        width: 1024,
                        height: 1024,
                        overwrite: true,
                        upscale: true
                    },
                    files: [{
                        src: srcArt,
                        dest: dest + 'Resources/iTunesArtwork'
                    }]
                };
                packageConfig.push('image_resize:' + key + '_1024');

                // setup images for ota deploy
                gruntConfig.image_resize[key + '_512x'] = {
                    options: {
                        width: 512,
                        height: 512,
                        overwrite: true,
                        upscale: true
                    },
                    files: [{
                        src: srcArt,
                        dest: dest + '../iTunesArtwork.png'
                    }]
                };
                packageConfig.push('image_resize:' + key + '_512x');

                gruntConfig.image_resize[key + '_57x'] = {
                    options: {
                        width: 57,
                        height: 57,
                        overwrite: true
                    },
                    files: [{
                        src: srcArt,
                        dest: dest + '../Icon.png'
                    }]
                };
                packageConfig.push('image_resize:' + key + '_57x');
            }
        });
    });

    // copy assets to www folder
    // copy from www to out/chainid/...
    myConfig.chains.forEach(function(chain) {
        myConfig.platforms.forEach(function(platform) {
            var key = 'content_' + platform + chain;
            var dest = 'out/' + chain + '/' + platform + '/MobileStore/';
            if (platform == 'android') 
            {
                dest += 'assets/www/';
            }
            else if (platform == 'ios') {
                dest += 'www/';
            }

            gruntConfig.copy[key] = {
                files: [
                  {
                    expand: true,
                    cwd: 'YourCompany.Mobile/www/', 
                    src: ['./**'], 
                    dest: dest
                  }
                ]
            };

            packageConfig.push('copy:' + key);
        });
    });

    // copy assets override
    // copy from assets/chainid/www to out/chainid/...
    myConfig.chains.forEach(function(chain) {
        myConfig.platforms.forEach(function(platform) {
            var key = 'content_override_' + platform + chain;
            var dest = 'out/' + chain + '/' + platform + '/MobileStore/';
            if (platform == 'android') 
            {
                dest += 'assets/www/';
            }
            else if (platform == 'ios') {
                dest += 'www/';
            }

            gruntConfig.copy[key] = {
                files: [
                  {
                    expand: true,
                    cwd: 'YourCompany.Mobile/assets/' + chain + '/www/', 
                    src: ['./**'], 
                    dest: dest
                  }
                ]
            };

            packageConfig.push('copy:' + key);
        });
    });

    // copy phonegap merges
    // copy from merges to out/chainid/...
    myConfig.chains.forEach(function(chain) {
        myConfig.platforms.forEach(function(platform) {
            var key = 'phonegap_override_' + platform + chain;
            var dest = 'out/' + chain + '/' + platform + '/MobileStore/';
            if (platform == 'android') 
            {
                dest += 'assets/www/';
            }
            else if (platform == 'ios') {
                dest += 'www/';
            }

            gruntConfig.copy[key] = {
                files: [
                  {
                    expand: true,
                    cwd: 'YourCompany.Mobile/merges/' + platform, 
                    src: ['./**'], 
                    dest: dest
                  }
                ]
            };

            packageConfig.push('copy:' + key);
        });
    });

    // doing beta assets deployment
    myConfig.chains.forEach(function (chain) {
        var key = 'content_beta_assets_' + chain;
        var src = 'out/' + chain + '/ios/MobileStore/www/';

        gruntConfig.copy[key] = {
            files: [
              {
                  expand: true,
                  cwd: src,
                  src: ['./**'],
                  dest: 'beta-assets/' + chain + '/www/'
              }
            ]
        };

        packageConfig.push('copy:' + key);

        // override cordova file
        gruntConfig.copy[key + '_pg'] = {
            files: [
              {
                  expand: true,
                  cwd: 'YourCompany.Mobile/www/',
                  src: ['./cordova.js'],
                  dest: 'beta-assets/' + chain + '/www/'
              }
            ]
        };

        packageConfig.push('copy:' + key + '_pg');

    });

    // doing android(ant) build
    myConfig.chains.forEach(function (chain) {
        var key = 'android_build_' + chain;

        var dest = 'out/' + chain + '/android/MobileStore/';
        var destFolder = './out/' + chain + '/';
        // use previous chainConfig to perform text replace
        gruntConfig["string-replace"][key + '_prep'] = {
            files: [
                  {
                    expand: true,
                    cwd: 'out/' + chain + '/', 
                    src: ['./**/**.java', './**/**.xml', './**/**.plist', './**/**.m'],
                    dest: 'out/' + chain + '/'
                  }
            ],
            options: {
              replacements: [
                {
                    pattern: /(net.yourcompany.MobileStore)+/ig,
                    replacement: myConfig.chainConfig[chain].id
                },
                {
                    pattern: /(AppleBundleSeedID)+/ig,
                    replacement: myConfig.chainConfig[chain].AppleBundleSeedID
                },
                {   pattern: '<string name="app_name">MobileStore</string>',
                    replacement: '<string name="app_name">' + myConfig.chainConfig[chain].ApplicationName + '</string>'
                }
              ]
            }
        };

        packageConfig.push('string-replace:' + key + '_prep');

        // do build
        gruntConfig.exec[key] = {
            cmd: 'ant clean && ant debug',
            cwd: dest,
            env: process.env
        };

        packageConfig.push('exec:' + key);

    });

    // doing xcode build
    myConfig.chains.forEach(function(chain) {
        var key = 'ios_build_' + chain;
        var chainConfig = myConfig.chainConfig[chain];
        var dest = myConfig.baseDir + 'out/' + chain + '/ios/MobileStore/';
        var buildDir = dest + 'Build/Products/Release-iphoneos/';
        var commandStart = 'export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/opt/local/bin:/opt/local/sbin:/sbin:/usr/local/bin:/Users/Shared/ImageMagick-6.8.6:$PATH" &&'
        var command = 'chmod 777 dobuild && ./dobuild "' + chainConfig.AppleProductName + '" ' + chain + ' ' + process.env.BUILD_NUMBER + ' "' + chainConfig.AppleBundleSeedID + '.' + chainConfig.id + '"';
        grunt.log.debug('ios build:' + command);

        if (isMacOS) {
            gruntConfig.exec[key] = {
                cmd: command,
                cwd: dest,
                exitCode: 0
            };
            packageConfig.push('exec:' + key);
        }

        // prep apk for deployment
        gruntConfig.copy['android_build_' + chain + '_apk'] = {
            options: {
                processContent: false
            },
            files: [
                {
                    expand: true,
                    flatten: true,
                    src: ['out/' + chain + '/android/MobileStore/bin/MobileStore-debug.apk'],
                    dest: 'beta-assets/' + chain + '/',
                    filter: 'isFile'
                }
            ]
        };

        packageConfig.push('copy:' + 'android_build_' + chain + '_apk');

        // prep ipa for ios deploy
        gruntConfig.copy['ios_build_' + chain + '_ipa'] = {
            options: {
                processContent: false
            },
            files: [
                {
                    expand: true,
                    flatten: true,
                    src: ['out/' + chain + '/ios/MobileStore/Build/**.ipa'],
                    dest: 'beta-assets/' + chain + '/',
                    filter: 'isFile'
                }
            ]
        };

        packageConfig.push('copy:' + 'ios_build_' + chain + '_ipa');

        // drop plist
        gruntConfig.copy['ios_build_' + chain + '_plist'] = {
            options: {
                processContent: false
            },
            files: [
                {
                    expand: true,
                    flatten: true,
                    src: ['out/' + chain + '/ios/MobileStore/Build/**.plist'],
                    dest: 'beta-assets/' + chain + '/',
                    filter: 'isFile'
                }
            ]
        };

        packageConfig.push('copy:' + 'ios_build_' + chain + '_plist');

        // drop html
        gruntConfig.copy['ios_build_' + chain + '_html'] = {
            options: {
                processContent: false
            },
            files: [
                {
                    expand: true,
                    flatten: true,
                    src: ['out/' + chain + '/ios/MobileStore/Build/install.html'],
                    dest: 'beta-assets/' + chain + '/',
                    filter: 'isFile'
                }
            ]
        };

        packageConfig.push('copy:' + 'ios_build_' + chain + '_html');

        // drop png
        gruntConfig.copy['ios_build_' + chain + '_png'] = {
            options: {
                processContent: false
            },
            files: [
                {
                    expand: true,
                    flatten: true,
                    src: ['out/' + chain + '/ios/MobileStore/*.png'],
                    dest: 'beta-assets/' + chain + '/',
                    filter: 'isFile'
                }
            ]
        };

        packageConfig.push('copy:' + 'ios_build_' + chain + '_png');
    });


    grunt.initConfig(gruntConfig);
    grunt.registerTask('package', packageConfig);

    // Default task.
    grunt.registerTask('default', 'package');
};

基本上,它会删除所有 native 并合并到 out/clientorchainid 文件夹中,以便为每个客户端进行构建。然后将构建结果复制到 beta-assets/clientorchainid 文件夹中,为远程部署做准备。

关于javascript - 使用 Grunt (Yeoman) 的多个构建文件夹(多个客户端、多任务、多个目标),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18449591/

相关文章:

javascript - 鼠标悬停时的 FullCalendar 事件给出 jQuery 错误

javascript - 如何更新json数组中的特定值

javascript - 不断将数据(blob)加载到对node.js的POST请求中

node.js - 检测可观察量何时连续两次发出相同的值

ios - 在 Cordova 插件中以编程方式添加 IOS 功能

javascript - 如何将图像与更新 JSON/API key 数据链接并将其显示到 HTML 网页

javascript - 动态添加td和tr onclick HTML JQUERY

javascript - Mongoose find() 使用锁存器在 for 循环内调用

javascript - 无法导航到 jquerymobile/phonegap 中动态添加的页面

jquery-mobile - 寻找与PhoneGap兼容的jQuery移动图像幻灯片