让 Grunt 为不同的设置生成索引.html

我正在尝试使用Grunt作为我的web应用程序的构建工具。

我希望至少有两个设置:

I. 开发设置 - 从单独的文件加载脚本,无需串联,

所以我的索引.html看起来像这样:

<!DOCTYPE html>
<html>
    <head>
        <script src="js/module1.js" />
        <script src="js/module2.js" />
        <script src="js/module3.js" />
        ...
    </head>
    <body></body>
</html>

II.生产设置 - 加载我的脚本缩小和串联在一个文件中,

相应地,索引.html:

<!DOCTYPE html>
<html>
    <head>
        <script src="js/MyApp-all.min.js" />
    </head>
    <body></body>
</html>

问题是,我如何使 grunt 生成这些索引.html这取决于我运行 grunt devgrunt prod 时的配置?

或者,也许我正在朝着错误的方向挖掘,并且总是生成会更容易,但是要么放在里面,要么放在里面,要么放在里面,从单独的文件异步加载这些脚本?MyApp-all.min.js

伙计们,你们是怎么做到的?


答案 1

我最近发现了这些Grunt兼容的任务:v0.4.0

以下是来自我的.Gruntfile.js

环境电压设置:

env : {

    options : {

        /* Shared Options Hash */
        //globalOption : 'foo'

    },

    dev: {

        NODE_ENV : 'DEVELOPMENT'

    },

    prod : {

        NODE_ENV : 'PRODUCTION'

    }

},

预处理:

preprocess : {

    dev : {

        src : './src/tmpl/index.html',
        dest : './dev/index.html'

    },

    prod : {

        src : './src/tmpl/index.html',
        dest : '../<%= pkg.version %>/<%= now %>/<%= ver %>/index.html',
        options : {

            context : {
                name : '<%= pkg.name %>',
                version : '<%= pkg.version %>',
                now : '<%= now %>',
                ver : '<%= ver %>'
            }

        }

    }

}

任务:

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

grunt.registerTask('dev', ['jshint', 'env:dev', 'clean:dev', 'preprocess:dev']);

grunt.registerTask('prod', ['jshint', 'env:prod', 'clean:prod', 'uglify:prod', 'cssmin:prod', 'copy:prod', 'preprocess:prod']);

在模板文件中(例如):/src/tmpl/index.html

<!-- @if NODE_ENV == 'DEVELOPMENT' -->

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
    <script src="../src/js/foo1.js"></script>
    <script src="../src/js/foo2.js"></script>
    <script src="../src/js/jquery.blah.js"></script>
    <script src="../src/js/jquery.billy.js"></script>
    <script src="../src/js/jquery.jenkins.js"></script>

<!-- @endif -->

<!-- @if NODE_ENV == 'PRODUCTION' -->

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

    <script src="http://cdn.foo.com/<!-- @echo name -->/<!-- @echo version -->/<!-- @echo now -->/<!-- @echo ver -->/js/<!-- @echo name -->.min.js"></script>

<!-- @endif -->

我确信我的设置与大多数人不同,上述内容的有用性将取决于您的情况。对我来说,虽然这是一个很棒的代码,但Yeoman grunt-usemin比我个人需要的更强大。

注意:我今天刚刚发现了上面列出的任务,所以我可能缺少一个功能和/或我的流程可能会改变。就目前而言,我喜欢grunt-preprocessgrunt-env必须提供的简单性和功能。:)


2014年1月更新:

受到反对票的激励...

当我发布这个答案时,Grunt没有多少选择可以提供满足我需求的解决方案。现在,几个月后,我想有更多的选择可能比我在这里发布的内容更好。虽然我个人仍然使用并喜欢使用这种技术进行构建,但我要求未来的读者花时间阅读给出的其他答案并研究所有选项。如果您找到更好的解决方案,请在此处发布您的答案。0.4.x

2014年2月更新:

我不确定它是否对任何人有任何帮助,但我在GitHub上创建了这个演示存储库,它使用我上面概述的技术显示了一个完整的(和更复杂的设置)。


答案 2

我想出了我自己的解决方案。还没有打磨,但我认为我会朝着这个方向前进。

在essense中,我使用grunt.template.process()从模板生成我的,该模板分析当前配置并生成我的原始源文件列表或链接到具有缩小代码的单个文件。下面的示例适用于 js 文件,但相同的方法可以扩展到 css 和任何其他可能的文本文件。index.html

咕噜.js

/*global module:false*/
module.exports = function(grunt) {
    var   // js files
        jsFiles = [
              'src/module1.js',
              'src/module2.js',
              'src/module3.js',
              'src/awesome.js'
            ];

    // Import custom tasks (see index task below)
    grunt.loadTasks( "build/tasks" );

    // Project configuration.
    grunt.initConfig({
      pkg: '<json:package.json>',
      meta: {
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
          '<%= grunt.template.today("yyyy-mm-dd") %> */'
      },

      jsFiles: jsFiles,

      // file name for concatenated js
      concatJsFile: '<%= pkg.name %>-all.js',

      // file name for concatenated & minified js
      concatJsMinFile: '<%= pkg.name %>-all.min.js',

      concat: {
        dist: {
            src: ['<banner:meta.banner>'].concat(jsFiles),
            dest: 'dist/<%= concatJsFile %>'
        }
      },
      min: {
        dist: {
        src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
        dest: 'dist/<%= concatJsMinFile %>'
        }
      },
      lint: {
        files: ['grunt.js'].concat(jsFiles)
      },
      // options for index.html builder task
      index: {
        src: 'index.tmpl',  // source template file
        dest: 'index.html'  // destination file (usually index.html)
      }
    });


    // Development setup
    grunt.registerTask('dev', 'Development build', function() {
        // set some global flags that all tasks can access
        grunt.config('isDebug', true);
        grunt.config('isConcat', false);
        grunt.config('isMin', false);

        // run tasks
        grunt.task.run('lint index');
    });

    // Production setup
    grunt.registerTask('prod', 'Production build', function() {
        // set some global flags that all tasks can access
        grunt.config('isDebug', false);
        grunt.config('isConcat', true);
        grunt.config('isMin', true);

        // run tasks
        grunt.task.run('lint concat min index');
    });

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

索引.js(索引任务):

module.exports = function( grunt ) {
    grunt.registerTask( "index", "Generate index.html depending on configuration", function() {
        var conf = grunt.config('index'),
            tmpl = grunt.file.read(conf.src);

        grunt.file.write(conf.dest, grunt.template.process(tmpl));

        grunt.log.writeln('Generated \'' + conf.dest + '\' from \'' + conf.src + '\'');
    });
}

最后是 index.tmpl,其中包含生成逻辑:

<doctype html>
<head>
<%
    var jsFiles = grunt.config('jsFiles'),
        isConcat = grunt.config('isConcat');

    if(isConcat) {
        print('<script type="text/javascript" src="' + grunt.config('concat.dist.dest') + '"></script>\n');
    } else {
        for(var i = 0, len = jsFiles.length; i < len; i++) {
            print('<script type="text/javascript" src="' + jsFiles[i] + '"></script>\n');
        }
    }
%>
</head>
<html>
</html>

UPD。发现基于 grunt 的 Yeoman 有一个内置的 usemin 任务,该任务与 Yeoman 的构建系统集成。它从 index 的开发版本中的信息生成 index.html的生产版本.html以及其他环境设置。有点复杂,但看起来很有趣。