มี Grunt สร้าง index.html สำหรับการตั้งค่าที่แตกต่างกัน


208

ฉันพยายามใช้ 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>

ครั้งที่สอง การตั้งค่าการผลิต - โหลดสคริปต์ของฉันย่อขนาดและต่อกันในไฟล์เดียว

ด้วย 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แต่ใส่ไว้ในนั้นทั้งสคริปต์ของฉัน (ตัดแบ่ง) หรือสคริปต์โหลดเดอร์ที่โหลดแบบอะซิงโครนัสสคริปต์เหล่านั้นจากไฟล์แยกกัน

คุณจะทำอย่างไรพวก?


3
ลองใช้เครื่องมือ Yeoman ซึ่งรวมถึงภารกิจ 'usemin' ซึ่งทำในสิ่งที่คุณทำ นอกจากนี้เครื่องกำเนิดไฟฟ้า Yeamon ยังมี "วิธีปฏิบัติที่ดี" จำนวนมากซึ่งง่ายต่อการเรียนรู้ซึ่งยากที่จะเรียนรู้เมื่อใช้เครื่องมือใหม่
EricSonaron

คำตอบ:


161

ฉันเพิ่งค้นพบv0.4.0งานที่เข้ากันได้Grunt เหล่านี้:

  • ฮึดฮัด preprocess

    Grunt ภารกิจรอบ ๆ โมดูล preprocess npm

  • ฮึดฮัด env

    Grunt task เพื่อกำหนดค่าสภาพแวดล้อมแบบอัตโนมัติสำหรับงานในอนาคต

Gruntfile.jsด้านล่างนี้เป็นตัวอย่างจากของฉัน

การตั้งค่า ENV:

env : {

    options : {

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

    },

    dev: {

        NODE_ENV : 'DEVELOPMENT'

    },

    prod : {

        NODE_ENV : 'PRODUCTION'

    }

},

preprocess:

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นั้นแข็งแกร่งกว่าที่ฉันต้องการ

หมายเหตุ:ฉันเพิ่งค้นพบงานที่ระบุไว้ข้างต้นวันนี้ดังนั้นฉันอาจจะขาดคุณสมบัติและ / หรือกระบวนการของฉันอาจเปลี่ยนไปตามถนน สำหรับตอนนี้ฉันรักความเรียบง่ายและมีที่ฮึดฮัด preprocessและฮึดฮัด envมีให้ :)


อัพเดทมกราคม 2014:

แรงบันดาลใจจากการลงคะแนนเสียง ...

เมื่อฉันโพสต์คำตอบนี้ไม่มีตัวเลือกมากมายสำหรับ Grunt 0.4.xที่เสนอวิธีแก้ไขปัญหาที่ตอบสนองความต้องการของฉัน ตอนนี้เดือนต่อมาฉันจะเดาว่ามีตัวเลือกเพิ่มเติมที่อาจดีกว่าสิ่งที่ฉันโพสต์ที่นี่ ในขณะที่ฉันยังคงใช้เป็นการส่วนตัวและเพลิดเพลินกับการใช้เทคนิคนี้สำหรับงานสร้างของฉันฉันขอให้ผู้อ่านในอนาคตใช้เวลาอ่านคำตอบอื่น ๆ ที่ได้รับและการวิจัยตัวเลือกทั้งหมด หากคุณพบทางออกที่ดีกว่าโปรดโพสต์คำตอบของคุณที่นี่

อัปเดตเมื่อ ก.พ. 2014:

ฉันไม่แน่ใจว่ามันจะเป็นประโยชน์กับทุกคนหรือไม่ แต่ฉันได้สร้างที่เก็บสาธิตนี้บน GitHubที่แสดงการตั้งค่าที่สมบูรณ์ (และการตั้งค่าที่ซับซ้อนมากขึ้น) โดยใช้เทคนิคที่ฉันได้อธิบายไว้ข้างต้น


ขอบคุณฉันจะตรวจสอบมันออก!
Dmitry Pashkevich

3
ทางออกของคุณช่วยฉันทุบตีกำแพงหลายชั่วโมง ขอบคุณ
sthomps

