Viblo Code
-1

Giơí thiệu về Elixir trong Laravel

Xin chào các bạn. Hôm nay mình sẽ giới thiệu với các bạn về Laravel Elixir. Cài đặt, làm việc cũng như tìm hiểu sâu về Elixir trong Laravel

Laravel Elixir

Giới thiệu

Laravel Elixir cung cấp một API gọn gàng và liền mạch cho việc tạo các Gulp task cho ứng dụng Laravel. Elixir cung cấp một số pre-processor phổ biến cho CSS và Javascript, cùng một số công cụ testing. Sử dụng móc nối hàm, Elixir cho phép bạn tạo các asset pipeline một cách liền mạch. Ví dụ:

elixir(function(mix) {
    mix.sass('app.scss')
       .coffee('app.coffee');
});

Nếu bạn từng cảm thấy khó khăn trong việc bắt đầu sử dụng Gulp và đóng gói asset, bạn sẽ yêu thích Laravel Elixir. Tuy nhiên, bạn không cần thiết phải sử dụng nó khi phát triển ứng dụng. Bạn hoàn toàn thoải mái chọn lựa công cụ đóng gói asset nào bạn muốn, hoặc thậm chi không dùng gì cả.

Cài đặt

Cài Node

Trước khi dùng Elixir, bạn phải đảm báo có NodeJS được cài trên máy của bạn.

    node -v

Mặc định, Laravel Homestead đã có sẵn tất cả mọi thứ; tuy nhiên, nếu bạn không sử dụng Vagrant, thì bạn có thể dễ dàng cài Node bằng cách download NodeJS tại trang chủ.

Gulp

Sau đó, bạn sẽ cần cài đặt Gulp vào trong nhóm thư viện global:

    npm install --global gulp

Nếu bạn sử dụng một hệ thống quản lý version, bạn có thể muốn chạy npm shrinkwrap để khoá các yêu cầu về NPM:

     npm shrinkwrap

Khi đã chạy lệnh này, bạn có thể thoải mái commit file npm-shrinkwrap.json lên source control.

Laravel Elixir

Việc còn lại là chỉ cần cài đặt Elixir! Đi cùng với bản cài mới đầy đủ của Laravel, bạn sẽ thấy một file package.json tại thư mục gốc. Hãy nghĩ đó tương tự file composer.json, chỉ khác là nó khai báo các dependency cho Node. Bạn có thể tiến hành cài đặt các dependency bằng cách chạy lệnh sau:

    npm install

Nếu bạn đang phát triển trên hệ điều hành Windows hay bạn đang trong VM trên host là Windows, bạn có thể cần chạy lệnh npm install với thông số --no-bin-links:

    npm install --no-bin-links

Chạy Elixir

Elixir được xây dựng dựa trên Gulp, vì thế, để chạy các Elixir task, bạn chỉ cần chạy lệnh gulp trên terminal. Thêm vào cờ --production vào câu lệnh để yêu cầu Elixir thực hiện minify CSS và Javascript:

    // Run all tasks...
    gulp

    // Run all tasks and minify all CSS and JavaScript...
    gulp --production

Theo dõi sự thay đổi của asset

Sẽ khá là bất tiện khi phải chạy lệnh gulp mỗi khi có sự thay đổi về assets, bạn có thể dùng gulp watch. Câu lệnh này sẽ tiếp tục chạy trên terminal và theo dõi sự thay đổi của asset, nếu phát hiện có sự thay đổi, hay file mới, thì asset sẽ lập tức được đóng gói lại:

    gulp watch

Làm việc với Stylesheets

File gulpfile.js trong thư mục gốc của project chứa tất cả các Elixir task. Elixir task có thể được móc nối liên tiếp để cho biết chính xác cách mà asset sẽ được đóng gói.

Less

Để đóng gói Less thành CSS, bạn có thể sử dụng hàm less. Hàm này lấy các file Less trong thư mục resources/assets/less. Mặc định, task sẽ đặt các file CSS đã đóng gói vào trong public/css/app.css:

elixir(function(mix) {
    mix.less('app.less');
});

Bạn cũng có thể gộp các file Less thành một file CSS:

elixir(function(mix) {
    mix.less([
        'app.less',
        'controllers.less'
    ]);
});

Bạn có thể thay đổi vị trí file CSS cuối cùng, bằng cách truyền vào tham số thứ hai trong hàm less:

elixir(function(mix) {
    mix.less('app.less', 'public/stylesheets');
});

// Specifying a specific output filename...
elixir(function(mix) {
    mix.less('app.less', 'public/stylesheets/style.css');
});

Sass

Hàm sass cho phép bạn đóng gói Sass thành file CSS. Với các file Sass lưu trong resources/assets/sass, bạn có thể sử dụng như sau:

elixir(function(mix) {
    mix.sass('app.scss');
});

Tương tự với hàm less, bạn có thể đóng gói nhiều file Sass thành một file CSS duy nhất, và chọn vị trí lưu file:

elixir(function(mix) {
    mix.sass([
        'app.scss',
        'controllers.scss'
    ], 'public/assets/css');
});

Plain CSS

Nếu bạn muốn gộp các file CSS thuần vào trong một file, bạn có thể sử dụng hàm styles. Các đường dẫn truyền vào trong hàm này là tương đối với thư mục resources/assets/css và file cuối cùng sẽ được lưu tại public/css/all.css:

elixir(function(mix) {
    mix.styles([
        'normalize.css',
        'main.css'
    ]);
});

Dĩ nhiên, bạn có thể thay đổi vị trí file kết quả vào một vị trí khác bằng cách truyền vào tham số thứ hai của hàm styles:

elixir(function(mix) {
    mix.styles([
        'normalize.css',
        'main.css'
    ], 'public/assets/css');
});

Source Maps

Source máp được kích hoạt sẵn. Vì thế, các file mà bạn đóng gói sẽ có một file *.css.map đi kèm trong cùng thư mục. Việc mapping này cho phép bạn theo dõi các CSS selector trên các file Sass, Less gốc khi thực hiện debug trên trình duyệt.

Nếu bạn không muốn sinh ra source maps, bạn có thể bỏ chúng đi trong cấu hình của Elixir:

elixir.config.sourcemaps = false;

elixir(function(mix) {
    mix.sass('app.scss');
});

Làm việc với Scripts

Elixir cũng cung cấp một vài hàm để giúp bạn làm việc với các file Javascript như đóng gói các file ECMAScript 6, CoffeeScript, Browserify, thu gọn, hay nối các file Javascript lại vào nhau.

CoffeeScript

Hàm coffee được dùng để đóng gói các file CoffeeScript thành file Javascript thuần. Hàm này nhận một chuỗi hay một mảng các file CoffeeScript tương đối trong thư mục resources/assets/coffee và tạo ra file app.js trong thư mục public/js:

elixir(function(mix) {
    mix.coffee(['app.coffee', 'controllers.coffee']);
});

Browserify

Elixir cũng cung cấp hàm browserify, cho phép bạn các lợi ích của việc require các module lên trình duyệt và sử dụng ECMAScript 6 và JSX.

Hàm này sẽ lấy các file script nằm trong thư mục resources/assets/js và sẽ tạo ra file public/js/main.js. Bạn có thể thay đổi vị trí output trong tham số thứ hai:

elixir(function(mix) {
    mix.browserify('main.js');
});

// Specifying a specific output filename...
elixir(function(mix) {
    mix.browserify('main.js', 'public/javascripts/main.js');
});

Mặc dù Browserify có sẵn Partialify và Babelify, bạn hoàn toàn có thể chọn cài thêm mà bạn muốn:

    npm install aliasify --save-dev
elixir.config.js.browserify.transformers.push({
    name: 'aliasify',
    options: {}
});

elixir(function(mix) {
    mix.browserify('main.js');
});

Babel

Hàm babel được sử dụng để đóng gói ECMAScript 6 and 7JSX thành Javascript thuần. Hàm này nhận một mảng các file trong thư mục resources/assets/js, và tạo ra một file all.js duy nhất trong thư mục public/js:

elixir(function(mix) {
    mix.babel([
        'order.js',
        'product.js',
        'react-component.jsx'
    ]);
});

Để chọn một vị trí output khác, bạn chỉ cần thêm vào tham số thứ hai. Đặc điểm và chức năng của hàm này hoàn toàn giống với mix.scripts(), chỉ trừ việc đóng gói Babel.

Scripts

Nếu bạn có nhiều file Javascript mà bạn muốn đóng gói thành một file, bạn có thể sử dụng hàm scripts.

Hàm scripts sẽ lấy tất cả các file trong thư mục resources/assets/js và tạo ra file Javascript cuối dùng tại thư mục public/js/all.js:

elixir(function(mix) {
    mix.scripts([
        'jquery.js',
        'app.js'
    ]);
});

Nếu bạn muốn tạo các tập hợp file scripts khác nhau, bạn có thể gọi nhiều hàm scripts.

elixir(function(mix) {
    mix.scripts(['app.js', 'controllers.js'], 'public/js/app.js')
       .scripts(['forum.js', 'threads.js'], 'public/js/forum.js');
});

Nếu bạn muốn gộp tất cả các scripts trong một thư mục, bạn có thể sử dụng hàm scriptsIn. File kết quả cuối cùng sẽ được đặt tại public/js.all.js:

elixir(function(mix) {
    mix.scriptsIn('public/js/some/directory');
});

Copy Files & Directories

Hàm copy được dùng để copy files và thư mục tới các vị trí mới. Tất cả đều ở vị trí relative tới thư mục gốc của project:

elixir(function(mix) {
	mix.copy('vendor/foo/bar.css', 'public/css/bar.css');
});

