vlambda博客
学习文章列表

sass之gulp自动化构建,在原生小程序中使用sass语法

由于我的英文不好,所以在写css的时候,通常会因为class类名而烦恼,当页面变得复杂的时候,会被页面杂乱无章、毫无规范的css影响开发体验,这是我选择sass来编写原生小程序样式最主要的原因(主要是less忘光了,sass还记得一点)。


gulp扫盲:gulp.js - 基于流(stream)的自动化构建工具。




下面开始做一些环境准备:


全局安装gulp:

npm i gulp -g


在项目目录中安装项目的gulp:

npm i -y
npm i gulp

gulp会分全局和项目内(或者叫本地)两个,全局安装是安装gulp的命令,项目中进行安装是提供gulp对象、在gulpfile.js中引入gulp。安装两次gulp是node的机制问题,本地require不到全局的包。


在项目中安装sass编译相关的插件依赖:

npm i node-sass gulp-rename gulp-sass gulp-changed

如果node-sass安装失败的时候,请把npm的镜像更改为淘宝的镜像,因为npm默认会使用国外的镜像进行依赖安装,由于某些不可描述的因素,改成淘宝镜像可以避免安装时不必要的报错。


如果你是通过nvm安装node的,先找到nvm目录,然后找到nvm目录下面的setting.txt文件,加入这两行:

node_mirrorhttps://npm.taobao.org/mirrors/node/npm_mirrorhttps://npm.taobao.org/mirrors/npm/

不了解nvm的可以翻一下前两篇文章,有介绍相关操作步骤。


在你小程序项目的根目录下(app.js同级)新建一个gulpfile.js文件,这个命名不可更改,是gulp构建时自动执行的任务文件,下面先附上完整的gulpfile.js内容,可以直接用于开发,无需任何修改(前提是依赖已经安装完毕,包括chalk这个包):

const gulp = require('gulp');const sass = require('gulp-sass');const rename = require('gulp-rename');const changed = require('gulp-changed');
//这个只是为了输出的时候带上一些明显的颜色,非必要const chalk = require('chalk');
const log = console.log;
//自动编译gulp.task('auto', gulp.series(function() {  return miniSass(); // 注意,这里有个return,为何?下面解释}));
//手动编译gulp.task('sass', function(){ let date1 = new Date().getTime(); miniSass(date1);});
// 执行自动编译gulp.task('watch', function(){ gulp.watch('./pages/**/*.scss',gulp.series('auto'));// gulp 4.x写法});
// 编译function miniSass(date1){ return gulp.src('./pages/**/*.scss')//需要编译的文件 .pipe(sass({ outputStyle: 'expanded'//展开输出方式 expanded })) .pipe(rename((path)=> { path.extname = '.wxss' })) .pipe(changed('./pages'))//只编译改动的文件 .pipe(gulp.dest('./pages'))//编译 .pipe(rename((path)=> { //下面这段只是为了唉控制台输出一些东西,非必要      let date2 = new Date().getTime(); if(date1){ log(chalk.yellow('[' +new Date().getHours() + ':' + new Date().getMinutes() + ':' + new Date().getSeconds()+ ']')+ ' 编译完成文件:' + 'pages\\' + path.dirname + '\\' + path.basename + '.scss' + ','+chalk.green('耗时:'+(date2 - date1)/1000 + 's')) }else{ log(chalk.yellow('编译完成文件:' + 'pages\\' + path.dirname + '\\' + path.basename + '.scss')) } }))}

使用的时候,只需要在wxml所在的目录创建一个同名的scss文件即可,这个可以与wxss共存,比如你有一个项目已经进入开发了的,想中途引入sass,行不行呢?那是裤裆里着火 -- 当然啦。按照上面的做法,已经做好的页面不会受到scss的影响,因为上面的代码只是监听scss文件的变动,当你目录中不存在scss文件,wxss就自然不会受到影响。


编译命令有两个,一个是手动编译:gulp sass;一个是自动编译:gulp watch。手动编译的话控制台的输出会干净很多,自动编译会打印很多无用的东西(但可以即时编译,无需再手动执行编译命令),可以根据实际来取舍。


如何定义一些全局的scss变量?一般是在app.js同级目录下新建一个scss文件,以“_”开头(比如:_base.scss),把一些全局的样式放在这个文件中,在需要使用的地方,通过import引入即可,例如:

// _base.scss$fs:20rpx;
//index.scss@import './base.scss';.title{ font-size:$fs;}

细心的gay会发现,命名的时候有下划线,为什么导入的时候不需要呢?

这是gulp插件做了一层定义,当你以下划线开头的,会不进行编译,但导入的时候不需要写下划线。


sass之gulp自动化构建,在原生小程序中使用sass语法


sass之gulp自动化构建,在原生小程序中使用sass语法


当你在scss文件中写了不存在的(未定义的)样式变量的时候,控制台会提醒你的,如上图。图中的son.wxss是gulp构建生成的。


到这里,在原生小程序中使用sass基本已经没有什么障碍了,在提交代码到小程序后台的时候,scss文件是不会被提交的,所以不用担心引入sass后会被scss文件占用了包的空间大小。最后,在这里解释一下,上面那个gulpfile.js文件中,自动编译任务里面为何要写个return,而手动编译却不用:


因为gulp使用了node的异步完成(Async Completion),需要一个任务完成信号(Signal task completion)去通知gulp,然后gulp去决定是继续后续任务(task),还是结束。当你不写return的时候,去执行watch监听,只会进行第一次编译,后面的所有改动将不再进行编译,因为你没有使用任何模式或者方式去通知gulp任务已经完成了,所以gulp不会再执行。

解决办法很简单:因为我们创建的gulp任务使用的是node的streams模式,返回此任务(task)的stream即是一种通知,所以我们只需要 return 就解决了。



注意:当你在项目使用scss文件的时候,会自动编译出一个同名的wxss文件,千万不要尝试在编译出来的wxss进行样式的编写,否则当你改动scss文件的时候,会清除未在scss文件中存在的所有样式。