Grunt를 webapp의 빌드 도구로 사용하려고합니다.
적어도 두 가지 설정을 원합니다.
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>
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
모든 스크립트 (연결 된) 또는 별도의 파일에서 해당 스크립트를 비동기 적으로로드하는 로더 스크립트 중 하나를 생성하는 것이 더 쉬울 까요?
어떻게합니까?
답변
최근에 이러한 Grunt v0.4.0
호환 작업을 발견했습니다 .
아래는 내 스 니펫입니다 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 -->
내 설정이 대부분의 사람들과 다를 것이라고 확신하며 위의 유용성은 상황에 따라 다릅니다. 저에게있어, 그것은 아주 멋진 코드이지만 Yeoman grunt-usemin 은 개인적으로 필요한 것보다 더 강력합니다.
참고 : 나는 단지 내가하는 기능이 누락 될 수 있도록, 오늘 위에 나열된 작업을 발견 및 / 또는 내 프로세스가 길을 변경할 수 있습니다. 지금 은 grunt-preprocess 와 grunt-env 가 제공해야하는 단순성 과 기능을 좋아 합니다. 🙂
2014 년 1 월 업데이트 :
다운 투표로 동기 부여 …
이 답변을 게시했을 때 Grunt의 옵션이 많지 않아 0.4.x
내 요구에 맞는 솔루션을 제공했습니다. 이제 개월 후, 나는 거기에 더 많은 옵션이 있음을 추측 할 수있는 내가 여기에 게시 한 것보다 더 나은가. 필자는 개인적으로이 빌드를 위해이 기술을 개인적으로 사용하고 즐겁게 사용 하면서 미래의 독자들에게 주어진 다른 답변을 읽고 모든 옵션을 연구 할 시간을 가지라고 요청합니다. 더 나은 해결책을 찾으면 여기에 답변을 게시하십시오.
2014 년 2 월 업데이트 :
그것이 누군가에게 도움이 될지 확신 할 수 없지만, GitHub 에서 위에서 설명한 기술을 사용하여 완전한 (더 복잡한 설정)을 보여주는 데모 저장소를 만들었습니다 .
답변
나는 내 자신의 해결책을 생각해 냈습니다. 아직 닦지 않았지만 그 방향으로 움직일 것 같습니다.
본질적으로 , grunt.template.process () 를 사용하여 index.html
현재 구성을 분석하고 원본 소스 파일 목록 또는 축소 된 코드가 포함 된 단일 파일에 대한 링크를 생성 하는 템플릿에서 my를 생성 합니다. 아래 예제는 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의 프로덕션 버전을 생성합니다. 조금 정교하지만보기에는 흥미 롭습니다.
답변
나는 여기 ( 이전에 제공 한 솔루션 포함)의 솔루션을 싫어 하며 여기에 이유가 있습니다.
- 가장 높은 투표 응답 의 문제점 은 JS 파일을 추가 / 이름 바꾸기 / 삭제할 때 스크립트 태그 목록을 수동으로 동기화해야한다는 것입니다.
- 허용되는 답변 의 문제점 은 JS 파일 목록에 패턴 일치가 없다는 것입니다. 이것은 Gruntfile에서 직접 업데이트해야한다는 것을 의미합니다.
이 두 가지 문제를 해결하는 방법을 알아 냈습니다. 파일을 추가하거나 삭제할 때마다 스크립트 태그가 자동으로 생성되도록 해당 작업을 설정했습니다. 이런 식으로 JS 파일을 추가 / 제거 / 이름 바꾸기 할 때 html 파일이나 grunt 파일을 수정할 필요가 없습니다 .
그 작동 방식을 요약하기 위해 스크립트 태그 변수가있는 html 템플릿이 있습니다. https://github.com/alanshaw/grunt-include-replace 를 사용 하여 해당 변수를 채 웁니다. dev 모드에서 해당 변수는 모든 JS 파일의 글 로빙 패턴에서 비롯됩니다. watch 파일 태스크는 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
와 함께 연결합니다 script
. destPath
각 파일에서 원하는 접두사입니다.
HTML은 다음과 같습니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Example</title>
</head>
<body>
@@scriptsTags
</body>
</html>
이제 설정에서 볼 수 있듯이 모드 script
에서 실행될 때 해당 변수의 값을 하드 코딩 된 태그 로 생성 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>
궁금한 점이 있으면 알려주세요.
추신 : 이것은 모든 클라이언트 측 JS 앱에서하고 싶은 무언가를위한 미친 양의 코드입니다. 누군가가 이것을 재사용 가능한 플러그인으로 바꿀 수 있기를 바랍니다. 아마 언젠가는
답변
나는 잠시 동안 나 자신에게 같은 질문을하고 있었고,이 grunt 플러그인은 원하는 것을 수행하도록 구성 될 수 있다고 생각한다 : https://npmjs.org/package/grunt-targethtml . 그런 대상에 따라 조건부 html 태그를 구현합니다.
답변
더 간단하고 직접적인 솔루션을 찾고 있었 으므로이 질문에 대한 답변을 결합했습니다.
다음과 같은 간단한 단계를 생각해 냈습니다.
- 나열된대로 두 가지 버전의 색인 파일을 유지하고 이름을 index-development.html 및 index-prodoction.html로 지정하십시오.
-
index.html 파일에 대해 Gruntfile.js의 concat / copy 블록에서 다음 논리를 사용하십시오.
concat: { index: { src : [ (function() { if (grunt.option('Release')) { return 'views/index-production.html'; } else { return 'views/index-development.html'; } }()) ], dest: '<%= distdir %>/index.html', ... }, ... },
-
‘grunt –Release’를 실행하여 index-production.html 파일을 선택하고 개발 버전을 갖도록 플래그를 생략하십시오.
추가하거나 구성 할 수있는 새로운 플러그인과 새로운 그런 작업이 없습니다.
답변
scriptlinker 라는 이름의이 거친 작업 은 dev 모드에서 스크립트를 추가하는 쉬운 방법처럼 보입니다. concat 작업을 먼저 실행 한 다음 prod 모드에서 연결된 파일을 가리킬 수 있습니다.
답변
grunt-dom-munger 는 CSS 선택기로 HTML을 읽고 조작합니다. 전의. HTML에서 태그를 읽습니다. 노드 제거, 노드 추가 등.
grunt-dom-munger를 사용하여 index.html에 의해 링크 된 모든 JS 파일을 읽고, 결합한 다음 grunt-dom-munger를 다시 사용하여 index.html을 수정하여 축소 된 JS 만 링크 할 수 있습니다.
