Có Grunt tạo index.html cho các thiết lập khác nhau


208

Tôi đang cố gắng sử dụng Grunt làm công cụ xây dựng cho ứng dụng web của mình.

Tôi muốn có ít nhất hai thiết lập:

I. Thiết lập phát triển - tải tập lệnh từ các tệp riêng biệt, không ghép nối,

vì vậy index.html của tôi sẽ trông giống như:

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

II. Thiết lập sản xuất - tải tập lệnh của tôi được thu nhỏ & nối trong một tệp,

với index.html tương ứng:

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

Câu hỏi là, làm thế nào tôi có thể làm cho grunt tạo các index.html này tùy thuộc vào cấu hình khi tôi chạy grunt devhoặc grunt prod?

Hoặc có thể tôi đang đào sai hướng và sẽ dễ dàng tạo ra hơn MyApp-all.min.jsnhưng đặt bên trong nó tất cả các tập lệnh của tôi (được nối) hoặc tập lệnh trình tải tải không đồng bộ các tập lệnh đó từ các tệp riêng biệt?

Làm thế nào để bạn làm điều đó, các bạn?


3
Hãy thử công cụ Yeoman, bao gồm một nhiệm vụ 'usemin', thực hiện những gì bạn làm. Ngoài ra, các trình tạo Yeamon bao gồm rất nhiều "thực hành tốt" dễ học, khó học khi sử dụng một công cụ mới.
EricSonaron

Câu trả lời:


161

Gần đây tôi đã phát hiện ra các v0.4.0nhiệm vụ tương thích Grunt này :

  • tiền xử lý

    Nhiệm vụ Grunt xung quanh mô đun npm tiền xử lý.

  • lẩm bẩm

    Nhiệm vụ Grunt để tự động hóa cấu hình môi trường cho các nhiệm vụ trong tương lai.

Dưới đây là đoạn trích từ của tôi Gruntfile.js.

Cài đặt ENV:

env : {

    options : {

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

    },

    dev: {

        NODE_ENV : 'DEVELOPMENT'

    },

    prod : {

        NODE_ENV : 'PRODUCTION'

    }

},

Tiền xử lý:

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 %>'
            }

        }

    }

}

Nhiệm vụ:

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']);

Và trong /src/tmpl/index.htmltệp mẫu (ví dụ):

<!-- @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 -->

Tôi chắc chắn rằng thiết lập của tôi khác với hầu hết mọi người và tính hữu ích của những điều trên sẽ phụ thuộc vào tình huống của bạn. Đối với tôi, trong khi đó là một đoạn mã tuyệt vời, thì Yeoman grunt-usemin là một thứ mạnh mẽ hơn cá nhân tôi cần.

LƯU Ý: Tôi mới phát hiện ra các tác vụ được liệt kê ở trên ngày hôm nay, vì vậy tôi có thể thiếu một tính năng và / hoặc quá trình của tôi có thể thay đổi. Hiện tại, tôi yêu sự đơn giản các tính năng mà grunt-pre processgrunt-env phải cung cấp. :)


Cập nhật tháng 1 năm 2014:

Được thúc đẩy bởi một cuộc bỏ phiếu ...

Khi tôi đăng câu trả lời này, không có nhiều lựa chọn cho Grunt 0.4.xđưa ra giải pháp phù hợp với nhu cầu của tôi. Bây giờ, nhiều tháng sau, tôi đoán rằng có nhiều lựa chọn ngoài kia thể tốt hơn những gì tôi đã đăng ở đây. Mặc dù tôi vẫn sử dụng cá nhân và thích sử dụng, kỹ thuật này cho các bản dựng của tôi , tôi yêu cầu các độc giả tương lai dành thời gian để đọc các câu trả lời khác được đưa ra và nghiên cứu tất cả các tùy chọn. Nếu bạn tìm thấy một giải pháp tốt hơn, xin vui lòng gửi câu trả lời của bạn ở đây.

Cập nhật tháng 2 năm 2014:

Tôi không chắc liệu nó có giúp được ai không, nhưng tôi đã tạo kho lưu trữ demo này trên GitHub để hiển thị toàn bộ (và thiết lập phức tạp hơn) bằng cách sử dụng (các) kỹ thuật tôi đã nêu ở trên.


Cảm ơn, tôi sẽ kiểm tra xem!
Dmitry Pashkevich

3
Giải pháp của bạn đã giúp tôi tiết kiệm được hàng giờ đập đầu vào tường. Cảm ơn.
sthomps

1
@sthomps Vui mừng vì nó đã giúp! Kể từ khi tôi phát hiện ra những nhiệm vụ đó, tôi đã yêu thích quy trình làm việc. FYI, tôi đã thực hiện một thay đổi nhỏ cho quy trình ... Thay vì chuyển một số biến bối cảnh cho các mẫu html của mình, tôi đã chọn chuyển một var path : '/<%= pkg.name %>/dist/<%= pkg.version %>/<%= now %>/<%= ver %>'có thể điều chỉnh tất cả các vars (đó là đường dẫn xây dựng của tôi). Trên mẫu của tôi, tôi sẽ có : <script src="http://cdn.foo.com<!-- @echo path -->/js/bulldog.min.js"></script>. Dù sao, tôi rất vui vì tôi đã có thể giúp bạn tiết kiệm thời gian! : D
mhulse

4
Bạn có thể làm điều tương tự bằng cách chỉ sử dụng mẫu grunt , bằng cách chuyển vào một datađối tượng khác cho dev / prod.
Mathias Bynens

2
Người đàn ông tôi yêu giải pháp này .. Nó sạch sẽ, dễ đọc và không quá kỹ thuật.
Gaurang Patel

34

Tôi đã đưa ra giải pháp của riêng mình. Chưa được đánh bóng nhưng tôi nghĩ tôi sẽ đi theo hướng đó.

Về bản chất, tôi đang sử dụng grunt.template. Process () để tạo của tôi index.htmltừ một mẫu phân tích cấu hình hiện tại và tạo một danh sách các tệp nguồn gốc của tôi hoặc liên kết đến một tệp với mã được rút gọn. Ví dụ dưới đây dành cho các tệp js nhưng cách tiếp cận tương tự có thể được mở rộng thành css và bất kỳ tệp văn bản nào khác có thể.

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 + '\'');
    });
}

Cuối cùng, index.tmplvới logic thế hệ nướng trong:

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

CẬP NHẬT. Phát hiện ra rằng Yeoman , dựa trên grunt, có một nhiệm vụ usemin tích hợp tích hợp với hệ thống xây dựng của Yeoman. Nó tạo ra một phiên bản sản xuất của index.html từ thông tin trong phiên bản phát triển của index.html cũng như các cài đặt môi trường khác. Một chút tinh vi nhưng thú vị để xem xét.


5
grunt-template là một trình bao bọc rất nhẹ xung quanhgrunt.template.process()(đó là những gì bạn đang sử dụng ở đây) sẽ giúp việc này trở nên dễ dàng hơn. Bạn có thể làm điều tương tự bằng cách sử dụng mẫu grunt bằng cách chuyển vào mộtdatađối tượngkháccho dev / prod.
Mathias Bynens

15

Tôi không thích các giải pháp ở đây (bao gồm cả giải pháp tôi đã đưa ra trước đây ) và đây là lý do:

  • Vấn đề với câu trả lời được bình chọn cao nhất là bạn phải đồng bộ hóa thủ công danh sách các thẻ script khi bạn thêm / đổi tên / xóa tệp JS.
  • Vấn đề với câu trả lời được chấp nhận là danh sách các tệp JS của bạn không thể có khớp mẫu. Điều này có nghĩa là bạn phải cập nhật nó bằng tay trong Gruntfile.

Tôi đã tìm ra cách giải quyết cả hai vấn đề này. Tôi đã thiết lập tác vụ lẩm cẩm của mình để mỗi khi một tệp được thêm hoặc xóa, các thẻ script sẽ tự động được tạo để phản ánh điều đó. Theo cách này, bạn không cần phải sửa đổi tệp html hoặc tệp grunt của mình khi bạn thêm / xóa / đổi tên tệp JS của mình.