1
@sthomps ดีใจที่ได้ช่วย! นับตั้งแต่ที่ฉันค้นพบภารกิจเหล่านั้นฉันก็รักกระบวนการทำงาน FYI ฉันได้ทำการเปลี่ยนแปลงเพียงเล็กน้อยในกระบวนการ ... แทนที่จะส่งตัวแปรบริบทหลายอย่างไปยังเทมเพลต html ของฉันฉันเลือกที่จะส่งหนึ่ง var path : '/<%= pkg.name %>/dist/<%= pkg.version %>/<%= now %>/<%= ver %>'ที่ concars vars ทั้งหมด (นั่นคือเส้นทางการสร้างของฉัน) บนแม่แบบของฉันฉันจะมี: <script src="http://cdn.foo.com<!-- @echo path -->/js/bulldog.min.js"></script>. อย่างไรก็ตามฉันมีความสุขที่ฉันสามารถช่วยคุณได้ในบางเวลา! : D
mhulse

4
คุณสามารถทำสิ่งเดียวกันโดยใช้เพียงเทมเพลต gruntเพียงแค่ส่งผ่านdataวัตถุที่แตกต่างสำหรับ dev / prod
งัด Bynens

2
ผู้ชายฉันชอบวิธีนี้ .. มันสะอาดอ่านง่ายและไม่ผ่านการออกแบบ
Gaurang Patel

34

ฉันคิดวิธีแก้ปัญหาของตัวเอง ยังไม่ขัด แต่ฉันคิดว่าฉันจะไปในทิศทางนั้น

ใน essense ฉันใช้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 พบว่าYeomanซึ่งมีพื้นฐานมาจากเสียงฮึดฮัดมีภารกิจuseminในตัวที่ทำงานร่วมกับระบบการสร้างของ Yeoman มันสร้างเวอร์ชันการผลิตของ index.html จากข้อมูลในเวอร์ชันการพัฒนาของ index.html รวมถึงการตั้งค่าสภาพแวดล้อมอื่น ๆ ดูซับซ้อน แต่ก็น่าสนใจ


5
Grunt-templateเป็น wrapper ที่เบามาก ๆgrunt.template.process()(ซึ่งเป็นสิ่งที่คุณใช้อยู่ที่นี่) ซึ่งจะทำให้สิ่งนี้ง่ายยิ่งขึ้น คุณสามารถทำสิ่งเดียวกันโดยใช้เทมเพลต gruntเพียงแค่ส่งผ่านdataวัตถุที่แตกต่างสำหรับ dev / prod
งัด Bynens

15

ฉันไม่ชอบวิธีแก้ไขปัญหาที่นี่ (รวมถึงที่ฉันเคยให้ไว้ก่อนหน้านี้ ) และนี่คือเหตุผล:

  • ปัญหาของคำตอบที่โหวตสูงสุดคือคุณต้องซิงค์รายการแท็กสคริปต์ด้วยตนเองเมื่อคุณเพิ่ม / เปลี่ยนชื่อ / ลบไฟล์ JS
  • ปัญหาของคำตอบที่ยอมรับคือรายการไฟล์ JS ของคุณไม่สามารถจับคู่รูปแบบได้ หมายความว่าคุณต้องอัปเดตด้วยตัวเองใน Gruntfile

ฉันหาวิธีแก้ปัญหาทั้งสองนี้แล้ว ฉันตั้งค่างานเสี้ยงฮึดฮัดแสดงความไม่พอใจดังนั้นทุกครั้งที่มีการเพิ่มหรือลบไฟล์แท็กสคริปต์จะถูกสร้างขึ้นโดยอัตโนมัติเพื่อแสดงให้เห็นว่า ด้วยวิธีนี้คุณไม่จำเป็นต้องแก้ไขไฟล์ html หรือไฟล์ grunt ของคุณเมื่อคุณเพิ่ม / ลบ / เปลี่ยนชื่อไฟล์ JS ของคุณ

