programing

Grunt가 다른 설정에 대해 index.html을 생성하도록 합니다.

minecode 2022. 10. 22. 23:27
반응형

Grunt가 다른 설정에 대해 index.html을 생성하도록 합니다.

웹 앱 빌드 도구로 Grunt를 사용하려고 합니다.

다음 두 가지 이상의 설정을 원합니다.

I. 개발 셋업 - 연결 없이 별도의 파일에서 스크립트를 로드합니다.

그래서 내 index.displaces는 다음과 같습니다.

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

II. 실가동 셋업 - 1개의 파일에 미니화하여 연결된 스크립트를 로드합니다.

index.displaces를 지정합니다.

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

문제는 실행 시 구성에 따라 이러한 index.html을 어떻게 grunt로 만들있는가 하는 것입니다.

제가 가 더 도 있습니다.MyApp-all.min.js모든 스크립트(연결) 또는 개별 파일에서 비동기식으로 스크립트를 로드하는 로더 스크립트 중 하나를 여기에 넣어야 합니까?

어떻게 하는 거야?

는 에 그룬트를 했다.v0.4.0「이것들」은 다음과 같습니다.

  • 그룬트 프로세스

    npm 모듈 전처리 관련 그룬트 작업

  • 불평하다

    Grunt 태스크를 통해 향후 태스크를 위해 환경 구성을 자동화합니다.

아래는 저의 단편입니다.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 -->

나의 설정은 대부분의 사람들과 다르며, 위의 유용성은 당신의 상황에 따라 달라질 것입니다.나에게 있어, 훌륭한 코드이긴 하지만, Yoman grunt-usemin은 내가 개인적으로 필요로 하는 것보다 더 강력하다.

메모: 오늘 의 작업을 발견했기 때문에 기능이 누락되거나 프로세스가 변경될 수 있습니다.현재로서는 grunt-preprocessgrunt-env가 제공하는 심플함과 기능이 마음에 듭니다.:)


2014년 1월 갱신:

낙선 투표에 자극받아...

가 이 때 Grunt에 옵션이 0.4.x제 요구에 맞는 솔루션을 제공했습니다.몇 달이 지난 지금, 저는 제가 여기에 올린 보다 더 나은 선택지가 있다고 생각합니다.는 이 기술을 개인적으로 사용하고 있고, 또 즐겨 사용하고 있습니다만, 장래의 독자들에게는, 주어진 다른 답을 읽고, 모든 옵션을 검토해 주셨으면 합니다.더 나은 해결책을 찾으시면 여기에 답변을 올려주세요.

2014년 2월 갱신:

누군가에게 도움이 될지는 모르겠지만 위에서 설명한 기술을 사용하여 완전하고 복잡한 설정을 보여주는 데모 저장소를 GitHub에 만들었습니다.

나는 나만의 해결책을 생각해냈다.아직 다듬지 않았지만 그 방향으로 갈 것 같아요.

즉, grunt.template.process()를 사용하여 module을 생성합니다.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 + '\'');
    });
}

마지막으로, 생성 로직은 다음과 같습니다.

<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은 Yeoman의 빌드 시스템과 통합되는 usemin 태스크를 내장하고 있음을 알게 되었습니다.index.html의 개발 버전 정보와 기타 환경 설정에서 index.html의 실제 버전을 생성합니다.좀 세련되었지만 보기엔 흥미롭네요.

여기의 솔루션(이전 솔루션 포함)은 마음에 들지 않습니다.이유는 다음과 같습니다.

  • 가장 많이 투표된 답변의 문제는 JS 파일을 추가/이름 변경/삭제할 때 스크립트 태그 목록을 수동으로 동기화해야 한다는 것입니다.
  • 승인된 답변의 문제는 JS 파일 목록이 패턴 매칭을 가질 수 없다는 것입니다.즉, Grunt 파일에서 수동으로 업데이트해야 합니다.

나는 이 두 가지 문제를 모두 해결할 방법을 알아냈다.파일이 추가 또는 삭제될 때마다 스크립트 태그가 자동으로 생성되도록 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투덜거리다 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>

궁금한 점이 있으면 알려주세요.

PS: 모든 클라이언트측 JS 앱에서 하고 싶은 코드의 양이 엄청납니다.누가 이걸 재사용 가능한 플러그인으로 바꿔줬으면 좋겠어요.언젠가 그럴지도 몰라요.

저는 한동안 같은 질문을 스스로에게 하고 있었습니다.이 grunt 플러그인은, https://npmjs.org/package/grunt-targethtml 라고 하는, 고객이 원하는 대로 설정할 수 있다고 생각합니다.grunt 대상에 따라 조건부 html 태그를 구현합니다.

보다 심플하고 알기 쉬운 솔루션을 찾고 있었기 때문에, 이 질문의 답을 조합했습니다.

gruntfile.js에 if 블록을 배치하는 방법

그리고 다음과 같은 간단한 단계를 생각해 냈습니다.

  1. 목록과 같이 인덱스 파일의 두 버전을 유지하고 이름을 index-development.html과 index-production.html로 지정합니다.
  2. Gruntfile.js의 concat/copy 블록에서 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',
           ...
        },
        ...
    },
    
  3. grunt --Release'를 실행하여 index-production.html 파일을 선택하고 플래그를 해제하여 개발 버전을 지정합니다.

