该来的一天还是来了,两年前立的Flag还是到了,现在在跟进项目配套的小程序开发,但对于写惯了 Stylus 的我,真的是太煎熬了,每次都忘记写冒号和分号…
所以就想着翻翻开发文档看 .wxss
支持不支持CSS预处理器的写法,比如 SCSS
。明显这是不可能的,官方也没有计划支持,所以还是得自己动手。
大概看了一下大家的解决方案,和我想的一样,使用 Gulp 来自动化构建成 .wxss
文件。
一、抄脚本
首先呢,就是安装依赖,这次需要的依赖项有3个:gulp
、 gulp-rename
和 gulp-stylus
(也可以是 sass
或 less
)
npm init -y
npm i gulp gulp-rename gulp-stylus -D
然后创建 Gulp 脚本
最初我直接复制的肉大的脚本改了下,但是遇到了报错信息 TypeError: gulp.src(...).pipe(...).pipe is not a function
,Google 后是说,Gulp4 更新后,API调整过了,旧的写法不可以用了。
所以我先选择降低了 Gulp
版本到 v3.9.1
,降低版本后继续执行,遇到另一个报错信息 ReferenceError: primordials is not defined
,好像是 Node 版本太高了,切换到 11.15.0
可以运行了,但是 侦听文件改变 的部分还有问题,运行之后执行了两次,后边再修改就没有编译了,所以还是用 Gulp4
自己重新调整吧。
二、Gulp4 重写
const gulp = require('gulp');
const stylus = require('gulp-stylus');
const rename = require('gulp-rename');
// 样式文件地址,我设置了全部,排除了node_modules,你也可以自己选择指定目录
const stylusFiles = [
"./**/*.styl",
"!./node_modules/**/*.styl",
]
// 编译stylus并且重命名为.wxss,生成在原目录下
const styl2wxss = () => {
return gulp
.src(stylusFiles)
.pipe(stylus({ prefixer: false}))
.pipe(rename({ extname: '.wxss' }))
.pipe(gulp.dest('./'));
};
// 编译任务
gulp.task(styl2wxss);
// 监听任务
gulp.task('watch', () => {
gulp.watch(stylusFiles, styl2wxss);
});
// 如果你有多个任务比如同时使用pug与stylus,可以像这样放入series内,会自动依次执行
gulp.task('dev', gulp.series('styl2wxss', 'watch'));
然后把执行脚本加入到 package.json
中
"scripts": {
"watch": "gulp watch"
"dev": "gulp dev"
}
执行 npm run watch
或者 npm run dev
就可以了。
到这里位置一切都正常,但是我编译完成之后,小程序编译报错了,因为不能加私有兼容前缀,所以还得处理一下,看看 stylus
的配置文档。
2 hours later….
翻了好久文档也没找到解决办法,不过 stylus
提供了一个 vendors
属性,具体看 文档链接
把 vendors = official
加到文件头部就可以了,但是总觉得怪怪的不舒服,官方好像也没有想处理这个问题的念头?先不管了,之后看有没有遇到其它解决方案吧。
三、使用VSCode扩展
VSCode的扩吧展商店里已经有大佬上传了 Stylus/Sass/Less
转换成 wxss
的插件了,有直接安装就可以用的,而且我上边提到的编译后出现兼容前缀的问题插件转换后没有遇到,还不知道他们是如何解决这个问题的,等空了看看他们的源码怎么写的吧。
扩展
# 如何让图片 url 在编译时自动补全CDN路径?
本地资源图片无法通过
WXSS
获取,可以使用网络图片,或者base64
,或者使用<image/>
标签
现阶段的小程序是不允许在 wxss
中使用本地资源了,不然会报错。
如果用图片CDN,每次都输入全网络地址又太麻烦了,所以就想着有没有什么好一些的解决方式。
解决方案1:使用 stylus
全局变量。
例如我的全局变量文件位于 /assets/stylus/variables.styl
。
那么修改一下脚本文件就可:
const styl2wxss = () => {
return gulp
.src(stylusFiles)
.pipe(stylus({
prefixer: false,
import: path.join(__dirname,'./assets/stylus/variables.styl'),
}))
.pipe(rename({ extname: '.wxss' }))
.pipe(gulp.dest('./'))
};
就这可以这样书写了
// 例如变量名为 $httpUrl
.className
background url($httpUrl/img/bg_img.png) center/contain no-repeat
// 编译为
// background: url("http://www.domain.com/assets/img/bg_img.png") center/contain no-repeat;
解决方案2:stylus 编译成 css 自动处理补全 CDN 地址
虽然使用全局变量可以用,但是也不优雅,想着可以在 stylus
编译成 css
的时候同步处理补全 CDN 路径,在书写的时候只需要键入 url(/img/xxx.jpg)
就会得到对应的 CDN 地址 url(https://www.baidu.com/assets/img/xxx.jpg)
了。
但是找了一圈还没找到解决,思路有了得等有时间了尝试一下,先挖个坑。
附
使用 Pug 和 Stylus 开发小程序的 watch 脚本
gulp.js
Expressive, dynamic, robust CSS — expressive, robust, feature-rich CSS preprocessor
node.js - How to fix ReferenceError: primordials is not defined in node - Stack Overflow
Vendor prefixed properties WITHIN vendor prefixed @keyframes · Issue #882 · stylus/stylus
Bug in vendored keyframes · Issue #1135 · stylus/stylus