Trong phần này tiếp tục nâng cao một chút những gì đã biết ở
Thiết lập Grunt chạy 1 tác vụ đơn giản
, chi tiết hơn về file cấu hình các tác vụ Gruntfile.js
. Nhớ tiếp tục sử dụng dự án myproject01
ở phần trước.
Target trong Gruntfile.js
Trong ví dụ trước ta đã tạo ra một target có tên build
cho tác vụ uglify
. Target là một tình huống, trường
hợp chạy tác vụ cụ thể, với mỗi tác vụ bạn có thể tạo ra nhiều target, sau đó tùy tình huống mà bạn muốn tác vụ chạy với target nào.
Trở lại file Gruntfile.js
cũ ta thêm vào một target tên là debug
với nội dung như sau:
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! Xuanthulab <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { files: { 'build/hello.min.js' : ['src/hello.js'] } }, debug: { files: { 'debug/hello_debug.min.js' : ['src/hello.js'] } } } }); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.registerTask('default', ['uglify']); //grunt grunt.registerTask('debug', ['uglify:debug']); //grunt debug grunt.registerTask('release', ['uglify:build']); //grunt release }
Ở trên ta đã thêm một target là debug vào, ở target này thì tạo ra file debug/hello_debug.min.js
từ file nguồn.
Vậy trong tác vụ uglify
có 2 target: build
và debug
Cũng để ý các hàm đăng ký tác vụ grunt.registerTask, có 3 trường hợp đăng ký tương ứng với 3 kiểu chạy lệnh grunt
Nếu chạy lệnh:
# grunt
Trường hợp này không chỉ ra tham số nào, nó sẽ chạy các tác vụ đăng ký trong default
, và trong đăng ký này
chỉ ra chạy tất cả các target của uglify
(do ['uglify']). Và kết quả chạy sẽ có cả build/hello.min.js
và
debug/hello_debug.min.js
Nếu chạy lệnh:
# grunt debug
Nó sẽ chạy các tác vụ đăng ký với tên debug
ở hàm grunt.registerTask
, nhìn vào trường hợp
này nó chỉ ra là chạy tác vụ uglify
với target là debug
. Do vậy kết quả sẽ chỉ là file: debug/hello_debug.min.js
Tương tự, nếu chạy lệnh:
# grunt release
Target build
sẽ thực hiện, và kết quả chỉ là file build/hello.min.js
Giờ bạn hãy thực hành lại các ví dụ trên, trước mỗi lần chạy grunt hãy xóa thư mục build
, debug
để
xem kết quả chạy task.
Tải code ví dụ dự án trên về bằng git
git clone git@github.com:xuanthulabnet/grunt-example.git cd grunt-example git checkout vd2.1 npm install
Thực hiện nhiều tác vụ
Phần này sẽ phức tạp hóa dự án lên một chút, giờ trong dự án myproject01
ngoài file nguồn src/hello.js
bạn tạo thêm một file nguồn JS nữa, giả sử tên là src/ab.js
, trong đó chứa đoạn mã JS bất kỳ nào đó do bạn viết,
ví dụ để phức tạp hóa một chút, bạn sẽ viết một lớp JS theo chuẩn ES6.
class User { constructor(name) { this.name = name; } showinfo() { console.log(this.name); } } var user = new User('xuanthulab'); user.showinfo();
Giờ bạn mong muốn thi hành các tác vụ sau trên target mặc định (tức là mỗi khi gõ lệnh grunt
không tham số):
- Nối nội dung 2 file nguồn
hello.js
vàab.js
thành một file lưu tạitmp/all.js
- Kiểm tra lại mã, cú pháp JS trong file
tmp/all.js
xem có cảnh báo, lỗi gì không, nếu không thì làm bước tiếp theo - Do JS bạn có viết với chuẩn ES6, bạn muốn tự động convert mã
tmp/all.js
sao cho tương thích ngược với các trình duyệt cũ không hỗ trợ ES6. Mã convert được lưu ởtmp/all_back.js
- File
tmp/all_back.js
được nén lại thành filebuild/hello.min.js
- Cuối cùng là xóa toàn bộ những file tạm lưu ra tại thư mục
tmp
Giờ ta sẽ thiết lập các package và cấu hình thi hành các tác vụ trên
1) Nối các file bằng concat
Tác vụ nối file concat
cung cấp bằng package plugin
grunt-contrib-concat (v 1.0.1), do vậy
cần thêm vào package.json
nội dung:
"grunt-contrib-concat": "~1.0.1"
Trong Gruntfile.js
thêm tác vụ concat
nối 2 file hello.js
, ab.js
thành file tmp/all.js
như sau:
concat: { build: { files: { 'tmp/all.js' : ['src/hello.js', 'src/ab.js'] } } },
2) Kiểm tra cú pháp Javascript
Để kiểm tra cú pháp JS, ta sử dụng package cung cấp tác vụ jshint
grunt-contrib-jshint (V 2.0.0)
thêm vào package.json
nội dung:
"grunt-contrib-jshint": "2.0.0"
Để kiểm tra cú pháp file tmp/all.js
thêm vào task vụ có tên jshint
jshint: { options: { '-W015': true, "esversion": 6 }, build: { src: ['tmp/all.js'] }, },
Dòng "esversion": 6
thiết lập chấp nhận code viết theo ES6.
3) Convert mã JS ES6 tương thích với phiên bản cũ
Để làm điều này ta sử dụng trình biên dịch JS có tên là Babel, đây là module phức tạp, đầu tiên bạn cài đặt core của nó bằng lệnh:
# npm install --save-dev @babel/core @babel/preset-env
Tác vụ sử dụng cung Babel
có tên là babel
cung cấp qua Package
grunt-babel (V 8.0.0),
thêm vào package.json
nội dung:
"grunt-babel": "^8.0.0",
Tạo ra tác vụ babel
để chuyển mã tmp/all.js
sang dạng tương thích với trình duyệt cũ
lưu tại tmp/all_back.js
babel: { options: { presets: ['@babel/preset-env'] }, build: { files: { 'tmp/all_back.js': 'tmp/all.js' } } },
4) Nén file JS
Nén file thì dùng tác vụ uglify
đã biết từ ví dụ trước
uglify: { options: { banner: '/*! Dòng này chèn vào đầu file <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { files: { 'build/hello.min.js' : ['tmp/all_back.js'] } }, },
5) Xóa file
Sua khi đã có hello.min.js
muốn xóa đi các file tạm, dùng đến tác vụ có tên clean
,
cung cấp qua package grunt-contrib-clean,
thêm vào package.json
nội dung:
"grunt-contrib-clean": "2.0.0"
Tác vụ clean
trong Gruntfile.js
diễn tả như sau:
clean: { build: { src: ['tmp/*'] }, }
Cuối cùng ta có các file package.json
hoàn chỉnh như sau:
{ "name": "my_project", "version": "0.1.0", "devDependencies": { "@babel/core": "^7.1.6", "@babel/preset-env": "^7.1.6", "grunt": "~0.4.5", "grunt-babel": "^8.0.0", "grunt-contrib-concat": "~1.0.1", "grunt-contrib-uglify": "~0.5.0", "grunt-contrib-jshint": "2.0.0", "grunt-contrib-clean": "2.0.0" } }
Gõ lệnh sau để cài các gói trên
# npm install
Gruntfile.js
hoàn chỉnh như sau:
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! Dòng này chèn vào đầu file <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { files: { 'build/hello.min.js' : ['tmp/all_back.js'] } }, }, concat: { build: { files: { 'tmp/all.js' : ['src/hello.js', 'src/ab.js'] } } }, babel: { options: { presets: ['@babel/preset-env'] }, build: { files: { 'tmp/all_back.js': 'tmp/all.js' } } }, jshint: { options: { '-W015': true, "esversion": 6 }, build: { src: ['tmp/all.js'] }, }, clean: { build: { src: ['tmp/*'] }, } }); //Nạp các plugin grunt.loadNpmTasks('grunt-babel'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-clean'); //Thực hiện 5 tác vụ mặc định grunt.registerTask('default', [ 'concat:build', 'jshint:build', 'babel:build', 'uglify:build', 'clean' ]); }
Giờ mỗi khi cần thực hiện 5 tác vụ trên để thu được file hello.min.js
bạn chỉ việc gõ grunt
từ dòng lệnh:
# grunt Running "concat:build" (concat) task Running "jshint:build" (jshint) task >> 1 file lint free. Running "babel:build" (babel) task Running "uglify:build" (uglify) task Running "clean:build" (clean) task >> 2 paths cleaned. Done, without errors.
Tải code ví dụ dự án trên về bằng git
git clone git@github.com:xuanthulabnet/grunt-example.git cd grunt-example git checkout vd2.2 npm install