Advertisement
  1. Web Design
  2. HTML/CSS
  3. JavaScript for Designers

Command Line trong thiết kế web: Tự động hoá với Grunt

Scroll to top
Read Time: 14 min
This post is part of a series called The Command Line for Web Design.
The Command Line for Web Design: Powering Up Front End Code
The Command Line for Web Design: Automation With Gulp

() translation by (you can also view the original English article)

Đến giờ bạn đã biết cách để biên dịch code, tự động tạo prefix, dọn sạch, nén và thu nhỏ chỉ trong vài từ. Điều này tuyệt, nhưng sẽ ra sao nếu bạn có một dự án cần chạy những lệnh này, lần lượt, lặp đi lặp lại đến khi bạn hoàn thành công việc? Ví dụ:

  1. Biên dịch tiền xử lý cho CSS
  2. Tự động tạo prefix cho CSS
  3. Dọn sạch CSS
  4. Biên dịch Jade thành HTML
  5. Kết hợp và thu nhỏ JavaScript

Thậm chí chỉ với vài từ mỗi lệnh sẽ nhanh chóng trở nên chán ngắt xuyên suốt quá trình tạo site điển hình.

Đây là lúc "Task Runners" xuất hiện hữu dụng. Với task runner bạn có thể thiết lập một file đơn lẻ bên trong dự án của bạn, nó định nghĩa tất cả những nhiệm vụ bạn cần để chạy trong dự án của bạn, và thự tự bạn cần phải chạy chúng. Trong file này bạn có thể dịnh nghĩa những lệnh riêng bạn có thể xử lý tất cả những lệnh đó một lần.

Bạn sẽ học cách thiết lập task runner theo cách này xuyên suốt hướng dẫn này, và trong quá trình bạn sẽ thấy một ví dụ dùng những script từ Bower package để triển khai hiệu quả cho dự án của bạn.

Chú ý: hướng dẫn này giả định bạn đã hoàn thành tất cả hướng dẫn trước đó trong loạt bài này. Nếu bạn chưa hoàn thành chúng, bạn sẽ thấy hữu ích khi xem kỹ chúng trước khi bắt đầu ở đây.

Hai task runner lớn nhất

Thực sự hiện giờ có vài task runner, tuy nhiên mục đích của hướng dẫn này là sẽ tập trung vào hai cái phổ biến nhất: GruntGulp.

Có nhiều điểm khác biệt về kỹ thuật giữa hai dự án, nhưng chúng ta không tìm hiểu vào lúc này. Tôi cũng không nói rằng bạn phải sử dụng cái nào. Thay vào đó, tôi khuyên bạn làm theo các bước sử dụng bên dưới sau đó tự quyết định bạn thích dự án nào hơn.

Tạo một dự án mẫu

Chúng ta sẽ tạo ra một dự án để theo dõi và tự động biên dịch Stylus và Jade, và tối ưu CSS và JavaScript. Chúng ta sẽ đạt được điều này bằng Grunt, và sau đó (trong hướng dẫn tiếp theo) sử dụng Gulp.

Để bắt đầu, chúng ta sẽ thiết lập một dự án mẫu với vài file và task runner của ta sẽ vận hành nó. Tạo một thư mục tên "Grunt Project", sau đó tạo một thư mục con tên là "build" và thư mục con tên "source".

Trong thư mục "source" bổ sung hai thư mục con mới tên "stylus" và "jade". Bổ sung vài file mẫu có kiểu thích vào vào mỗi thư mục.

Các file này chứa code bất kỳ bạn muốn, vì vậy bạn có cái gì đấy để có thể nhìn thấy quá trình biên dịch hoạt động.

Lời khuyên: nếu bạn không biết thêm vào code gì, hãy thử lấy vài code mẫu từ Codepen: pen tagged stylus, pens tagged jade.

Ví dụ:

Sau đó chúng ta sẽ tận dụng điều ta đã được học về Bower trong bài học trước đó và tải về jQuery và Mondernizr, chúng ta sẽ biên dịch và thu gọn chúng sau đó.