เพื่อสรุปวิธีการทำงานฉันมีเทมเพลต html ที่มีตัวแปรสำหรับแท็กสคริปต์ ฉันใช้https://github.com/alanshaw/grunt-include-replaceเพื่อเติมตัวแปรนั้น ในโหมด dev ตัวแปรนั้นมาจากรูปแบบการวนรอบของไฟล์ 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 ฝั่งไคลเอ็นต์ ฉันหวังว่าบางคนสามารถเปลี่ยนสิ่งนี้ให้เป็นปลั๊กอินที่ใช้ซ้ำได้ บางทีฉันอาจจะสักวัน


1
เสียงที่มีแนวโน้ม โอกาสใดที่คุณสามารถแชร์ตัวอย่างได้บ้าง
Adam Marshall

I've set up my grunt task so that every time a file is added or deleted, the script tags automatically get generated to reflect thatคุณทำได้อย่างไร?
CodyBugstein

2
คำถามอื่น: คุณรู้วิธีการเพียงแค่ลบบล็อกของ<script>แท็กHTML หรือไม่?
CodyBugstein

@ ไม่วาดส่วนบนของหัวของฉัน คุณหมายถึงโดยไม่มีรูปแบบของการสร้างเทมเพลตใด ๆ (เช่น grunt-include-replace)? ความคิดแรกที่ปรากฏในหัวของฉันจะเป็น xslt อาจไม่ใช่วิธีที่ดีแม้ว่า
Daniel Kaplan

1
คำตอบนี้เป็นจุดที่แม้ว่าฉันจะลบออกdestPathจากjsScriptTagsและสลับgrunt.file.expandMappingกับส่วนตัวgrunt.file.expandเป็นไฟล์ที่ฉันต้องการอยู่ในสถานที่ที่ถูกต้องแล้ว สิ่งที่ทำให้เข้าใจง่ายมาก ขอบคุณ @DanielKaplan คุณประหยัดเวลาได้มาก :)
DanielM

13

ฉันได้รับการถามตัวเองคำถามเดียวกันในขณะที่และฉันคิดว่าปลั๊กอินเสียงฮึดฮัดนี้อาจจะมีการกำหนดค่าที่จะทำสิ่งที่คุณต้องการ: https://npmjs.org/package/grunt-targethtml มันใช้แท็ก HTML แบบมีเงื่อนไขซึ่งขึ้นอยู่กับเป้าหมายเสียงฮึดฮัด


2
ฉันได้เห็นปลั๊กอินนี้แล้ว แต่ฉันไม่ชอบความคิดในการระบุไฟล์ทั้งหมดด้วยตนเอง (และมีตรรกะใด ๆ ด้วยตนเอง) ใน index.html ของฉันเพราะฉันมีรายการแหล่งไฟล์ js / css อยู่ในการตั้งค่า grunt และ don ' ไม่อยากพูดซ้ำ บรรทัดล่างคือ - ไม่อยู่ใน index.html ที่คุณควรตัดสินใจว่าจะรวมไฟล์อะไรบ้าง
Dmitry Pashkevich

+1 สำหรับ grunt-Targethtml แม้ว่าจะเป็นเรื่องที่น่าเกลียดที่จะเพิ่มถ้าคำสั่ง "ตัดสินใจ" ใน index.html ของคุณว่าจะโหลดเนื้อหาใด ถึงกระนั้นมันก็สมเหตุสมผล นี่คือสถานที่ที่คุณมักจะมองหาเพื่อรวมแหล่งข้อมูลในโครงการของคุณ นอกจากนี้การติดตามเรื่องนี้ทำให้ฉันไปดูงานที่ไม่ดี มันมีบางสิ่งที่ยอดเยี่ยมอยู่ในนั้น
carbontax

8

ฉันกำลังมองหาวิธีแก้ปัญหาตรงไปตรงมาง่ายขึ้นดังนั้นฉันรวมคำตอบจากคำถามนี้:

วิธีการวางถ้าอื่น ๆ บล็อกใน gruntfile.js

