我试图使用Grunt作为我的网络应用程序的构建工具。

我想至少有两个设置:

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

所以我的index.html看起来是这样的:

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

2生产设置-加载我的脚本缩小和连接在一个文件,

根据index.html:

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

问题是,当我运行grunt dev或grunt prod时,我如何让grunt根据配置创建这些index.html ?

或者也许我在错误的方向上挖掘,它会更容易总是生成MyApp-all.min.js,但把它里面要么我所有的脚本(连接)或加载器脚本异步加载这些脚本从单独的文件?

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


当前回答

考虑processhtml。它允许为构建定义多个“目标”。注释用于有条件地从HTML中包含或排除材料:

<!-- build:js:production js/app.js -->
...
<!-- /build -->

就变成了

<script src="js/app.js"></script>

它甚至声称可以做这样漂亮的事情(参见README):

<!-- build:[class]:dist production -->
<html class="debug_mode">
<!-- /build -->

<!-- class is changed to 'production' only when the 'dist' build is executed -->
<html class="production">

其他回答

我不喜欢这里的解决方案(包括我之前给出的),原因如下:

投票最多的答案的问题是,当你添加/重命名/删除一个JS文件时,你必须手动同步脚本标签列表。 接受的答案的问题是你的JS文件列表不能有模式匹配。这意味着你必须在Gruntfile中手动更新它。

我已经找到了解决这两个问题的方法。我已经设置了grunt任务,以便每次添加或删除文件时,都会自动生成脚本标记来反映该任务。这样,当你添加/删除/重命名JS文件时,你不需要修改你的html文件或grunt文件。

为了总结它是如何工作的,我有一个带有脚本标记变量的html模板。我使用https://github.com/alanshaw/grunt-include-replace填充该变量。在开发模式下,该变量来自我所有JS文件的通配符模式。当添加或删除JS文件时,监视任务会重新计算这个值。

现在,要在dev或prod模式中获得不同的结果,只需用不同的值填充该变量。下面是一些代码:

var jsSrcFileArray = [
    'src/main/scripts/app/js/Constants.js',
    'src/main/scripts/app/js/Random.js',
    'src/main/scripts/app/js/Vector.js',
    'src/main/scripts/app/js/scripts.js',
    'src/main/scripts/app/js/StatsData.js',
    'src/main/scripts/app/js/Dialog.js',
    'src/main/scripts/app/**/*.js',
    '!src/main/scripts/app/js/AuditingReport.js'
];

var jsScriptTags = function (srcPattern, destPath) {
    if (srcPattern === undefined) {
        throw new Error("srcPattern undefined");
    }
    if (destPath === undefined) {
        throw new Error("destPath undefined");
    }
    return grunt.util._.reduce(
        grunt.file.expandMapping(srcPattern, destPath, {
            filter: 'isFile',
            flatten: true,
            expand: true,
            cwd: '.'
        }),
        function (sum, file) {
            return sum + '\n<script src="' + file.dest + '" type="text/javascript"></script>';
        },
        ''
    );
};

...

grunt.initConfig({

    includereplace: {
        dev: {
            options: {
                globals: {
                    scriptsTags: '<%= jsScriptTags(jsSrcFileArray, "../../main/scripts/app/js")%>'
                }
            },
            src: [
                'src/**/html-template.html'
            ],
            dest: 'src/main/generated/',
            flatten: true,
            cwd: '.',
            expand: true
        },
        prod: {
            options: {
                globals: {
                    scriptsTags: '<script src="app.min.js" type="text/javascript"></script>'
                }
            },
            src: [
                'src/**/html-template.html'
            ],
            dest: 'src/main/generatedprod/',
            flatten: true,
            cwd: '.',
            expand: true
        }

...

    jsScriptTags: jsScriptTags

jsSrcFileArray是典型的grunt文件替换模式。jsScriptTags接受jsSrcFileArray,并将它们与两侧的脚本标记连接在一起。destPath是我想在每个文件上使用的前缀。

下面是HTML的样子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Example</title>

</head>

<body>    
@@scriptsTags
</body>
</html>

现在,正如您在配置中看到的,当它在prod模式下运行时,我将该变量的值生成为一个硬编码的脚本标记。在dev模式下,该变量将展开为如下值:

<script src="../../main/scripts/app/js/Constants.js" type="text/javascript"></script>
<script src="../../main/scripts/app/js/Random.js" type="text/javascript"></script>
<script src="../../main/scripts/app/js/Vector.js" type="text/javascript"></script>
<script src="../../main/scripts/app/js/StatsData.js" type="text/javascript"></script>
<script src="../../main/scripts/app/js/Dialog.js" type="text/javascript"></script>

如果你有任何问题请告诉我。

PS:对于我想在每个客户端JS应用中做的事情来说,这是一个疯狂的代码量。我希望有人能把它变成一个可重用的插件。也许有一天我会的。

考虑processhtml。它允许为构建定义多个“目标”。注释用于有条件地从HTML中包含或排除材料:

<!-- build:js:production js/app.js -->
...
<!-- /build -->

就变成了

<script src="js/app.js"></script>

它甚至声称可以做这样漂亮的事情(参见README):

<!-- build:[class]:dist production -->
<html class="debug_mode">
<!-- /build -->

<!-- class is changed to 'production' only when the 'dist' build is executed -->
<html class="production">

grunt-bake是一个很棒的grunt脚本,可以在这里工作。我在JQM自动构建脚本中使用了它。

https://github.com/imaginethepoet/autojqmphonegap

看看我的呼噜声。咖啡文件:

bake:
    resources: 
      files: "index.html":"resources/custom/components/base.html"

这将查看base.html中的所有文件,并将它们吸收到创建index.html中,这对于多页面应用(phonegap)非常有用。这让开发变得更容易,因为所有的开发者都不需要开发一个很长的单页应用(防止大量冲突)。相反,您可以将页面拆分,处理较小的代码块,并使用watch命令编译成整个页面。

Bake从base.html中读取模板,并在watch中注入组件html页面。

<!DOCTYPE html>

jQuery移动演示

app.initialize ();

<body>
    <!--(bake /resources/custom/components/page1.html)-->
    <!--(bake /resources/custom/components/page2.html)-->
    <!--(bake /resources/custom/components/page3.html)-->
</body>

你可以更进一步,在页面中为“菜单”、“弹出窗口”等添加注入,这样你就可以真正地将页面分解成更小的可管理组件。

这个名为scriptlinker的任务看起来是在开发模式中添加脚本的简单方法。您可以先运行连接任务,然后以prod模式将其指向连接的文件。

grunt-dom-munger使用CSS选择器读取和操作HTML。例如,从html中读取标签。删除节点、添加节点等等。

你可以使用grunt-dom-munger读取所有由index.html链接的JS文件,丑化它们,然后再次使用grunt-dom-munger修改index.html,只链接最小化的JS文件