Magento 2 đã được phát hành cách đây một thời gian. Nhiều developer mà tôi biết thì vẫn chưa làm việc với dự án thật. Tuy nhiên, hầu hết trong số họ đã cài đặt và trải nghiệm về Magento 2.

Từ các ý kiến trên github, phương tiện truyền thông và qua các cuộc trao đổi với các developer thì có kết luận rằng: Về phía Frontend của Magento 2 có nhiều vấn đề khó, một trong những vấn đề quan trọng nhất đó là: CSS preprocessing.

Magento 1

Từ quan điểm của một frontend developer, người mà phần lớn dành thời gian làm việc cho dự án của khách hàng, CSS trong Magento 1 thì thật dễ sử dụng. Bạn chỉ cần include file CSS trong file XML, ví dụ trong file page.xml:

<default translate="label" module="page">
	<block type="page/html" …… template="page/3columns.phtml">
		<block type="page/html_head" name="head" as="head">
			<action method="addCss">
                <stylesheet>css/styles.css</stylesheet>
            </action>
      	</block>
	</block>
</default>

Bạn có thể sử dụng bất cứ cách nào để tạo ra file CSS. Ví dụ Theme Madison Island trong Magento 1.9 sử dụng Sass preprocessor để biên dịch CSS.

CSS preprocessing hoạt động trong Magento 2 như thế nào?

Trong Magento 2, bạn vẫn sử dụng file CSS thông qua XML. Có điều có một chút khác biệt

<page>
	<head>
        <css src="css/styles-m.css" />
        <css src="css/styles-l.css" media="screen and (min-width: 768px)"/>
        <css src="css/print.css" media="print" />
    </head>
</page>

Nếu bạn view source của theme Luma mặc định ở trang homepage, bạn có thể thấy rằng những file CSS chủ yếu được đặt ở  /pub/static/frontend/Magento/luma/en_US/css/styles-l.css. Tuy nhiên những file CSS và LESS thực sự thì được đặt ở bên trong thư mục Theme, vậy tại sao lại có những file này?

Request flow 

Từ sơ đồ bạn có thể thấy rằng đầu tiên hệ thống sẽ tìm kiếm file .css bên trong thư mục pub/static. Nếu có file tồn tại thì nó sẽ được trả về.

Nếu không có file trong thư mục đó, hệ thống sẽ tìm ở bên trong theme bạn đang dùng. Nếu được tìm thấy, nó sẽ được tạo ở trong pub/static/... với liên kết symlink đến file gốc ở trong theme.

Nếu hệ thống cũng không tìm thấy file đó thì nó sẽ tìm kiếm những file tương tự nhưng với đuôi mở rộng là .less và LESS preprocessing sẽ hoạt động để tạo ra các file css, điều này chúng tôi sẽ đề cập sau.

Bước đầu tiên của tiến trình thực thi này là chúng ta có thể làm việc với Magento 2 giống cách chúng ta đã làm ở Magento 1: thêm file css thông qua  XML, hệ thống sẽ tìm file css ở bên trong pub/static hoặc ở trong theme, nó sẽ được dùng nếu được tìm thấy. Không có preprocessing nào được kích hoạt. Bạn hoàn toàn có thể dùng trực tiếp file CSS đó.

Tuy nhiên cách làm này không theo đúng chuẩn của Magento 2. Extension và Theme sẽ không hoạt động được tốt với nhau khi code theo cách này. Để Extension và Theme hoạt động được tốt, tương thích với nhau thì chúng ta nên sử dụng LESS preprocessor có sẵn trong Magento 2.

Less preprocessing

LESS là preprocessor, nó kế thừa các chức năng của CSS với những tính năng như: các biến, hàm, quy tắc minxin hoặc xếp chồng, việc trả về kết quả cũng giống như sử dụng CSS. Các developer viết code của họ ở bằng cú pháp của LESS, cuối cùng nó được biên dịch về CSS. Trong Magento, nó rất quan trọng để xây dựng hệ thống nơi mà các Extension hoặc Theme có thể hoạt động độc lập và người dùng có thể cài đặt Extension hoặc Theme vào trang web của mình và nó sẽ hoạt động tốt. Vì thế họ phải hình dung được cách để các Extension có thể  tương thích với Theme bằng cách kế thừa hoặc ghi đè. Đây chính là nơi các preprocessor được dùng. Ví dụ, bạn sử dụng biến cho h1:

@heading-color: #00FF00;