และเกิดขึ้นกับขั้นตอนง่าย ๆ :

  1. เก็บไฟล์ดัชนีสองเวอร์ชันของคุณตามที่คุณระบุไว้และตั้งชื่อพวกเขา index-development.html และ index-prodoction.html
  2. ใช้ตรรกะต่อไปนี้ในบล็อก concat / copy ของ Gruntfile.js สำหรับไฟล์ 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 และปล่อยแฟล็กเพื่อให้มีเวอร์ชันการพัฒนา

ไม่มีปลั๊กอินใหม่เพื่อเพิ่มหรือกำหนดค่าและไม่มีงานเสี้ยงฮึดฮัดใหม่


3
ข้อเสียเพียงอย่างเดียวที่นี่คือมีสองไฟล์ index.html ที่จะรักษา
Adam Marshall

5

งาน grunt นี้ชื่อscriptlinkerดูเหมือนจะเป็นวิธีที่ง่ายในการเพิ่มสคริปต์ในโหมด dev คุณอาจเรียกใช้งาน concat ก่อนแล้วจึงชี้ไปที่ไฟล์ที่ต่อกันในโหมด prod


+1 เอกสารมีความสับสนและบางสิ่ง (appRoot, ญาติ) ไม่ทำงานตามที่ตั้งใจ แต่ยังคง: เครื่องมือที่มีประโยชน์
hashchange

1
@hashchange ฉันไม่ได้ใช้เครื่องมือนี้ ฉันลงเอยด้วยการใช้github.com/alanshaw/grunt-include-replaceแทน ฉันมีตัวแปรในไฟล์ html ของฉันแสดงถึงแท็กสคริปต์ จากนั้นฉันก็เติมตัวแปรนั้นด้วยสตริงของ html ที่ฉันต้องการ ในโหมด dev ตัวแปรนี้เป็นรายการของสคริปต์ ในโหมด prod ตัวแปรนี้คือ concatenated, minified version
Daniel Kaplan

ขอบคุณสำหรับตัวชี้ไปที่ grunt-include-replace (ฉันต้องการจริงเครื่องมือสำหรับการเพิ่มไฟล์ข้อมูลจำเพาะทั้งหมดในไดเรกทอรีเป็นไฟล์ index.html Mocha Scriptlinker จะดีสำหรับการที่..)
hashchange

@hashchange คุณพูดถูกเกี่ยวกับการดูดเอกสาร คุณจะบอกได้อย่างไรว่าจะวางไทล์สคริปต์ลงในไฟล์ html ของคุณได้อย่างไร
แดเนียลแคปแลน

1
คุณกำหนดความคิดเห็น HTML ลองดูที่ไฟล์นี้ แทรกที่เกิดขึ้นและ<!--SINON COMPONENT SCRIPTS--> <!--SPEC SCRIPTS-->และนี่คืองาน Grunt ที่ทำได้ (เป็นงานที่ใช้งานจริงซึ่งตรงข้ามกับเนื้อหาในเอกสาร) หวังว่ามันจะช่วย;)
hashchange

5

grunt-dom-mungerอ่านและจัดการ HTML ด้วย CSS selectors อดีต อ่านแท็กจาก html ของคุณ ลบโหนดเพิ่มโหนดและอื่น ๆ

คุณสามารถใช้ grunt-dom-munger เพื่ออ่านไฟล์ JS ทั้งหมดของคุณที่ลิงก์โดย index.html ของคุณทำลายพวกเขาและจากนั้นใช้ grunt-dom-munger อีกครั้งเพื่อปรับเปลี่ยน index.html ของคุณเพื่อลิงก์ JS ที่ย่อขนาดแล้วเท่านั้น


5

ฉันพบปลั๊กอินเสี้ยงฮึดฮัดที่เรียกว่า grunt-dev-prod-switch สิ่งที่มันทำก็คือคอมเม้นท์บล็อกที่มันหาตามตัวเลือก --env ที่คุณส่งไปยังเสี้ยงฮึดฮัด

เมื่อคุณตั้งค่าตามที่อธิบายไว้ที่นี่คุณสามารถเรียกใช้ตัวอย่าง:

grunt serve --env=devและสิ่งที่มันทำก็คือคอมเม้นท์บล็อคที่ถูกห่อหุ้มด้วย

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