추가 또는 구성할 새 플러그인 및 새 grunt 태스크가 없습니다.

scriptlinker라는 이름의 이 grunt 태스크는 개발 모드에서 스크립트를 쉽게 추가할 수 있는 방법처럼 보입니다.먼저 연결 태스크를 실행하고 다음으로 prod 모드에서 연결된 파일을 가리킬 수 있습니다.

grunt-dom-munger는 CSS 셀렉터를 사용하여 HTML을 읽고 조작합니다.예를 들어 html에서 태그를 읽습니다.노드 삭제, 노드 추가 등

grunt-dom-munger를 사용하여 index.html에 의해 링크된 모든 JS 파일을 읽고 그것들을 uglimize한 후 다시 grunt-dom-munger를 사용하여 index.html을 변경하여 최소화된 JS만 링크할 수 있습니다.

grunt-dev-prod-switch라는 grunt 플러그인을 찾았습니다.grunt에 전달된 --env 옵션에 따라 검색된 특정 블록을 주석으로 지정하는 것(단, 개발, 실행 및 테스트로 제한됨)이 전부입니다.

여기서 설명하는 대로 설정하면 다음과 같이 실행할 수 있습니다.

grunt serve --env=dev 이 는, 「이 이라고 하는 코멘트 밖에 없습니다.

    <!-- env:test/prod -->
    your code here
    <!-- env:test/prod:end -->

그리고 그것은 에워싸여진 블록들을 언코멘트할 것이다.

    <!-- env:dev -->
    your code here
    <!-- env:dev:end -->

javascript에서도 동작합니다.백엔드 API에 접속하기 위한 올바른 IP 주소를 설정하기 위해 사용합니다.블록이 로 바뀝니다.

    /* 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>

grunt-timeout은 환상적인 grunt-timeout 대본입니다.JQM 자동 빌드 스크립트에서 사용합니다.

https://github.com/imaginethepoet/autojqmphonegap

내 grunt.coffee 파일을 확인합니다.

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

그러면 base.html 내의 모든 파일이 검색되어 index.html이 멀티페이징 앱(phonegap)에 매우 적합합니다.따라서 모든 개발자가 하나의 긴 한 페이지 앱에서 동작하지 않기 때문에 (많은 컨플릭트체크인을 방지할 수 있습니다) 쉽게 개발할 수 있습니다.대신 페이지를 분할하여 더 작은 코드 청크로 작업하고 watch 명령을 사용하여 전체 페이지로 컴파일할 수 있습니다.

Bake는 base.html에서 템플릿을 읽고 컴포넌트 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>

한 걸음 더 나아가 페이지에 "메뉴" "팝업" 등을 위한 주입을 추가하면 페이지를 관리하기 쉬운 작은 컴포넌트로 분할할 수 있습니다.

wiredep https://github.com/taptapship/wiredep 와 usmin https://github.com/yeoman/grunt-usemin 의 조합을 사용하여 grunt가 이러한 작업을 처리하도록 합니다.Wiredep은 의존관계를 한번에1개의 스크립트파일로 추가하고 usemin은 그것들을 모두 1개의 파일로 연결하여 프로덕션합니다.이것은 몇 가지 html 코멘트만으로 실행할 수 있습니다.예를 들어 bower 패키지는 실행 시 자동으로 포함되어 html에 추가됩니다.bower install && grunt bowerInstall:

<!-- build:js /scripts/vendor.js -->
<!-- bower:js -->
<!-- endbower -->
<!-- endbuild -->

이 대답은 'Noobs'가 아니야!

Jade 템플릿 사용... Jade 템플릿에 변수를 전달하는 것은 매우 일반적인 사용 사례입니다.

grunt(grunt-contrib-jade)를 사용하고 있습니다만, grunt를 사용할 필요는 없습니다.표준 npm 옥 모듈을 사용합니다.

grunt를 사용하는 경우 grunt 파일에는 다음과 같은 것이 필요합니다.

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"
        }
      ]
    }
  },

이제 Jade 템플릿에서 grunt가 전달한 데이터에 쉽게 액세스할 수 있습니다.

Modernizr에서 사용하는 접근법과 마찬가지로 전달된 변수의 값에 따라 HTML 태그에 CSS 클래스를 설정하고 CSS 클래스의 존재 여부에 따라 JavaScript 로직을 사용할 수 있습니다.

이는 Angular를 사용하는 경우 클래스 존재 여부에 따라 페이지에 요소를 포함하기 위해 ng-if를 수행할 수 있으므로 매우 유용합니다.

예를 들어, 클래스가 존재하는 경우 스크립트를 포함할 수 있습니다.

(예를 들어 라이브 새로고침 스크립트는 dev에는 포함하지만 실제 가동에는 포함하지 않는 경우가 있습니다).

<script ng-if="controller.isClassPresent()" src="//localhost:35729/livereload.js"></script> 

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">

언급URL : https://stackoverflow.com/questions/12401998/have-grunt-generate-index-html-for-different-setups

반응형