elixir(function(mix) {
	mix.copy('vendor/package/views', 'resources/views');
});

Versioning / Cache Busting

Nhiều lập trình viên muốn đóng gói assets với một timestamp hay token đặc biệt để ép trình duyệt phải load lại asset thay vì sử dụng file cache. Elixir có thể xử lý cho bạn bằng hàm version.

Hàm version nhận tên file relatie với thư mục public, và sẽ thêm vào một hash unique trong tên file. Ví dụ, tên file sinh ra sẽ có thể như thế này, all-16d570a6.css:

elixir(function(mix) {
    mix.version('css/all.css');
});

Sau khi tạo ra file được version, bạn có thể sử dụng hàm helper elixir bên trong views để lấy ra asset đã được hash. Hàm elixir sẽ tự động xác định tên file:

    <link rel="stylesheet" href="{{ elixir('css/all.css') }}">

Đánh version cho nhiều file

Bạn có thể truyền vào một mảng trong hàm version để đánh version cho nhiều file:

elixir(function(mix) {
    mix.version(['css/all.css', 'js/app.js']);
});

Sau đó, bạn có thể sử dụng hàm helper elixir để lấy link tới các file đã được hash. Chú ý là bạn chỉ cần truyền vào tên file đầy đủ mà không có hash vào hàm elixir.

    <link rel="stylesheet" href="{{ elixir('css/all.css') }}">

    <script src="{{ elixir('js/app.js') }}"></script>

BrowserSync

BrowserSync tự động refresh lại trình duyệt sau khi có cập nhật ở frontend. Bạn có thể sử dụng hàm browserSync để bảo Elixir bắt đầu một BrowserSync server khi chạy lệnh gulp watch:

elixir(function(mix) {
    mix.browserSync();
});

Sau khi chạy gulp watch, truy cập vào trang web sử dụng port 3000 để kích hoạt đồng bộ browser: http://homestead.app:3000. Nếu bạn đang sử dụng domain khác với homestead.app cho môi trường phát triển, bạn có thể truyền vào mảng options ở tham số đầu tiên cho hàm browserSync:

elixir(function(mix) {
    mix.browserSync({
    	proxy: 'project.app'
    });
});

Gọi các Gulp task có sẵn

Nếu bạn cần gọi tới các Gulp task từ Elixir, bạn có thể sử dụng hàm task. Ví dụ, tưởng tượng bạn có một Gulp task đơn giản chỉ hiển thị text khi được gọi:

gulp.task('speak', function() {
    var message = 'Tea...Earl Grey...Hot';

    gulp.src('').pipe(shell('say ' + message));
});

Nếu bạn muốn gọi task này từ Elixir, sử dụng hàm mix.task và truyền vào tên của task:

elixir(function(mix) {
    mix.task('speak');
});

Custom Watchers

Nếu bạn muốn đăng kí một watcher để chạy task riêng của bạn mỗi khi có file bị thay đổi, truyền vào một regular expression ở tham số thứ hai trong hàm task:

elixir(function(mix) {
    mix.task('speak', 'app/**/*.php');
});

Viết extensions riêng cho Elixir

Nếu bạn muốn xử lý linh hoạt hơn những gì mà hàm task của Elixir cung cấp, bạn có thể viết Elixir extension. Điều này cho phép bạn truyền vào một task riêng. Ví dụ, bạn có thể viết một extension như sau:

// File: elixir-extensions.js

var gulp = require('gulp');
var shell = require('gulp-shell');
var Elixir = require('laravel-elixir');

var Task = Elixir.Task;

Elixir.extend('speak', function(message) {

    new Task('speak', function() {
        return gulp.src('').pipe(shell('say ' + message));
    });

});

// mix.speak('Hello World');

Chỉ có vậy! Chú ý là phần logic của Gulp cần được đặt bên trong hàm được truyền vào ở tham số thứ hai trong hàm khởi tạo của Task. Bạn có thể đặt chúng ở đầu Gulpfile, hoặc tách chúng ra thành một file riêng. Ví dụ, bạn có thể để extension trong elixir-extensions.js, bạn có thể lấy file này trong Gulpfile như sau:

// File: Gulpfile.js

var elixir = require('laravel-elixir');

require('./elixir-extensions')

elixir(function(mix) {
    mix.speak('Tea, Earl Grey, Hot');
});

Custom Watchers

Nếu bạn muốn task của bạn được kích hoạt khi chạy gulp watch, bạn có thể đăng kí một watcher:

new Task('speak', function() {
    return gulp.src('').pipe(shell('say ' + message));
})
.watch('./app/**');

Dưới đây tôi đã giới thiệu cũng như cài đặt và làm việc với Elixir Laravel. Cảm ơn các bạn đã theo dõi. Nếu có bất kì thắc mắc gì hãy để lại comment ở phía dưới nhé.

Thao Khảo

https://laravel.com/docs/5.3/elixir


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.