Để tóm tắt cách thức hoạt động, tôi có một mẫu html với một biến cho các thẻ script. Tôi sử dụng https://github.com/alanshaw/grunt-include-replace để điền vào biến đó. Trong chế độ dev, biến đó xuất phát từ một mẫu toàn cầu của tất cả các tệp JS của tôi. Tác vụ theo dõi tính toán lại giá trị này khi một tệp JS được thêm hoặc xóa.

Bây giờ, để có được kết quả khác nhau trong chế độ dev hoặc prod, bạn chỉ cần nhập biến đó với một giá trị khác. Đây là một số mã:

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

jsSrcFileArraylà mô hình tập tin grunt điển hình của bạn. jsScriptTagslấy jsSrcFileArrayvà ghép chúng lại với nhau bằng scriptcác thẻ ở cả hai bên. destPathlà tiền tố tôi muốn trên mỗi tệp.

Và đây là HTML trông như thế nào:

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

</head>

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

Bây giờ, như bạn có thể thấy trong cấu hình, tôi tạo giá trị của biến đó dưới dạng scriptthẻ được mã hóa cứng khi nó chạy ở prodchế độ. Trong chế độ dev, biến này sẽ mở rộng thành một giá trị như thế này:

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

Hãy cho tôi biết nếu bạn có bất kỳ câu hỏi.

PS: Đây là một lượng mã điên rồ cho một thứ gì đó tôi muốn làm trong mọi ứng dụng JS phía máy khách. Tôi hy vọng ai đó có thể biến điều này thành một plugin có thể tái sử dụng. Có lẽ tôi sẽ có một ngày.


1
Âm thanh đầy hứa hẹn. Bất kỳ cơ hội bạn có thể chia sẻ một số đoạn?
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 thatCậu đã làm thế nào vậy?
CodyBugstein

2
Một câu hỏi khác: Bạn có biết một cách để xóa các khối <script>thẻ HTML không?
CodyBugstein

@Imray không ra khỏi đỉnh đầu của tôi. Bạn có nghĩa là không có bất kỳ hình thức templating (ví dụ, grunt-bao gồm-thay thế)? Ý nghĩ đầu tiên xuất hiện trong đầu tôi là xslt. Có lẽ không phải là một giải pháp tốt.
Daniel Kaplan

1
Câu trả lời này được phát hiện trên, mặc dù cá nhân tôi lấy ra destPathtừ jsScriptTagsvà hoán đổi grunt.file.expandMappingvới grunt.file.expandnhư các tập tin tôi muốn đều đã ở các vị trí chính xác. Điều này đơn giản hóa rất nhiều. Cảm ơn bạn @DanielKaplan, bạn đã tiết kiệm cho tôi một khoảng thời gian rất lớn :)
DanielM

13

Tôi đã tự hỏi mình câu hỏi tương tự trong một thời gian và tôi nghĩ rằng plugin grunt này có thể được cấu hình để làm những gì bạn muốn: https://npmjs.org/package/grunt-targethtml . Nó thực hiện các thẻ html có điều kiện, phụ thuộc vào mục tiêu grunt.


2
Tôi đã thấy plugin này nhưng tôi không thích ý tưởng chỉ định thủ công tất cả các tệp (và thực sự có bất kỳ logic nào) trong index.html của tôi vì tôi đã có một danh sách các tệp js / css nguồn trong cấu hình grunt của tôi và không ' t muốn lặp lại chính mình. Điểm mấu chốt là - nó không nằm trong index.html nơi bạn nên quyết định những tập tin nào sẽ bao gồm
Dmitry Pashkevich

+1 cho grunt-targethtml. Mặc dù có một chút xấu xí khi thêm các câu lệnh nếu "quyết định" trong index.html của bạn sẽ tải tài sản nào. Tuy nhiên, nó có ý nghĩa. Đây là nơi bạn thường sẽ tìm kiếm để bao gồm các tài nguyên trong dự án của bạn. Ngoài ra, theo dõi điều này đã dẫn tôi để kiểm tra grunt-contrib. Nó có một số thứ tuyệt vời trong đó.
carbontax