และมันจะยกเลิกการใส่เครื่องหมายในบล็อกที่ห่อด้วย

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

มันใช้งานได้กับจาวาสคริปต์ฉันใช้เพื่อตั้งค่าที่อยู่ 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>

4

grunt-bake เป็นสคริปต์ grunt ที่ยอดเยี่ยมซึ่งจะทำงานได้ดีที่นี่ ฉันใช้มันในสคริปต์สร้าง JQM อัตโนมัติ

https://github.com/imaginethepoet/autojqmphonegap

ลองดูที่ไฟล์ grunt.coffee ของฉัน:

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

นี่จะดูไฟล์ทั้งหมดใน base.html และเก็บไว้ในการสร้าง index.html ใช้งานได้ดีสำหรับแอพหลายรายการ (phonegap) สิ่งนี้ช่วยให้การพัฒนาง่ายขึ้นเนื่องจาก devs ทั้งหมดไม่ทำงานบนแอพพลิเคชั่นหน้าเดียวยาว ๆ แต่คุณสามารถแยกหน้าและทำงานกับโค้ดขนาดเล็กและคอมไพล์ไปยังหน้าเต็มโดยใช้คำสั่ง 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>

คุณสามารถใช้ขั้นตอนนี้ต่อไปและเพิ่มการแทรกในหน้าของคุณสำหรับ "เมนู" "ป๊อปอัป" ฯลฯ เพื่อให้คุณสามารถแบ่งหน้าเป็นองค์ประกอบที่เล็กลงได้


บางทีคุณสามารถปรับปรุงคำตอบของคุณด้วยการสาธิตโค้ดที่ใช้ grunt-bake?
Dmitry Pashkevich

4

ใช้การรวมกันของ wiredep https://github.com/taptapship/wiredepและ usemin https://github.com/yeoman/grunt-useminเพื่อที่จะทำภารกิจเหล่านี้ให้ได้ Wiredep จะเพิ่มการอ้างอิงไฟล์สคริปต์หนึ่งไฟล์ของคุณในแต่ละครั้งและ usemin จะต่อเชื่อมไฟล์เหล่านั้นทั้งหมดให้เป็นไฟล์เดียวเพื่อการผลิต สิ่งนี้สามารถทำได้ด้วยความคิดเห็น html เพียงบางส่วน ตัวอย่างเช่นแพ็คเกจ bower ของฉันจะถูกรวมและเพิ่มลงใน html โดยอัตโนมัติเมื่อฉันเรียกใช้bower install && grunt bowerInstall:

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

2

คำตอบนี้ไม่ได้สำหรับ noobs!

ใช้ Jade templating ... การส่งตัวแปรไปยังเทมเพลต Jade เป็นกรณีการใช้มาตรฐานที่ลุ่ม

ฉันใช้เสียงฮึดฮัด (เสียงฮึดฮัด -contrib- หยก) แต่คุณไม่จำเป็นต้องใช้เสียงฮึดฮัด เพียงใช้โมดูลหยก npm มาตรฐาน

ถ้าใช้เสียงฮึดฮัดแสดงความไม่พอใจไฟล์ 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 ได้อย่างง่ายดาย

เช่นเดียวกับวิธีที่ใช้โดย Modernizr ฉันตั้งค่าคลาส CSS บนแท็ก HTML ตามค่าของตัวแปรที่ส่งผ่านและสามารถใช้ตรรกะ JavaScript จากที่นั่นโดยขึ้นอยู่กับว่ามีคลาส CSS อยู่หรือไม่

นี่เป็นสิ่งที่ดีถ้าใช้ Angular เนื่องจากคุณสามารถทำ ng-if เพื่อรวมองค์ประกอบในหน้าโดยขึ้นอยู่กับว่ามีคลาสอยู่หรือไม่

ตัวอย่างเช่นฉันอาจรวมสคริปต์หากมีคลาส ...

(ตัวอย่างเช่นฉันอาจรวมสคริปต์การโหลดซ้ำใน dev แต่ไม่ได้อยู่ในการผลิต)

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

2

พิจารณา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">
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.