Chạy các lệnh sau:

1
bower install jquery --save
1
bower install modernizr --save

Giờ hãy sao chép toàn bộ thư mục dự án mẫu và đặt tên lại thành "Gulp Project".

Bằng cách này, Bạn có thể làm theo các bước với Grunt trong thư mục "Grunt Project", và các bước với Gulp trong thư mục "Gulp Project".

Bắt đầu với Grunt

Cài Grunt CLI

Để cho lệnh Grunt hoạt động bạn sẽ cần cài đặt CLI - Command LIne Interface (giao diện dòng lệnh). Cài đặt toàn cục với:

1
[sudo] npm install -g grunt-cli

Thiết lập dự án cho Grunt

Bổ sung file package.json

Mỗi dự án sử dụng Grunt sẽ cần một file package.json" trong thư mục gốc.

Chúng ta đã nói về viêc thiết lập file "package.json" bằng lệnh npm init trong hương dẫn trước Taming 3rd Party Package. Nếu bạn chưa hoàn thành phần đó, vui lòng quay lại và làm theo.

Cài đặt Grunt package.

Cài đặt Grunt vào dự án của bạn và lưu nó thành development dependency với:

1
npm install grunt --save-dev

Thêm Gruntfile

Mỗi dự án Grunt cũng sẽ cần phải có Gruntfile trong thư mục gốc.

Gruntfile là file có tên "Gruntfile.js", hoặc "Gruntfile.coffee" nếu bạn thích viết bằng CoffeeScript. Trong trường hợp này, ta sẽ làm việc với JavaScript, vậy bổ sung một file có tên "Gruntfile.js" cho thư mục gốc của bạn.

Đưa vào nội dung vào Gruntfile sẽ cho phép bạn để quyết định các lệnh nào sẽ kích hoạt task nào sẽ được chán. Bạn có thể bắt đầu bổ sung vào shell cơ bản trong Gruntfile. Chúng ta sẽ thiết lập cấu hình thực sự sau đó.

Bổ sung code sau đây và Gruntfile.js:

1
module.exports = function(grunt) {
2
3
};

Cài đặt plugin cho Grunt

Bạn sẽ nhớ rằng khi nào bạn muốn sử dụng package với npm hoặc Bower, bạn phải tìm đúng chỗ để lấy các phiên bản thiết kế phù hợp với mỗi hệ thống.

Bạn sẽ Khi dùng những package với grunt Thông qua Grunt bạn có thể truy xuất một hệ sinh thái các plugin, chúng là wrapper quan trọng cho những npm package thuần tuý. Những plugin này vẫn được npm phân phối, nhưng chúng đặc biệt được dùng với Grunt.

Ví dụ, thay vì dùng package Uglify của npm, bạn có thể dùng plugin "grunt-contrib-uglify" của Grunt.

Bạn có thể tìm plugin cho Grunt tại http://gruntjs.com/plugins

Đối với dự án của chúng tôi, chúng ta sẽ cài đặt 6 plugin Grunt này:

Mỗi plugin sẽ được cài đặt vào thư mục con "node_modules" của thư mục dự án của bạn và được lưu dưới dạng development dependency.

Chạy các lệnh này, từng lệnh một, với terminal của bạn chỉ vào thư mục “Grunt Project” của bạn:

1
npm install grunt-contrib-stylus --save-dev
1
npm install grunt-autoprefixer --save-dev
1
npm install grunt-contrib-cssmin --save-dev
1
npm install grunt-contrib-jade --save-dev
1
npm install grunt-contrib-uglify --save-dev
1
npm install grunt-contrib-watch --save-dev

Khi bạn hoàn tất, bạn sẽ thấy các thư mục này bên trong thư mục “node_modules” của dự án của bạn:

Kích hoạt plugin thông qua Gruntfile

Bây giờ chúng ta sẽ sử dụng phương thức grunt.loadNpmTasks để kích hoạt các plugin của chúng ta.