8

Tôi đang tìm kiếm một giải pháp đơn giản hơn, đơn giản hơn vì vậy tôi đã kết hợp câu trả lời từ câu hỏi này:

Cách đặt nếu khối khác trong gruntfile.js

và đưa ra các bước đơn giản sau:

  1. Giữ hai phiên bản tệp chỉ mục của bạn khi bạn liệt kê và đặt tên chúng là index-Development.html và index-prodoction.html.
  2. Sử dụng logic sau trong khối concat / copy của Gruntfile.js cho tệp index.html của bạn:

    concat: {
        index: {
            src : [ (function() {
                if (grunt.option('Release')) {
                  return 'views/index-production.html';
                } else {
                  return 'views/index-development.html';
                }
              }()) ],
           dest: '<%= distdir %>/index.html',
           ...
        },
        ...
    },
  3. chạy 'grunt --Release' để chọn tệp index-sản xuất.html và bỏ cờ để có phiên bản phát triển.

Không có plugin mới để thêm hoặc cấu hình và không có tác vụ mới.


3
Nhược điểm duy nhất ở đây là có hai tệp index.html cần duy trì.
Adam Marshall

5

Tác vụ khó khăn này có tên scriptlinker trông giống như một cách dễ dàng để thêm các tập lệnh trong chế độ dev. Bạn có thể có thể chạy một tác vụ concat trước và sau đó trỏ nó vào tệp được nối của bạn trong chế độ prod.


+1. Tài liệu này gây nhầm lẫn và một số nội dung (appRoot, họ hàng) không phải lúc nào cũng hoạt động như dự định, nhưng vẫn: công cụ hữu ích.
trao đổi

1
@hashchange Tôi không sử dụng công cụ này. Thay vào đó, tôi đã sử dụng github.com/alanshaw/grunt-include-replace . Tôi có một biến trong tệp html của tôi đại diện cho các thẻ script. Sau đó, tôi điền biến đó với Chuỗi html tôi muốn. Trong chế độ dev, biến này là một danh sách các tập lệnh. Trong chế độ prod, biến này là phiên bản rút gọn, rút ​​gọn.
Daniel Kaplan

Cảm ơn các con trỏ để grunt-bao gồm-thay thế. (Tôi thực sự đang rất cần một công cụ để thêm tất cả các file đặc tả trong một thư mục vào một tập tin index.html Mocha Scriptlinker là tốt cho điều đó..)
hashchange

@hashchange bạn nói đúng về việc hút tài liệu. Làm thế nào để bạn nói với nó nơi để đặt các tập lệnh trong tập tin html của bạn?
Daniel Kaplan

1
Bạn xác định một nhận xét HTML. Có một cái nhìn vào tập tin này . Sự chèn ép xảy ra tại <!--SINON COMPONENT SCRIPTS--><!--SPEC SCRIPTS-->. Và đây là nhiệm vụ Grunt thực hiện nó (một công việc thực tế, trái ngược với những thứ trong tài liệu). Hy vọng nó sẽ giúp;)
hashchange

5

grunt-dom-munger đọc và thao tác HTML với các bộ chọn CSS. Ví dụ. đọc các thẻ từ html của bạn. Loại bỏ các nút, thêm các nút, và nhiều hơn nữa.

Bạn có thể sử dụng grunt-dom-munger để đọc tất cả các tệp JS được liên kết bởi index.html của bạn, làm xấu đi chúng và sau đó sử dụng grunt-dom-munger một lần nữa để sửa đổi index.html của bạn để chỉ liên kết với JS đã rút gọn


5

Tôi tìm thấy một plugin grunt gọi là grunt-dev-prod-switch. Tất cả những gì nó làm là nhận xét các khối nhất định mà nó tìm kiếm dựa trên tùy chọn --env mà bạn chuyển sang grunt (mặc dù nó giới hạn bạn trong dev, prod và test).

Khi bạn thiết lập nó như giải thích ở đây , bạn có thể chạy ví dụ:

grunt serve --env=devvà tất cả những gì nó làm là nhận xét các khối được bao bọc bởi

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