Và trong file .less:

h1 {
    color: @heading-color;
}

Sẽ được biên dịch thành:

h1 {
    color: #00FF00;
}

Bạn có thể viết một Extension với màu như vậy, có thể chưa biết màu đó là gì.

.my-heading {
    color: @heading-color;
}

Code được biên dịch sẽ trông như thế này:

.my-heading {
    color: #00FF00;
}

Như bạn thấy, lập trình viên viết Extension có thể sử dụng màu tương tự, mặc dù hiện tại anh ta không biết màu đó là gì.

OK, bây giờ bạn biết tại sao Magento thực thi preprocessor, bạn có thể tự hỏi rằng tại sao họ lại chọn LESS, trong khi có nhiều bộ CSS preprocessor khác?  Không có bí mật lớn nào ở đây cả: tại thời điểm phát hành Magento thì LESS là CSS preprocessor duy nhất với bộ biên dịch PHP ổn định.

Quy trình phát triển Frontend

Trong Magento 2, có sẵn hai kiểu trong quy trình phát triển Frontend: Client side và Server side. Đây là cấu hình đặt ở trong trang quản trị Magento: Store > Configuration > Advanced > Developer > Frontend development workflow

Client side - Biên dịch những gì xảy ra bên trong trình duyệt thông qua native less.js complier.

Server side là quy trình làm việc mặc định và tùy chọn chỉ có sẵn trong production mode. Nó sử dụng trình biên dịch PHP complier sẵn có trong Magento.

Tóm tắt lại tiến trình request file css:

  1. Hệ thống tìm file .css. Nếu tìm thấy, CSS preprocessor ngừng thực thi.
  2. Hệ thống tìm file tương tự với đuôi mở rộng là .less, theo cơ chế dự phòng theme. Nếu file không được tìm thấy, CSS preprocessor sẽ ngừng thực thi
  3. Đọc nội dung trong file .less, sau đó tách ra @magento_import và mặc định @import để điều hướng
  4. Phân tích tất cả các đường dẫn trong file .less để những đường dẫn tương đối ở bên trong hệ thống sử dụng cơ chế dự phòng theme. Tất cả các đường dẫn riêng được đặt ở thư mục var/view_preprocessed/less 
  5. Tất cả file nguồn được thông qua  bộ biên dịch PHP compiler và kết quả các file .css được đưa vào pub/static/frontend/<Vendor>/<theme>/<locale>

@magento_import

Mặc định LESS @import sẽ import nội dung những file cần dùng vào bên trong file hiện tại. Nó cho phép các developer phân chia style thành các file nhỏ hợp lý hơn:

@import "modules/global.less";
@import "modules/header.less";
@import "modules/search.less";
@import "modules/forms.less";
@import "modules/buttons.less";

Có một vấn đề gặp phải trong Magento, kể từ khi chuẩn điều hướng @import LESS không phải là cơ chế dự phòng, không module nào được cài đặt và làm thế nào để thêm file .less?.

Chúng được giải quyết bằng cách thêm dòng //@magento_import nó cho phép include nhiều file với tên giống nhau. Điều này cho phép các developer viết Extension có thể "ghim vào" đoạn style của họ thông qua file module.less

//@magento_import 'source/_module.less';

Để tránh xung đột với các file LESS mặc định thì @magento_import phải được viết giống comment - với hai dấu sược( / ).

Đây chính là những gì tôi gọi Magento Pre-preprocess.

Khi trình biên dịch chạy @magento_import, như trong ví dụ dưới đây,  chúng sẽ tìm kiếm tất cả các file source/_module.less ở trong theme theo quy tắc dự phòng. Và nó sẽ thay thế @magento_import với sự điều hướng LESS @import mặc định:

@import '../Magento_AdvancedCheckout/css/source/_module.less';
@import '../Magento_Bundle/css/source/_module.less';
@import '../Magento_Catalog/css/source/_module.less';
@import '../Magento_CatalogEvent/css/source/_module.less';
@import '../Magento_CatalogSearch/css/source/_module.less';
….

Những file này được xuất vào trong thư mục var/view_preprocessed, sau đó được bộ chuẩn biên dịch LESS tiếp nhận.

Cleaning, reloading, waiting, ...

Như bạn thấy khi người dùng yêu cầu file .css, hệ thống sẽ tìm nó ở trong folder pub/static. Nếu được tìm thấy, nó sẽ được trả về cho bạn. Nếu bạn thay đổi bất cứ điều gì trong file .less hoặc .css, hệ thống sẽ không nhận ra. Do đó bạn phải xóa file trong thư mục pub/static/folder để hệ thống nhận sự thay đổi ở trong file .css.