Bên trong dấu ngoặc nhọn của Gruntfile hiện tại của bạn, chúng tôi sẽ bổ sung 6 dòng, mỗi dòng kích hoạt mỗi plugin grunt, như vậy:

1
module.exports = function(grunt) {
2
3
// Load grunt plugins.

4
 grunt.loadNpmTasks('grunt-contrib-stylus');
5
 grunt.loadNpmTasks('grunt-autoprefixer');
6
 grunt.loadNpmTasks('grunt-contrib-cssmin');
7
 grunt.loadNpmTasks('grunt-contrib-jade');
8
 grunt.loadNpmTasks('grunt-contrib-uglify');
9
 grunt.loadNpmTasks('grunt-contrib-watch');
10
11
};

Code này đăng ký tên của mỗi plugin như một lệnh grunt, cho phép chúng ta dùng lệnh đó để bắt plugin để chạy một task: Ví dụ, chúng ta sẽ dùng lệnh grunt stylus để chạy stylus, grunt autoprofixer để chạy task autoprefixer và cứ thế.

Cấu hình các task trong Gruntfile

Các grunt plugin được cài đặt và các lệnh để dùng mỗi plugin sẵn sàng sử dụng, tuy nhiên nếu bạn sử dụng chúng ngay bây giờ bạn sẽ không thấy điều gì xảy ra. Lý do là chúng ta cần thiết lập một số cấu hình để xác định từng task thực sự nên làm gì.

Việc này được hoàn thành bằng cách bổ sung phương thức grunt.initConfig trong Gruntfile của bạn, và sau đó chuyển thông tin sang nó để biết cách thức mà bạn muốn mỗi task được chạy.

Đầu tiên, ta sẽ bổ sung phương thức grunt.initConfig trên những dòng mà bạn vừa mới thêm vào để tải các plugin của Grunt.

1
grunt.initConfig();

Giờ chúng ta sẽ đưa thông tin vào. Thêm vào ngoặc nhọn đóng và mở bên trong các dấu ngoặc thông thông, sau đó thêm vào một dòng trắng giữa họ:

1
grunt.initConfig({
2
3
});

Giờ chúng ta có thể tiếp tục bổ sung cấu hình cho mỗi plugin đã cài đặt.

Mỗi plugin có thông số riêng để bạn có thể sử dụng, và những chọn lựa này đã được trình bày chi tiết trên các trang có liên kết đến phần "Cài đặt plugin cho Grunt" ở phía trên.

Bạn cũng có thể đọc chi tiết về cấu hình task cho Grunt ở đây: http://gruntjs.com/configuring-tasks

Ví dụ cấu hình Grunt Task: Stylus

Chúng sẽ bắt đầu bằng việc bổ sung cấu hình cho task stylus.

Giữa hai dấu ngoặc nhọn bạn vừa thêm vào, ở dòng trống, bổ sung code sau đây:

1
    stylus: {
2
      compile: {
3
        options: {
4
          compress: false,
5
          paths: ['source/stylus']
6
        },
7
        files: {
8
          'build/style.css': 'source/stylus/main.styl'
9
        }
10
      }
11
    },

Gruntfile của bạn sẽ giống như vậy:

1
module.exports = function(grunt) {
2
3
  grunt.initConfig({
4
5
    stylus: {
6
      compile: {
7
        options: {
8
          compress: false,
9
          paths: ['source/stylus']
10
        },
11
        files: {
12
          'build/style.css': 'source/stylus/main.styl'
13
        }
14
      }
15
    },
16
17
  });
18
19
  // Load grunt plugins.

20
  grunt.loadNpmTasks('grunt-contrib-stylus');
21
  grunt.loadNpmTasks('grunt-autoprefixer');
22
  grunt.loadNpmTasks('grunt-contrib-cssmin');
23
  grunt.loadNpmTasks('grunt-contrib-jade');
24
  grunt.loadNpmTasks('grunt-contrib-uglify');
25
  grunt.loadNpmTasks('grunt-contrib-watch');
26
  
27
};