và nó sẽ bỏ qua các khối được bọc bởi

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

Nó cũng hoạt động trên javascript, tôi sử dụng nó để thiết lập đúng địa chỉ IP để kết nối với API phụ trợ của mình. Các khối chỉ thay đổi thành

    /* env:dev */
    your code here
    /* env:dev:end */

Trong trường hợp của bạn, nó sẽ đơn giản như thế này:

<!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 là một kịch bản grunt tuyệt vời sẽ làm việc tuyệt vời ở đây. Tôi sử dụng nó trong tập lệnh xây dựng tự động JQM của tôi.

https://github.com/imaginethepoet/autojqmphonegap

Hãy xem tập tin grunt.coffee của tôi:

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

Cái này xem xét tất cả các tệp trong base.html và hút chúng vào để tạo index.html hoạt động tuyệt vời cho nhiều ứng dụng (phonegap). Điều này cho phép phát triển dễ dàng hơn vì tất cả các nhà phát triển không hoạt động trên một ứng dụng một trang dài (ngăn chặn nhiều kiểm tra xung đột). Thay vào đó, bạn có thể chia nhỏ các trang và làm việc trên các đoạn mã nhỏ hơn và biên dịch thành toàn bộ trang bằng lệnh xem.

Bake đọc mẫu từ base.html và tiêm các trang html thành phần trên đồng hồ.

<!DOCTYPE html>

Trình diễn di động jQuery

app.initialize ();

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

Bạn có thể tiến thêm một bước này và thêm tiêm trong các trang của mình cho "menu" "cửa sổ bật lên", v.v. để bạn thực sự có thể chia trang thành các thành phần nhỏ hơn có thể quản lý được.


Có lẽ bạn có thể nâng cao câu trả lời của mình bằng bản demo mã sử dụng grunt-bake?
Dmitry Pashkevich

4

Sử dụng kết hợp Wiredep https://github.com/taptapship/wiredep và usemin https://github.com/yeoman/grunt-usemin để có thể xử lý các nhiệm vụ này. Wiredep sẽ thêm các tệp phụ thuộc của bạn một tệp script tại một thời điểm và usemin sẽ ghép tất cả chúng thành một tệp duy nhất để sản xuất. Điều này sau đó có thể được thực hiện chỉ với một số bình luận html. Chẳng hạn, các gói Bower của tôi được tự động đưa vào và thêm vào html khi tôi chạy bower install && grunt bowerInstall:

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

2

Câu trả lời này không dành cho noobs!

Sử dụng khuôn mẫu Jade ... chuyển các biến sang mẫu Jade là trường hợp sử dụng tiêu chuẩn không có thật

Tôi đang sử dụng grunt (grunt-contrib-jade) nhưng bạn không phải sử dụng grunt. Chỉ cần sử dụng mô-đun ngọc npm tiêu chuẩn.

Nếu sử dụng grunt thì gruntfile của bạn sẽ giống như ...

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

Bây giờ chúng ta có thể dễ dàng truy cập dữ liệu được truyền bởi grunt trong mẫu Jade.

Giống như cách tiếp cận được Modernizr sử dụng, tôi đặt một lớp CSS trên thẻ HTML theo giá trị của biến được truyền và có thể sử dụng logic JavaScript từ đó dựa trên việc lớp CSS có mặt hay không.

Điều này thật tuyệt nếu sử dụng Angular vì bạn có thể thực hiện ng-if để bao gồm các thành phần trong trang dựa trên việc lớp có mặt hay không.

Ví dụ, tôi có thể bao gồm một tập lệnh nếu lớp có mặt ...

(Ví dụ: tôi có thể bao gồm tập lệnh tải lại trực tiếp trong dev nhưng không có trong sản xuất)

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

2

Hãy xem xét processhtml . Nó cho phép định nghĩa nhiều "mục tiêu" cho các bản dựng. Nhận xét được sử dụng để bao gồm có điều kiện hoặc loại trừ tài liệu khỏi HTML:

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

trở thành

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

Nó thậm chí còn có ý định làm những thứ tiện lợi như thế này (xem phần 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">
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.