cnq 发表于 2017-2-23 11:29:28

我的LESS编译方案

背景
  近期项目前端决定使用less,简单介绍一下,详细信息有兴趣查看官方文档(http://www.lesscss.net/article/home.html)
  LESSCSS是一种动态样式语言,属于CSS预处理语言的一种,它使用类似CSS的语法,为CSS的赋予了动态语言的特性,如变量、继承、运算、函数等,更方便CSS的编写和维护。
  简单来说,它自定义了一套语法规则,在css中提供公共变量的抽取,简单的函数运算等功能,最终通过编译器或解析器将其编译或解析为相对应的css代码。
  但是LESS文件在何时编译成为一个值得关注的问题,按照常规方式由几种方案

1、前端人员手工将less文件编译为css,并在页面引入css文件
  这种方案前端人员工作量会比较大,同时维护less文件和css文件,多人编辑同一个文件时很容易出错,并且多版本并行时合并代码不方便,一点点细微的改动都要重新编译文件

2、页面引入less文件,项目编译时使用插件统一进行预编译
  该方案要求所有开发人员都要安装编译环境(nodejs和less),并且文件修改后都要重新编译项目才能看到效果

3、页面引入less文件和js解析文件,在页面上将less解析为css
  其实对于互联网项目来说,这种方式基本不会考虑在线上运营,执行效率太低

LESS的两种编译方式

1、页面引入js代码文件解析
  首先引入less代码



<link rel="stylesheet/less" href="example.less" />
  然后引入解析代码



<script src="lesscss-1.4.0.min.js"></script>
  解析代码会根据rel属性类型通过ajax方式拉取less代码,然后并解析成css后追加到页面


好处:不必安装less编译环境,同样可以使用less文件

缺点:在页面上解析代码,效率较低,受机器、网络影响较大
2、服务端预编译
  官方提供了基于node.js的编译工具lessc
  首先全局安装less



npm install -g less
  然后直接使用less编译即可



lessc example/example.less example/example.css

优点:服务端预编译,效率高,避免客户端解析延时。

缺点:需要安装node以及less环境,并且每次修改less后都需要将其编译为css文件方可见效
方案基本思路
  鉴于上述原因,经与前端商量后决定制定一套较为平衡的方案,即:
  开发环境使用方式1,不用所有开发人员安装环境,降低开发成本,避免每次修改后都编译
  其他环境使用方式2,预编译less文件,提高页面加载速度

方案概括


1、通过配置文件,添加一个区分开发环境和其他环境的标志位lessOn(比如开发环境为false,其他环境为true)

2、页面使用自定义标签引入less文件,通过区分lessOn的值来判断引入编译前的less文件还是编译后的css文件

  这里自定义标签代码就不贴了,举个例子:

  通过自定义标签引入文件"/less/example.less",在输出到页面前判断当前如果是服务器环境将其转为"/css/example.css"  

3、页面全局通过判断lessOn的取值决定是否添加对less.js的引入

  如果是开发环境则引入官方的js脚本用于页面解析,服务器环境则不引入  


<script src="lesscss-1.4.0.min.js"></script>

4、使用node.js编写工具脚本遍历指定目录、批量编译less文件






var fs = require('fs'),
path = require('path'),
exec = require('child_process').exec,
sourcePath, targetPath;
//获取命令行中的路径
process.argv.forEach(function (val, index, array) {
if (index == 2) {
sourcePath = val;
}
if (index == 3) {
targetPath = val;
}
})
var lessc = function (rootPath, targetPath) {
//取得当前绝对路径
rootPath = path.resolve(rootPath);
//目标路径绝对路径
targetPath = path.resolve(targetPath);
//判断目录是否存在
fs.exists(rootPath, function (exists) {
//路径存在
if (exists) {
//获取当前路径下的所有文件和路径名
var childArray = fs.readdirSync(rootPath);
if (childArray.length) {
for (var i = 0; i < childArray.length; i++) {
var currentFilePath = path.resolve(rootPath, childArray);
var currentTargetPath = path.resolve(targetPath, childArray)
//读取文件信息
var stats = fs.statSync(currentFilePath);
//若是目录则递归调用
if (stats.isDirectory()) {
lessc(currentFilePath, currentTargetPath);
} else {
//判断文件是否为less文件
if (path.extname(currentFilePath) === ".less") {
var newFilePath = path.resolve(targetPath, path.basename(currentFilePath, '.less') + ".css");
if (!fs.existsSync(targetPath)) {
fs.mkdirSync(targetPath);
}
console.log(newFilePath);
exec("lessc -x " + currentFilePath + " > " + newFilePath);
}
}
}
}
} else {
console.log("directory is not exists");
}
});
}
lessc(sourcePath, targetPath);
View Code   5、使用maven插件maven-antrun-plugin,在编译打包前执行第4部的脚本预编译less文件



<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configration>
<tasks>
<echo>
------------node less-compiler.js-------------
</echo>
<exec executable="node" dir="${project.basedir}/src/main/webapp/assets/less" failonerror="true">
<arg line="less-compiler.js${project.basedir}/src/main/webapp/assets/less
                    ${project.basedir}/src/main/webapp/assets/css"/>
</exec>
<echo>
------------compiler success-----------------
</echo>
</tasks>
</configration>
<goals>run</goals>
</execution>
</executions>
</plugin>
总结
  思路其实很简单,通过区分项目运行环境,兼得两种编译方式的优点
  任何工具都不应当直接拿来使用,通过合适的定制使其更加适合自身项目开发
页: [1]
查看完整版本: 我的LESS编译方案