详解如何在微信小程序中愉快地使用sass


Posted in Javascript onJuly 30, 2018

前言

在微信小程序中,css是用wxss来表示,但写法基本一致。需要注意的是wxss扩展了两个特性,分别是:

  • 尺寸单位
  • 样式导入

具体可参考wxss,此处不做过多赘述。

为了方便打包sass,我们使用gulp来处理我们的scss文件,将其转换为wxss。

目录结构

在开发中,我们一般会有一个src源代码目录,一个dist目录用来输出我们打包的代码。而本次讲解用到的目录结构如下:

详解如何在微信小程序中愉快地使用sass

  • build目录用来配置我们的打包参数,目前里面只有一个config.js文件
  • dist目录为打包输出的目录,也是小程序运行的目录
  • gulpfile.js配置打包的任务
  • src就是我们的源代码目录

src的目录结构如下:

详解如何在微信小程序中愉快地使用sass

安装依赖

yarn add gulp gulp-sass gulp-rename gulp-replace gulp-tap gulp-clean -D

gulp和gulp-sass为打包sass必须,gulp-rename则负责把scss后缀改为wxss,gulp-replace负责内容的替换(这个后面会讲到),gulp-tap用来处理当前执行的文件,gulp-clean负责清除我们不需要的文件。

sass打包配置

gulp配置打包sass非常简单,代码如下:

const gulp = require('gulp');
const sass = require('gulp-sass');
const rename = require('gulp-rename');

gulp.task('sass', () => gulp.src('./src/**/*.{scss,wxss}')
  .pipe(sass().on('error', sass.logError))
  .pipe(rename({
    extname: '.wxss'
  }))
  .pipe(gulp.dest('./dist'))
);

这样就可以完成了sass的配置,但是这样会有问题。前面讲到了wxss是支持样式导入的,也就是说import语法wxss是支持的,但css不支持,因此sass打包会把import的文件打包到当前文件,从而导致当前文件的体积变大。由于微信限制单包代码不能超过2M,因此当css越写越多的时候,这种打包方式势必会使样式文件越来越大。

解决import导入问题

那如何解决import的导入问题呢,其实也比较简单,说白了就是sass处理的时候,让其不处理import部分的语句就可以了。有两种方式可以做到,第一种是改写sass处理的源码,当遇到import语句时跳过。第二种是,在把文件交给sass处理前,我们先把import语句部分注释掉,这样sass处理的时候就会忽略了,当sass处理完成后,再把注释掉的语句打开即可。显然第一种成本比较高,也不好维护。我们采用第二种,代码如下:

const gulp = require('gulp');
const sass = require('gulp-sass');
const replace = require('gulp-replace');
const rename = require('gulp-rename');
const clean = require('gulp-clean');
const tap = require('gulp-tap');
const path = require('path');

const config = require('./build/config');

const hasRmCssFiles = new Set();
gulp.task('sass', () => gulp.src('./src/**/*.{scss,wxss}')
  .pipe(tap((file) => {
    // 当前处理文件的路径
    const filePath = path.dirname(file.path);
    // 当前处理内容
    const content = file.contents.toString();
    // 找到filter的scss,并匹配是否在配置文件中
    content.replace(/@import\s+['|"](.+)['|"];/g, ($1, $2) => {
      const hasFilter = config.cssFilterFiles.filter(item => $2.indexOf(item) > -1);
      // hasFilter > 0表示filter的文件在配置文件中,打包完成后需要删除
      if (hasFilter.length > 0) {
        const rmPath = path.join(filePath, $2);
        // 将src改为dist,.scss改为.wxss,例如:'/xxx/src/scss/const.scss' => '/xxx/dist/scss/const.wxss'
        const filea = rmPath.replace(/src/, 'dist').replace(/\.scss/, '.wxss');
        // 加入待删除列表
        hasRmCssFiles.add(filea);
      }
    });
    console.log('rm', hasRmCssFiles);
  }))
  .pipe(replace(/(@import.+;)/g, ($1, $2) => {
    const hasFilter = config.cssFilterFiles.filter(item => $1.indexOf(item) > -1);
    if (hasFilter.length > 0) {
      return $2;
    }
    return `/** ${$2} **/`;
  }))
  .pipe(sass().on('error', sass.logError))
  .pipe(replace(/(\/\*\*\s{0,})(@.+)(\s{0,}\*\*\/)/g, ($1, $2, $3) => $3.replace(/\.scss/g, '.wxss')))
  .pipe(rename({
    extname: '.wxss',
  }))
  .pipe(gulp.dest('./dist')));

在处理import的时候,还有个地方是需要注意的。在sass中,import除了能引入css外,也可以引入变量,函数。因此,我们在处理的时候也需要注意区分,变量和函数最好有一个独立的文件目录存放,并且在import的时候,对于变量和函数,是必须交给sass处理的,也就是不能注释掉。因此,在上面的代码中,我们可以看到,我们引入了build目录下的config,其配置了sass变量和函数存放的位置,这样我们在打包的时候,遇到这样的import语句,我们就跳过,交给sass处理,否则就代表其是引入了共用的样式文件,这样我们交给sass处理前,就先将其注释掉,sass处理完成后再把注释打开。另外,import的可能是一个scss文件,但在转成wxss的时候,已经将其后缀改为了wxss,因此,在将注释打开的时候也需要更改相应的引入,这也就是gulp-replace包的作用。config的配置如下:

module.exports = {
  cssFilterFiles: ['scss/var.scss'],
};

清理无用的wxss文件

前面讲了,我们在sass中可能会定义一些变量,函数,这些文件一会一并打包到dist目录,但其内容是空的,这时候我们就需要对其进行清理,前面在打包过程中,我们有一个set变量hasRmCssFiles记录了相应的文件,这样我们遍历这个变量即可删除相应的文件,代码如下:

gulp.task('clean:wxss', () => {
  const arr = [];
  hasRmCssFiles.forEach((item) => {
    arr.push(item);
  });
  return gulp.src(arr, { read: false })
    .pipe(clean({ force: true }));
});

总结

  • wxss的特性
  • sass打包配置以及如何处理import语句
  • sass变量、函数的文件清理

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Extjs学习笔记之七 布局
Jan 08 Javascript
一个简单的jQuery插件制作 学习过程及实例
Apr 25 Javascript
js运动框架_包括图片的淡入淡出效果
May 11 Javascript
JavaScript调试技巧之console.log()详解
Mar 19 Javascript
js实现select跳转功能代码
Oct 22 Javascript
基于jQuery插件实现环形图标菜单旋转切换特效
May 15 Javascript
基于bootstrap3和jquery的分页插件
Jul 31 Javascript
浅析在javascript中创建对象的各种模式
May 06 Javascript
BootStrap智能表单实战系列(十一)级联下拉的支持
Jun 13 Javascript
jquery判断对象是否为空并遍历对象的简单实例
Jul 26 Javascript
vue 项目打包时样式及背景图片路径找不到的解决方式
Nov 12 Javascript
稍微学一下Vue的数据响应式(Vue2及Vue3区别)
Nov 21 Javascript
详解JSON Web Token 入门教程
Jul 30 #Javascript
JS中Promise函数then的奥秘探究
Jul 30 #Javascript
浅析java线程中断的办法
Jul 29 #Javascript
还不懂递归?读完这篇文章保证你会懂
Jul 29 #Javascript
如何在js代码中消灭for循环实例详解
Jul 29 #Javascript
Vue-cli3项目配置Vue.config.js实战记录
Jul 29 #Javascript
vue权限路由实现的方法示例总结
Jul 29 #Javascript
You might like
隐藏你的.php文件的实现方法
2007/03/19 PHP
简单PHP上传图片、删除图片实现代码
2010/05/12 PHP
用php简单实现加减乘除计算器
2014/01/06 PHP
php中文验证码实现示例分享
2014/01/12 PHP
jquery 获取dom固定元素 添加样式的简单实例
2014/02/04 Javascript
javascript实现2048游戏示例
2014/05/04 Javascript
angularjs的一些优化小技巧
2014/12/06 Javascript
JavaScript跨平台的开源框架NativeScript
2015/03/24 Javascript
js实现从右向左缓缓浮出网页浮动层广告的方法
2015/05/09 Javascript
浅谈angularJS 作用域
2015/07/05 Javascript
JavaScript中数组添加值和访问值常见问题
2016/02/06 Javascript
JS基于MSClass和setInterval实现ajax定时采集信息并滚动显示的方法
2016/04/18 Javascript
Web前端开发之水印、图片验证码
2016/11/27 Javascript
vue-resouce设置请求头的三种方法
2017/09/12 Javascript
解读vue生成的文件目录结构及说明
2017/11/27 Javascript
Vue的elementUI实现自定义主题方法
2018/02/23 Javascript
微信小程序实现上传图片功能
2018/05/28 Javascript
JavaScript中BOM对象原理与用法分析
2019/07/09 Javascript
js如何获取访问IP、地区、当前操作浏览器
2019/07/23 Javascript
JavaScript监听触摸事件代码实例
2019/12/30 Javascript
Vue循环遍历选项赋值到对应控件的实现方法
2020/06/22 Javascript
解决vux 中popup 组件Mask 遮罩在最上层的问题
2020/11/03 Javascript
详解Vue3 Teleport 的实践及原理
2020/12/02 Vue.js
自己使用总结Python程序代码片段
2015/06/02 Python
Python扩展内置类型详解
2018/03/26 Python
python3中property使用方法详解
2019/04/23 Python
python tkinter 设置窗口大小不可缩放实例
2020/03/04 Python
解决pytorch 交叉熵损失输出为负数的问题
2020/07/07 Python
五分钟学会怎么用Pygame做一个简单的贪吃蛇
2021/01/06 Python
托管代码(Managed Code)和非托管代码(Unmanaged Code)有什么区别
2014/09/29 面试题
会计专业求职信范文
2014/03/16 职场文书
学前班评语大全
2014/05/04 职场文书
“四风”问题整改措施和努力方向
2014/09/20 职场文书
学院党的群众路线教育实践活动第一阶段情况汇报
2014/10/25 职场文书
国富论读书笔记
2015/06/26 职场文书
科普 | 业余无线电知识-波段篇
2022/02/18 无线电