Trong bài viết này mình sẽ giới thiệu cho bạn cách cấu hình và cài đặt dùng Gulp trong VueJS. Trước khi bắt đầu bài viết này thì bạn nên đọc trước phần 1 và phần 2. Bài viết này là phần 3 tiếp tục trong chuỗi bài viết về cách cài đặt và cấu hình môi trường cho Vue. Trong bài viết này chúng ta sẽ sử dụng lại code trong những bài viết trước.
Gulp là gì
Gulp là một task runner dùng để chạy các task một cách tự động. Trong thế giới các ứng dụng Web javascript , Gulp là một công cụ hết sức tiện dụng giúp chúng ta có thể minify Javascript và CSS, nối các thư viện javascript, hoặc biên dịch các file SASS hoặc LESS. Gulp sử dụng Node.js như một nền tảng do đó bạn phải cài đặt Node.js trên máy của mình trước.
Tại sao sử dụng Gulp?
- Sử dụng file gulpfile.js là Javascript file và có thể viết các task sử dụng Javascript.
- Sử dụng SASS và LESS như một tiền xử lý CSS.
- Nó tương đối nhanh so với các task runner khác.
Đặc tính
- Hỗ trợ nối các file lại và minify Javascript
- Sử dụng code Javascript thuần tuý
- Chuyển đổi LESS và SASS thành CSS
- Quản lý các thao tác với file sử dụng memory và cải tiến tốc độ sử dụng Node.js
Cài đặt Gulp
Trước khi bắt đầu thì bạn cần download source code về trước trên github
Hãy mở terminal và di chuyển đến thư mục project mà bạn vừa tải về và gõ lệnh sau để cài đặt Gulp
$ npm install --save-dev gulp
Bạn có thể tìm hiểu thêm về Gulp ở đây
Sau khi cài đặt xong, hãy thử kiểm tra xem đã cài đặt được chưa bằng cách gõ lệnh sau
$ gulp --version [13:28:09] CLI version 2.0.1 [13:28:09] Local version 4.0.0
Chúng ta đã cài đặt thành công Gulp trong project, tiếp theo sẽ cần phải tạo một gulpfile.js
, Gulp sẽ đọc vào file này để chạy các task. Trong project này ngoài Vue và webpack, còn sử dụng cả chuẩn es6, nên thay vì tạo file gulpfile.js
, file sẽ đặt tên là gulpfile.babel.js
.
Sau khi tạo file gulpfile.babel.js
, sử dụng đoạn code sau đây để chạy thử một task bằng Gulp
function defaultTask (cb) { // place code for your default task here console.log('Run a task') cb() } exports.default = defaultTask
Chạy lệnh gulp để chạy task ở bên trên
$ gulp [13:31:12] Starting 'default'... Run a task [13:31:12] Finished 'default' after 1.99 ms
Như vậy chúng ta đã cài đặt và chạy thành công một task sử dụng Gulp
Cấu hình
Thông thường nếu project của bạn đơn giản thì chúng ta có thể viết hết tất cả các task vào trong gulpfile.js
. Nhưng nếu bạn muốn tạo nhiều task và nhiều tác vụ khác nhau như trong bài viết này sẽ cần chạy webpack và chuyển đổi scss thành css, nên chúng ta sẽ chia các task này ra thành từng module.
Nhưng trước khi module hoá các task thì bạn cần cài đặt package sau
$ npm install require-dir —save-dev
Bạn có thể tìm hiểu thêm về package tại đây
Tiếp theo mở lại file gulpfile.babel.js
và thay bằng đoạn code sau
var requireDir = require('require-dir') requireDir('./gulp/tasks', { recurse: true })
Tham số đầu tiên trong requireDir
là thư mục chúng ta chứa các task, recurse dùng để đệ qui các thư mục con. Mặc định nó sẽ được thiết lập là false
. requireDir tương đối là hữu ích, nó giúp cho các task có thể chia ra thành các module nhỏ thay vì phải đặt toàn bộ trong gulpfile.js
, nó sẽ tạo cho code trở nên phức tạp và khó hiểu
Do cấu hình ở trên, thư mục gulp/tasks là nơi chứa các file tasks. Nên chúng ta cần tạo thư mục này trong project
$ mkdir gulp $ cd gulp $ mkdir tasks
Nhưng trước khi tạo các tasks, tạo file config.js
trước để lưu trữ các biến dùng chung cho các task
const app = { srcDir: './src', srcFiles: './src/**', buildDir: './dist', releaseDir: './dist' } export default { app: app, script: { srcFiles: app.srcFiles + '/*.js' }, style: { srcFiles: app.srcFiles + '/**/*.scss', output: { filename: 'bundle.css' }, options: { outputStyle: 'expanded' }, prod: { options: { outputStyle: 'compressed' } } } }
File cấu hình sẽ chứa thông tin đường dẫn chứa các file sau khi chạy build, các thư mục code, các file scss, javascript
Task trong Gulp
Như đã nói ở trên chúng ta sử dụng ES6 cả trong các task của Gulp nên trước khi tạo các file task chúng ta sẽ cần cài đặt thêm một số package sau
$ npm install gulp-babel babel-preset-es2015 babel-plugin-transform-runtime --save-dev $ npm install gulp4-run-sequence del --save-dev $ npm install gulp-plumber gulp-notify gulp-sourcemaps --save-dev $ npm install gulp-cssnext gulp-sass gulp-concat —save-dev
- gulp-babel: Gulp plugin cho babel
- babel-preset-es2015: babel preset cho toàn bộ chuẩn es2015
- babel-plugin-transform-runtime: Cho phép sử dụng lại các code của babel
- gulp4-run-sequence: Cho phép chạy các task bất đồng bộ hoặc song song cùng một lúc
- gulp-plumber: Thay thế phương thức pip, loại bỏ chuẩn errorhandler trong error event
- gulp-notify: Plugin gửi thông báo cho Gulp
- gulp-sourcemaps: Hỗ trợ map source cho Gulp
- gulp-cssnext, gulp-sass: Chuyển đổi scss thành css
- gulp-concat: Nối các file sử dụng Gulp
Webpack cho client
Như ở phần trước, project hiện tại sử dụng webpack và chia làm 2 phần là client và server. Do đó, chúng ta cũng sẽ chia làm 2 module dùng để chạy webpack cho client và server
Hãy chuyển đến thư mục gulp/tasks và tạo file clientScript.js
import gulp from 'gulp' import webpack from 'webpack' import webpackConfig from '../../webpack.config' import merge from 'webpack-merge' gulp.task('clientScript', (done) => { const webpackRun = webpack(merge(webpackConfig, { devtool: '#source-map', plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"develop"' } }) ] })) webpackRun.run((err) => { if (err) { console.log('Error', err) } done() }) }) gulp.task('clientScript:release', (done) => { const webpackRun = webpack(merge(webpackConfig, { devtool: '#source-map', plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"' } }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } }), new webpack.LoaderOptionsPlugin({ minimize: true }) ] })) webpackRun.run((err) => { if (err) { console.log('Error', err) } done() }) })
Chúng ta tạo 2 task
- clientScript: Dùng để chạy ở phía local, nhưng trong bài viết sau chúng ta sẽ tìm hiểu làm thế nào để sử dụng và chạy nó trên máy của mình
- clientScript:release: Thực hiện build javascript client sử dụng webpack.
Chúng sẽ cần import webpack.config
ở thư mục bên ngoài và sau đó dùng webpack để load cấu hình vào, sau đó chạy run để webpack thực hiện build file javascript cho phía client theo câú hình đã cài đặt ở bên ngoài trong file webpack.config
Hãy thử chạy câu lệnh sau để kiểm tra xem task có hoạt động hay không
$ gulp clientScript:release
Sau khi chạy xong, bạn sẽ thấy một file bundle.js
được sinh ra trong thư mục dist
. Như vậy là chúng ta đã tạo xong được một task thành công
Webpack cho server
Tương tự như phần client, chúng ta sẽ tạo một task để chạy webpack cho các file javascript của server
Hãy chuyển đến thư mục gulp/tasks và tạo file serverScript.js
import gulp from 'gulp' import webpack from 'webpack' import webpackConfig from '../../webpack.server.config' gulp.task('serverScript', (done) => { const webpackRun = webpack(webpackConfig) webpackRun.run((err) => { if (err) { console.log('Error', err) } done() }) }) gulp.task('serverScript:release', (done) => { const webpackRun = webpack(webpackConfig) webpackRun.run((err) => { if (err) { console.log('Error', err) } done() }) })
Chúng ta cũng tạo 2 task
- serverScript: Dùng để chạy trên máy phát triển
- serverScript:release: Thực hiện build javascript server sử dụng webpack.
Chúng sẽ cần import webpack.server.config
ở thư mục bên ngoài và sau đó dùng webpack để load cấu hình vào, sau đó chạy run để webpack thực hiện build file javascript cho phía server theo câú hình đã cài đặt ở bên ngoài trong file webpack.server.config
Hãy thử chạy câu lệnh sau để kiểm tra xem task có hoạt động hay không
$ gulp serverScript:release
Sau khi chạy xong, bạn sẽ thấy một file server.bundle.js
được sinh ra trong thư mục dist
. Như vậy là chúng ta đã tạo xong được một task cho server thành công
Chuyển đổi SCSS thành CSS
Chúng ta sẽ tạo một task dùng để chuyển đổi toàn bộ các file scss trong thư mục code thành css. Sau đó nối lại với nhau thành một file bundle.css
và minify lại
Tạo một file task với tên là style.js
trong thư mục gulp/tasks
import gulp from 'gulp' import sass from 'gulp-sass' import cssnext from 'gulp-cssnext' import plumber from 'gulp-plumber' import notify from 'gulp-notify' import sourcemaps from 'gulp-sourcemaps' import concat from 'gulp-concat' import config from '../config' gulp.task('style', done => { gulp.src(config.style.srcFiles) .pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') })) .pipe(sourcemaps.init()) .pipe(sass(config.style.options)) .pipe(cssnext()) .pipe(sourcemaps.write('.')) .pipe(concat(config.style.output.filename)) .pipe(gulp.dest(config.app.buildDir)) done() }) gulp.task('style:release', done => { gulp.src(config.style.srcFiles) .pipe(sass(config.style.prod.options)) .pipe(cssnext()) .pipe(concat(config.style.output.filename)) .pipe(gulp.dest(config.app.releaseDir)) done() })
Chúng ta cũng tạo 2 task
- style: Dùng để chạy trên máy phát triển
- style:release: Thực hiện chuyển đổi toàn bộ file scss thành css vào nối lại thành một file
bundle.css
sau đó thực hiện minify lại
Hãy thử chạy câu lệnh sau để kiểm tra xem task có hoạt động hay không
$ gulp style:release
Sau khi chạy xong, bạn sẽ thấy một file bundle.css
được sinh ra trong thư mục dist
. Như vậy là chúng ta đã tạo xong được một task để chuyển đổi scss thành css thành công
Xoá dữ liệu trước khi chạy task
Trước khi chúng ta chạy các task thì thông thường sẽ xoá hết các file trong thư mục dist
, nó giảm thiểu những lỗi hoặc rủi ro không mong muốn
Do đó, chúng ta sẽ tạo một task để thực hiện xoá bỏ toàn bộ các file trong thư mục dist
Tạo một task với tên là clean.js
trong thư mục gulp/tasks
import gulp from 'gulp' import del from 'del' import config from '../config' gulp.task('clean', cb => { return del(config.app.releaseDir, cb) }) gulp.task('clean:release', cb => { return del(config.app.releaseDir, cb) })
Chúng ta cũng tạo 2 task
- clean: Dùng để chạy trên máy phát triển
- clean:release: Xoá toàn bộ file trong thư mục build
Hãy thử chạy câu lệnh sau để kiểm tra xem task có hoạt động hay không
$ gulp clean:release
Sau khi chạy xong, bạn sẽ thấy toàn bộ dữ liệu trong thư mục dist
bị xoá
Chạy các task
Chúng ta đã tạo xong toàn bộ các task cần thiết cho bài viết này, nhưng không thể chạy từng task như trên được, do đó cần phải tạo một task giúp chúng ta chạy một lần và chạy tất cả các task trên cùng một lúc
Để thực hiện điều này, hãy tạo một file release.js
trong thư mục gulp/tasks
import gulp from 'gulp' import runSequence from 'gulp4-run-sequence' gulp.task('release', cb => { runSequence( 'clean:release', ['style:release', 'clientScript:release', 'serverScript:release'], cb ) })
Hãy thử chạy câu lệnh sau để kiểm tra xem task có hoạt động hay không
$ gulp release
Sau khi chạy xong, bạn sẽ thấy toàn bộ dữ liệu trong thư mục dist
bị xoá, sau khi các task kết thúc, tất cả các file được tạo ra bởi từng task nhỏ bên trên sẽ được sinh ra trong thư mục dist
Như vậy, chúng ta đã gần như cấu hình xong các task cần thiết sử dụng Gulp
Chạy project
Công đoạn build ra các file cần thiết đã xong. Giờ chúng ta cần cấu hình Node để thực hiện chạy các task của Gulp.
Mở file package.json
, và sửa lại phần script như sau
"scripts": { "start": "gulp release && npm run start-server", "start-server": "node server.js" }
Chúng ta thực hiện chạy các lệnh của Gulp trước để sinh ra các file cần thiết trong thư mục dist
. Sau đó thực hiện start server.js
Source code tham khảo trên github ở đây