我试图用步兵作为我的web应用构建工具。
我想至少有两个设置:
一,发展设置 -从单独的文件加载脚本,无连接,
所以我的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>
II。 产品设置 -载入我的剧本精缩和在一个文件中串联,
将以index.html因此:
<!DOCTYPE html>
<html>
<head>
<script src="js/MyApp-all.min.js" />
</head>
<body></body>
</html>
现在的问题是, 如何才能让咕噜使取决于配置这些的index.html的,当我运行grunt dev
或grunt prod
?
或者,也许我挖错了方向,它会更容易总是生成MyApp-all.min.js
而是把它里面要么所有我的脚本(串联)或异步加载从单独的文件这些脚本加载器脚本?
你怎么做,伙计们?
Answer 1:
我最近发现了这些咕噜v0.4.0
兼容的任务:
咕噜,预处理
围绕预处理NPM模块咕噜任务。
咕噜-ENV
咕噜任务,为今后的任务自动化环境的配置。
以下是我的片段Gruntfile.js
。
ENV设置:
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 -->
我敢肯定,我的设置是比大多数人不同,和上述的效用取决于你的情况。 对于我来说,虽然它的代码真棒位,自耕农咕噜-usemin是一个更强大的比我个人的需要。
注: 我今天发现上面列出的任务,所以我可能会丢失功能和/或我的过程中可能会改变的道路。 现在,我爱的简单性和功能是咕噜,预处理和咕噜-ENV所提供的。 :)
2014年1月更新:
通过下投票的驱使。
当我张贴了这个答案有不咕噜许多选项0.4.x
是提供对于我的工作需要的解决方案。 现在,几个月后,我猜想,有更多的选择,在那里, 可能比我在这里贴好。 虽然我还是个人使用,并享有使用,该技术为我建立的,我问未来的读者需要阅读给出其他答案并研究所有选项的时间。 如果你找到一个更好的解决办法,请在这里发表您的答案。
2014年2月更新:
我不知道这是否是对任何人的帮助,但我已经创建了GitHub上这个演示存储库 ,显示了完整的(和更复杂的设置)使用该技术(S)我先前提到。
Answer 2:
我拿出自己的解决方案。 不用抛光,但是我想我会朝着这个方向移动。
从根本上,我使用grunt.template.process()来生成我index.html
从分析当前配置和生产无论是我的原始源文件或链接列表与缩小的代码的单个文件的模板。 下面的例子是js文件,但是同样的方法可以扩展到CSS和其他任何可能的文本文件。
grunt.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');
};
index.js (the index task)
:
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。 发现了约曼 ,这是基于咕噜,有一个内置的usemin与约曼的构建系统集成任务。 它产生的index.html从信息的index.html的开发版本,以及其他环境设置的量产版。 复杂的,但有趣的位来看待。
Answer 3:
我不喜欢这里的解决方案(包括我以前给一个 )和这里的原因:
- 这个问题的投票最高的答案是,你必须手动同步,当你添加/重命名/删除JS文件脚本标签的列表。
- 这个问题接受的答案是,你的JS文件列表不能有模式匹配。 这意味着你得用手在Gruntfile更新它。
我已经想通了如何解决这两个问题。 我建立了我的咕噜任务让每一个文件被添加或删除时,标签自动获取生成的脚本,以反映。 这样一来, 就不需要修改HTML文件或在添加/删除/重命名你的JS文件的咕噜文件 。
总结如何工作的,我有对脚本标记的变量的HTML模板。 我用https://github.com/alanshaw/grunt-include-replace来填充变量。 在开发模式下,该变量来自于我所有的JS文件的文件名匹配模式。 手表任务重新计算时JS文件添加或移除该值。
现在,为了获得开发或督促模式不同的结果,您只需填充与不同的值的变量。 下面是一些代码:
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
是典型的咕噜的文件名匹配模式。 jsScriptTags
采取jsSrcFileArray
并连同连接它们script
两侧的标签。 destPath
是我想对每个文件的前缀。
这里有什么HTML的样子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Example</title>
</head>
<body>
@@scriptsTags
</body>
</html>
现在,你可以在配置看,我产生变量作为一个硬编码的值script
时,它的运行标签prod
模式。 在开发者模式,这个变量将扩大到这样一个值:
<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做。 我希望有人能够把它变成一个可重复使用的插件。 也许我会买一些日子。
Answer 4:
我一直在问自己了,而同样的问题,我觉得这咕噜插件可以被配置为你想要的东西: https://npmjs.org/package/grunt-targethtml 。 它实现了有条件的html标签,这取决于咕噜目标。
Answer 5:
我一直在寻找一种更简单,直接的解决方案,所以我结合这个问题的答案:
如何放置如果gruntfile.js else块
并提出了以下简单步骤:
- 保持你的索引文件的两个版本,你列出他们的名字指数development.html和索引prodoction.html。
请使用您Gruntfile.js的CONCAT /复制块以下逻辑为您的index.html文件:
concat: { index: { src : [ (function() { if (grunt.option('Release')) { return 'views/index-production.html'; } else { return 'views/index-development.html'; } }()) ], dest: '<%= distdir %>/index.html', ... }, ... },
运行“咕噜--release”选择指数production.html文件,并留下关闭标志有开发版本。
没有新的插件添加或配置也没有新的咕噜任务。
Answer 6:
这个名为咕噜任务scriptlinker看起来像一个简单的方法来在开发模式中添加脚本。 你也许可以先运行一个CONCAT任务,然后在PROD模式下,它指向您的连结文件。
Answer 7:
咕噜-DOM-芒格读取和使用CSS选择器操纵HTML。 防爆。 读你的HTML标签。 删除节点,添加节点,等等。
您可以使用咕噜-DOM-芒格读取由您的index.html链接所有的JS文件,丑化他们,然后用咕噜-DOM-芒格再次修改您的index.html只链接缩小的JS
Answer 8:
我发现了一个咕噜叫插件咕噜-DEV-PROD-开关。 它所做的是注释掉某些块看起来基于传递给咕噜(虽然它限制你到dev,prod和测试)的--env选项。
一旦你设置它,因为它解释在这里 ,你可以运行的例子:
grunt serve --env=dev
,并且它是所有注释其由缠绕的块
<!-- env:test/prod -->
your code here
<!-- env:test/prod:end -->
它将取消注释出它们通过包裹块
<!-- env:dev -->
your code here
<!-- env:dev:end -->
它也适用于JavaScript,我用它来设置正确的IP地址连接到我的后端API。 该块只是改变
/* env:dev */
your code here
/* env:dev:end */
对你来说,这将是这么简单:
<!DOCTYPE html>
<html>
<head>
<!-- env:dev -->
<script src="js/module1.js" />
<script src="js/module2.js" />
<script src="js/module3.js" />
...
<!-- env:dev:end -->
<!-- env:prod -->
<script src="js/MyApp-all.min.js" />
...
<!-- env:prod:end -->
</head>
<body></body>
</html>
Answer 9:
咕噜烘烤是一个梦幻般的咕噜脚本,将工作的伟大在这里。 我用它在我的JQM自动生成脚本。
https://github.com/imaginethepoet/autojqmphonegap
看看我的grunt.coffee文件:
bake:
resources:
files: "index.html":"resources/custom/components/base.html"
这看起来在base.html文件中的所有文件,并在吮吸他们创造的index.html作品梦幻般的多页的应用程序(PhoneGap的)。 这使得开发变得更容易,因为所有的开发者都不能在一个长单页的应用程序(防止大量冲突签入)工作。 相反,你可以打破了网页和对工作的代码更小的块,并用watch命令编译成完整的页面。
烘烤读取base.html文件模板,并注入值班的组件的HTML页面。
<!DOCTYPE html>
jQuery Mobile的演示
app.initialize();
<body>
<!--(bake /resources/custom/components/page1.html)-->
<!--(bake /resources/custom/components/page2.html)-->
<!--(bake /resources/custom/components/page3.html)-->
</body>
您可以更进一步借此在您的网页添加为注射“菜单”“弹出窗口”等这样你就可以真正打破页面分成更小的管理的组成部分。
Answer 10:
使用wiredep的组合https://github.com/taptapship/wiredep和usemin https://github.com/yeoman/grunt-usemin才能有咕噜承担这些任务的照顾。 Wiredep将一次添加你的依赖一个脚本文件,usemin将它们全部连接成用于生产单个文件。 然后可以用只是一些HTML注释来完成。 例如,我的亭子包自动包含并添加到当我运行HTML bower install && grunt bowerInstall
:
<!-- build:js /scripts/vendor.js -->
<!-- bower:js -->
<!-- endbower -->
<!-- endbuild -->
Answer 11:
考虑processhtml 。 它允许多个“指标”定义的基础之上。 注释用于有条件地包括或从HTML排除材料:
<!-- build:js:production js/app.js -->
...
<!-- /build -->
变
<script src="js/app.js"></script>
它甚至声称做漂亮的东西,这样的(见自述 ):
<!-- build:[class]:dist production -->
<html class="debug_mode">
<!-- /build -->
<!-- class is changed to 'production' only when the 'dist' build is executed -->
<html class="production">
Answer 12:
这个答案是不适合菜鸟!
用玉模板...传递变量到玉模板是一个沼泽标准使用情况
我使用的咕噜(咕噜-的contrib玉),但你不必使用咕噜。 只需使用标准NPM玉模块。
如果使用咕噜那么你gruntfile想类似...
jade: {
options: {
// TODO - Define options here
},
dev: {
options: {
data: {
pageTitle: '<%= grunt.file.name %>',
homePage: '/app',
liveReloadServer: liveReloadServer,
cssGruntClassesForHtmlHead: 'grunt-' + '<%= grunt.task.current.target %>'
},
pretty: true
},
files: [
{
expand: true,
cwd: "src/app",
src: ["index.jade", "404.jade"],
dest: "lib/app",
ext: ".html"
},
{
expand: true,
flatten: true,
cwd: "src/app",
src: ["directives/partials/*.jade"],
dest: "lib/app/directives/partials",
ext: ".html"
}
]
}
},
现在,我们可以很容易地访问由咕噜在玉模板传递的数据。
很像由Modernizr的使用方法,我的HTML标签根据传递变量的值而设定的CSS类并且可以基于CSS类是否存在或不存在使用JavaScript逻辑从那里。
这是伟大的,如果采用了棱角分明,因为你可以做NG,如果是包括基于该类是否存在的页面元素。
例如,我可能包括脚本如果类存在...
(例如,我可能包括开发,但不是在生产现场重装脚本)
<script ng-if="controller.isClassPresent()" src="//localhost:35729/livereload.js"></script>
文章来源: Have Grunt generate index.html for different setups