CSS preprocessor tạo ra những file trên trong đường dẫn thư mục var/view_preprocessed, vì thế nếu bạn có thay đổi điều gì ở trong file .less, bạn cũng phải xóa thư mục đó.

Việc biên dịch sẽ kéo dài, vì vậy nếu bạn thay đổi file css và muốn nhìn thấy kết quả trên trình duyệt, bạn phải kiên nhẫn.

Preprocessing tự động bởi Grunt

Khi tiến trình xử lý quá chậm cho các developer frontend, Magento đã quyết định tự động hóa (và tăng tốc) cho quá trình này bằng việc thêm sự hỗ trợ cho bộ xử lý của Grunt.

Grunt là một bộ xử lý dựa trên ngôn ngữ javascript, nó có tác dụng tự động hóa công việc lặp đi lặp lại. Trong trường hợp này sẽ là: xem, biên dịch, dọn dẹp...

Bộ xử lý Grunt đã được tích hợp sẵn vào Magento 2, nhưng bạn phải thực hiện một vài bước để có thể sử dụng nó.

Vấn đề của Grunt là nó sử dụng node.js để biên dịch, nó không nhận ra cơ  chế hoạt động dự phòng của theme và nó không biết @magento_import . Thật may mắn vì đã có bộ điều hướng Magento CLI.

bin/magento dev:source-theme:deploy

Nó sẽ làm những việc sau:

  1. Giải quyết các đường dẫn cơ chế dự phòng
  2. Tạo ra liên kết symlink cho file nguồn (.less)
  3. Mở rộng thêm "$magento_import" để import file nhỏ
  4. Xuất các file trong cây thư mục pub/static

Giờ đây tất cả các file ở trong cây thư mục pub/static, bạn có thể xem những sự thay đổi và sự biên dịch những file này sử dụng bộ xử lý Grunt.

Có vài lệnh xử lý Grunt có sẵn:

  • grunt clean:<theme> - Xóa những file static trong các folder pub và var

  • grunt exec:<theme> - Tạo cây thư mục với liên kết symlinks để chứa các file .less ở bên trong pub/static/vendor/theme/web

  • grunt less:<theme> - Biên dịch những file .css sử dụng liên kết symlinks được xuất ra ở folder pub

  • grunt watch - Xem những sự thay đổi ở bên trong file nguồn .less, quá trình biên dịch css và thêm vào những style mới mà không refresh trình duyệt

Với cách này có 1 vài nhược điểm như

  • Node.js không được nhận ra sự có mặt của LESS, vì thế trong trường hợp bạn thay đổi những file LESS gốc (style-l.less), bạn sẽ phải xây dựng lại cây thư mục một lần nữa.
  • Sự biên dịch với grunt chiếm khoảng 8-10s, điều này còn phụ thuộc vào kích cỡ của những file .less, tiến trình xử lý lâu hơn so với bộ biên dịch PHP compiler.

LESS thì không tốt hơn

Tổng thể về cách hoạt động CSS preprocessor trong Magento 2 ra sao. Như bạn có thể thấy bộ xử lý khá phức tạp và không hiệu quả. Hầu hết các dev frontend ngày nay đang sử sụng SASS kết hợp với Gulp. Đây là nguyên nhân hình thành cộng đồng với những project thú vị:

https://github.com/poddubny/magento2-gulp

https://github.com/SnowdogApps/magento2-frontools

Tôi đã thử dùng kết hợp với Gulp và biên dịch với Gulp chỉ chiếm 3-4s, tiết kiệm thời gian hơn so với biên dịch PHP và Grunt.

Theme  blank Sass:

https://github.com/SnowdogApps/magento2-theme-blank-sass

Nếu bạn lắng nghe ý kiến từ cộng đồng, hầu hết họ đang hỏi về sự kết hợp Sass + Gulp. Hoàn toàn tách biệt về phía Frontend, cho phép các developer sử dụng bất cứ tool nào họ muốn.

Tóm lại, những ý kiến tốt thì luôn được cộng đồng tranh luận và Magento 2 đang lắng nghe... Hy vọng rằng chúng ta sẽ sớm tìm ra giải pháp tốt nhất cho vấn đề này.

Bài viết được dịch từ  http://inchoo.net