Magento 2已经发布了一段时间了。我认识的大多数开发人员尚未参与Magento 2项目,然而,他们中的大多数人已经安装它并开始学习。

从github和社交媒体的评论以及与开发人员的聊天得出的结论是Magento 2 前端有很多问题,其中最重要的一个是:CSS预处理。

 

Magento 1

从前端开发人员的角度来看,大多数时间都是在做定制项目,Magento 1 CSS是小菜一碟。您可以通过XML包含CSS文件,例如,在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>

您可以使用(或不使用)任何你想要生成的文件。首先推出Magento 1.9的Madison Island主题是使用Sass预处理器来编译CSS。

 

它在Magento 2中如何工作?

在Magento 2中,您仍然可以通过XML添加CSS文件。现在看起来有点不同,但那是完全不同的故事

<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>

如果您查看默认Luma主题主页的来源,您可以看到主要的CSS文件位于/pub/static/frontend/Magento/luma/en_US/css/styles-l.css知道CSS和LESS文件实际存储在Theme目录中,文件是如何结束的?

请求流程

从图中可以看出,系统首先在pub/static目录中搜索文件如果文件存在那里,它会返回那个文件。

如果文件不在该文件夹中,系统将在您使用的主题中搜索它。如果它在那里找到它,它将在pub/static/…创建一个文件,其中包含指向主题中实际文件的符号链接。

如果系统在主题中找不到文件,它将搜索相同的文件,但是使用.less扩展名,然后整个LESS预处理将被启动,我们将在稍后介绍。

这个流程的第一步实际上意味着我们可以像在Magento 1中那样工作:通过XML添加css文件,系统将在pub/static或我们的主题中搜索它,如果找到了文件将使用该文件。至少会触发预处理。您可以假设使用任何您想要生成的CSS文件……

但是关于…?

但是,在这种情况下,您是根据Magento 2最佳实践编写代码的,扩展和主题不会“开箱即用”。

如果您想遵循规则,并保持主题模块化并与市场上的扩展兼容,您将使用内置的LESS预处理器。

 

减少预处理

LESS是预处理器,它扩展了CSS的功能,添加了变量,函数,混合或嵌套等功能,将其转换为类似于原始编程语言的功能。开发人员用LESS语法编写代码,最终编译为CSS。

对于Magento来说,重要的是要建立一个扩展或主题开箱即用的系统。客户可以自己安装扩展程序或主题,那就可以了。因此,他们必须想办法让扩展与主题进行通信,使样式继承或覆盖变得简单。这就是预处理的作用,例如,如果您的主题使用变量为h1颜色:

@heading-color: #00FF00;

在.less文件中:

h1 {
    color: @heading-color;
}

编译到这个:

h1 {
    color: #00FF00;
}

您可以编写一个可以使用相同颜色的扩展,甚至不知道该颜色是什么。

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

编译后的代码如下所示:

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

正如您所看到的,扩展开发人员可以使用相同的颜色,即使他实际上并不知道哪种颜色。

好了,现在你知道为什么Magento实现了预处理器,但你可能想知道为什么他们选择LESS,当你知道大多数前端开发人员使用更强大的Sass预处理器时?这里没有什么大不了的:在做决策时,LESS是唯一具有稳定PHP编译器的预处理器。

 

前端开发工作流程

在Magento 2中,有两种前端开发工作流模式:客户端和服务器端。这可以在Magento管理下进行配置 Stores > Configuration > Advanced > Developer > Frontend development workflow

客户端 - 通过本机less.js编译器在浏览器内部进行编译。

服务器端是默认工作流,是生产模式中唯一可用的选项,它使用Magento内置的PHP编译器。