Hãy tỉ mĩ xem xét bên trong của code mà ta vừa bổ sung: Chúng ta sẽ không phân tách từng task, nhưng xem xét task này sẽ cho bạn khái niệm về kiểu cú pháp được sử dụng khi kết hợp cấu hình của Grunt task.

Như đã đề cập trước đó, mỗi plugin có chọn lựa cấu hình khác nhau vì thế khi bạn sử dụng một plugin mới, hãy xem kỹ phần hướng dẫn sử dụng mà nó cung cấp.

Điều đầu tiên chúng ta đã hoàn thành cho đến giờ là bổ sung một mục mới vào trong cấu hình cho task stylus trong code:

1
    stylus: {
2
3
    },

Trong đó chúng ta đã thêm mục complie để kiểm soát quá trình biên dịch:

1
    stylus: {
2
      compile: {
3
4
      }
5
    },

Trong task compile, chúng ta đã tạo ra khu vực options.

Chúng ta dùng khu vực này để xét chọn lựa compress thành false, bởi vì chúng ta sẽ thực hiện tối ưu code sau đó.

Chúng ta cũng xét tuỳ chọn paths thành ['source/stylus'] vì thế nếu stylus tìm thấy directives @import khi biên dịch nó sẽ tìm các file để import trong thư mục dự án "source/stylus":

1
    stylus: {
2
      compile: {
3
        options: {
4
          compress: false,
5
          paths: ['source/stylus']
6
        }
7
      }
8
    },

Sau khu vực options, chúng ta bổ sung thêm khu vực files để kiểm soát đường output directory và file name, cũng như input directory và file name.

Chúng ta xét vị trí của output của file CSS đã biên dịch thành 'build/style.css', khi file Stylus cần xử lý là 'source/stylus/main.styl'.

1
    stylus: {
2
      compile: {
3
        options: {
4
          compress: false,
5
          paths: ['source/stylus']
6
        },
7
        files: {
8
          'build/style.css': 'source/stylus/main.styl'
9
        }
10
      }
11
    },

Giờ khi terminal trỏ tới thư mục gốc của bạn, chạy lệnh sau:

1
grunt stylus

Xem bên trong thư mục "build" và bạn sẽ thấy file "style.css" đã biên dịch.

Cấu hình những task còn lại

Giờ chúng ta đã lướt nhanh qua phần cấu hình của từng task còn lại. Chèn mỗi block của code cấu hình vào sau mỗi code bạn đã bổ sung trước đó.

Autoprefixer

Thêm vào code sau:

1
    autoprefixer: {
2
      compile: {
3
        files: {
4
          'build/style.css': 'build/style.css'
5
        },
6
      },
7
    },

Chạy task autoprefixer với:

1
grunt autoprefixer

Nếu bạn xem xét file "build/style.css" giờ bạn sẽ thấy những prefix được thêm vào chỗ cần thiết.

cssmin

Thêm code này vào:

1
    cssmin: {
2
      clean: {
3
        files: {
4
          'build/style.css': 'build/style.css'
5
        }
6
      }
7
    },

Chạy task cssmin với:

1
grunt cssmin

Nếu bạn xem "build/style.css" của bạn lần nữa, bạn sẽ thấy nó đã được dọn sách và nén lại.

Jade

Thêm code sau vào:

1
    jade: {
2
      compile: {
3
        files: [{
4
          expand: true,
5
          cwd: "source/jade",
6
          src: "*.jade",
7
          dest: "build",
8
          ext: ".html"
9
        }]
10
      }
11
    },

Chạy task jade với:

1
grunt jade

Nếu bạn xem thư mục "build", giờ bạn sẽ thấy một flie HTML tương ứng với từng file Jade bạn có trong thư mục "source/jade".

Uglify

Thêm code sau vào:

1
    uglify: {
2
      bower_js_files: {
3
        files: {
4
          'build/output.min.js': [
5
            'bower_components/jquery/dist/jquery.js',
6
            'bower_components/modernizr/modernizr.js'
7
          ]
8
        }
9
      }
10
    },

Trong ví dụ này bạn sẽ thấy chúng tôi tham chiếu vị trí của các đối tượng Bower đã cài đặt trước đó.

Chúng ta sẽ lấy phiên bản mở rộng của jQuery và Modenizr ra khỏi thư mục "bower_components", sau đó kết hợp và thu gọn chúng thành một file mới "output.min.js". Đây là một cách tuyệt vời để triển khai các script bạn đang quảy lý với Bower.

Chạy task uglify với:

1
grunt uglify

Giờ bạn sẽ thấy file mới "output.min.js" trong thư mục "build".

Thêm task "watch"

Đến giờ có vẻ chúng ta chỉ thay thế một lệnh để thực hiện task cụ thể bằng một lệnh khác, nhưng điều chúng ta đã thực sự thực hiện hiện là sắp đặt nền tảng giúp Grunt thực sự bắt đầu phát huy.

Quan trong là khả năng của Grunt dùng một task để chạy một task khác. Vậy giờ chúng ta sẽ tiếp tục thiết lập task watch để theo dõi những thay đổi của các file cụ thể, sau đó tự động chạy các task stylusjade.

Thêm vào code sau:

1
    watch: {
2
      stylus: {
3
        files: [ 'source/stylus/*.styl' ],
4
        tasks: ['stylus', 'autoprefixer', 'cssmin']
5
      },
6
      jade: {
7
        files: [ 'source/jade/*.jade' ],
8
        tasks: ['jade']
9
      }
10
    },

Đầu tiên ta đã thêm vào task watch, sau đó trong đó chúng ta thiết lập mục cho stylus và cho jade.

Tuỳ chọn files trong mỗi nhóm thiết lập file nào sẽ được theo dõi các thay đổi. Tuỳ chọn task thiết lập các task nào nên được xử lý khi có thay đổi xảy ra, và theo thứ tự nào.

Với stylus, chúng ta thiết lập task watch để giám sát tất cả file ".styl" trong thư mục "source/stylus", vài khi nó thấy có thấy đổi nó sẽ chạy tuần tự các task: stylus, autorprefixer, và cssmin.

Vậy giờ khi task watch đang chạy, tất cả bạn cần phải làm là lưu các file Stylus và bạn sẽ tự động lấy được một file CSS đã biên dịch, có prefix và đã tối ưu ở trong thư mục "build".

Tương tự cho jade, chúng ta thiết lập các file ".jade" trong thư mực "source/jade" để giám sát, và bất kể khi nào một file được lưu trong task jade sẽ tự động chạy và biên dịch file HTML tương ứng trong thư mục "build".

Chạy task watch với:

1
grunt watch

Dừng nó lại:

  • Đóng terminal
  • Nhấn CTRL + C

Bổ sung task "default"

Ngay lúc này đây, có lẽ bạn đang tự hỏi, task JavaScript uglify làm gì?

Lý do chúng ta không kèm nó và task watch là bạn sẽ không thay đổi các file jQuery và Modenizr là task uglify thay đổi. Vậy bởi vì task watch chỉ phản hồi các thay đổi mà nó chưa bao giờ kích hoạt để xử lý JavaScript của bạn.

Thay vào đó, chúng ta sẽ sử dụng task default đã được xét trong Gruntfile. Đây là task sẽ chạy nếu bạn dùng duy nhất lệnh grunt.

Sau dòng sau cùng grunt.loadNpmTasks, nhưng trước }; của file, bổ sung dòng này:

1
  grunt.registerTask('default', ['stylus', 'autoprefixer', 'cssmin', 'jade', 'uglify']);

Dòng này xét task default để chạy stylus, autoprefixer, cssmin, jade và sau đó uglify.

Vậy giờ nếu bạn chạy chỉ chạy duy nhất lệnh grunt, thì nó sẽ build toàn bộ project, gồm cả JavaScript của bạn.

Trong hướng dẫn tiếp theo

Tiếp theo chúng ta sẽ lặp lại quá trình chúng ta vừa học, nhưng sử dụng Gulp để xử lý

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.