LESS编译是如何工作呢?我们已经讨论过CSS文件请求流程。

  1. 系统搜索请求的.css文件。如果找到,预处理器将停止执行。
  2. 系统按照主题回退机制搜索具有.less扩展名的同一文件。如果找不到文件,预处理器将停止执行
  3. 读取.less文件的内容并解析@magento_import和默认的@import指令
  4. 使用主题回退机制将.less文件中的所有路径解析为系统中的相对路径。所有已解析的路径都存储在var/view_preprocessed/less目录中
  5. 所有源文件都传递给PHP编译器,生成的.css文件发布到pub/static/frontend/<Vendor>/<theme>/<locale>

 

@magento_import

默认LESS @import将指定文件的内容导入当前文件。它允许开发人员将他们的样式分解为更小的逻辑文件:

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

Magento在这里有一个问题,因为标准的LESS @import指令不知道回退机制,也不知道安装了哪些模块以及如何添加自己的.less文件。

他们通过添加// @ magento_import指令解决了这个问题,该指令允许包含多个具有相同名称的文件。这允许扩展开发人员通过module.less文件“插入”他们的样式。

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

为避免与默认LESS冲突,必须将@magento_import写为注释 - 带有两个斜杠。

这就是我所说的Magento预处理器,或者Sandro为什么被称之为Pre2processor

因此,当编译器选中@mageno_import时,在我们的示例中,它将根据回退规则查找主题中的所有source/_module.less文件。它将用默认的LESS @import指令替换@magento_import:

@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';
….

具有已解析路径的此文件将发布到var/view_preprocessed目录,然后传递给标准LESS编译器。

清洁,重装,等待,等待......

如您所见,当发出.css文件请求时,系统将在pub/static文件夹中搜索它。如果文件在那里,它将返回该文件。这意味着,如果您对主题中的.less或.css文件进行了任何更改,系统将无法识别它。您必须删除pub/static/ 文件夹中的文件,以便系统获取主题中.css文件中的更改。

此外,Pre2processor在var/view_preprocessed文件夹中生成了已解析路径的文件,因此如果您对.less文件进行任何更改,则还必须清除该文件夹。

这需要大量的清理工作……而且,编译需要很长时间,所以如果您在CSS中进行了更改并希望在浏览器中看到结果,则需要很大的耐心。

 

使用Grunt进行自动预处理

当发现这个工作流对于前端开发人员来说过于缓慢和痛苦时,Magento决定通过添加对Grunt任务运行器的支持来为这个过程添加自动化(和速度)。

Grunt是一个javascript任务运行器,可以帮助您实现重复性任务的自动化。在我们的例子中,那些将是:观察,编译,清理......

Magento 2带有内置的grunt任务,但在使用它之前需要采取一些步骤

Grunt的问题是我们使用node.js进行编译,它不知道主题回退机制,也不知道@magento_import是什么。幸运的是,有一个Magento CL指令:

bin/magento dev:source-theme:deploy

...基本上这样做:

  1. 解决所有后备路径
  2. 为源(.less)文件创建符号链接
  3. 展开所有“@magento_import”以导入单个文件
  4. 将树中的所有文件发布到pub/static文件夹

现在,您已经将所有资源放在pub/static文件夹中,您可以监视更改并使用Grunt任务编译这些文件。

有几个任务可用:

  • grunt clean:<theme>
    • 从pub和var文件夹中删除静态文件
  • grunt exec:<theme>
    • 使用符号链接创建整个树,以及pub / static / frontend / vendor / theme / web中的源.less文件
  • grunt less:<theme>
    • 使用pub文件夹中发布的符号链接编译.css文件
  • grunt watch
    • 观察源.less文件中的更改,编译.css并在浏览器中注入新样式而不刷新页面(例如通过Livereload)

请注意,这些任务中的大多数只是bin/magento指令的包装器。

这种方法有一些奇怪之处。如前所述,node.js不知道magento风格的LESS,因此如果您对根LESS文件(styles-l.less)进行更改或者添加,删除或重命名导入的.less文件,您将不得不重新构建整个树。这意味着 - >停止观察者 - > grunt exec - > grunt watch。

使用grunt进行编译需要aprox。8-10秒,取决于.less文件的大小,这与PHP编译器相比是一个很大的进步。