微信小程序的 wxss 、阿里(li)旗下(xia)淘寶、支付寶小程序的 acss 等等語(yu)法很類似原生(sheng)css,但是在web開發里(li)用慣了動態(tai)css語(yu)言(yan),再寫(xie)回(hui)原生(sheng)css很不習(xi)慣,尤其是父子樣式(shi)的嵌套寫(xie)法非常繁(fan)瑣。
因此,我希望能有一個自動化構建方案,能夠簡單(dan)地將(jiang)scss轉換成小程(cheng)序的樣式語言。
以前寫微信小程序的(de)(de)依賴庫(ku)時用過,使用gulp編(bian)譯(yi),將源碼和編(bian)譯(yi)后的(de)(de)代碼分別(bie)放(fang)到(dao)(dao)src和dist兩個目(mu)錄。gulp會處理src下面(mian)的(de)(de)所(suo)有(you)文件,將其中的(de)(de)scss轉換成(cheng)css,并將其他所(suo)有(you)文件原封不動挪到(dao)(dao)dist下相應位置(zhi)。
這里就(jiu)不詳細(xi)說了,代碼參考 Wux 。
非常簡單(dan)直接,使用 Webstorm / IDEA 的 File Watchers 功能實(shi)時轉換。
確(que)保命(ming)令行(xing)輸入 sass -v 能出現版本(ben)號,安(an)裝過程略。
安裝(zhuang) File Watchers
到插件市場上搜索并安裝(已安裝則跳過)
現在安裝完插件打開項(xiang)目會(hui)自動(dong)彈(dan)出(chu)scss轉css的向導,方便了(le)很多。但還需要做一(yi)些修改,配(pei)置如下:
首(shou)先要將(jiang)生成文(wen)件的后綴名改掉,比(bi)如(ru)這里我的淘寶小程序就得是 acss 。
其次,將Arguments改為:
$FileName$:$FileNameWithoutExtension$.acss --no-cache --sourcemap=none --default-encoding utf-8 --style expanded 復制代碼
如果不加 --no-cache ,scss文(wen)件同目錄下會(hui)出現一個 .sass-cache 目錄。
如果(guo)不加 --sourcemap=none , scss文件(jian)同目錄(lu)下會出現一個 .map 文件(jian)。
如果不加 --default-encoding utf-8 , scss文件如果有中(zhong)文注釋轉換就會報錯。
style 可不加,這(zhe)里用(yong)的(de)是無縮進和(he)壓(ya)縮的(de)風格,反正(zheng)小程序打包發布時還會壓(ya),這(zhe)里保持可讀性。
現(xian)在這個(ge)(ge)scss轉換是單獨作用于項目的(de),如果新建一個(ge)(ge)小程序項目,就需要重新添加(不(bu)建議設置成global,容易誤傷(shang))。
注意到 File Watchers 列表的右側(ce)操作欄下方(fang)有(you)導(dao)入導(dao)出按鈕,可(ke)以(yi)將(jiang)現(xian)在(zai)配(pei)好的設(she)置導(dao)出保存,將(jiang)來新建項目時只要(yao)導(dao)入一(yi)下就行了。
之后(hou)還(huan)有(you)一(yi)個(ge)問題,如果我(wo)手動將編譯(yi)后(hou)的css(即(ji) wxss 或(huo)(huo)者(zhe) acss ,下略)文件刪除,scss文件不改動的話,就不會重(zhong)新(xin)編譯(yi)出(chu)css文件。 或(huo)(huo)者(zhe)萬一(yi)監聽失效或(huo)(huo)者(zhe)不夠及時,css還(huan)有(you)可能是舊的。 所以還(huan)需(xu)要(yao)一(yi)個(ge)命令(ling),用來將整個(ge)目(mu)錄(lu)下的scss文件統一(yi)轉換,確保(bao)沒有(you)遺漏和(he)保(bao)持代碼(ma)最新(xin)。
不過我看了(le)半天 sass 和 sass-convert 的文(wen)檔(dang),沒有找到一個可用的寫法,能讓命令行遍歷指(zhi)定(ding)目錄(lu)下的所(suo)有scss文(wen)件(jian),將其轉換成(cheng)css放(fang)到源文(wen)件(jian)所(suo)在目錄(lu),并且(qie)將后(hou)綴名(ming)改(gai)為 wxss 或者 acss 。
所以遍(bian)歷這個(ge)行為(wei)只(zhi)能交給nodejs來實現,代碼如下:
創建(jian)編譯腳本 build/scss-convert.js :
var path = require("path")
var fs = require("fs")
const { exec } = require('child_process')
const basePath = path.resolve(__dirname, '../')
function mapDir(dir, callback, finish) {
fs.readdir(dir, function(err, files) {
if (err) {
console.error(err)
return
}
files.forEach((filename, index) => {
let pathname = path.join(dir, filename)
fs.stat(pathname, (err, stats) => { // 讀取文件信息
if (err) {
console.log('獲取文件stats失敗')
return
}
if (stats.isDirectory()) {
mapDir(pathname, callback, finish)
} else if (stats.isFile()) {
if (!['.scss'].includes(path.extname(pathname))) {
return
}
callback(pathname)
}
})
if (index === files.length - 1) {
finish && finish()
}
})
})
}
mapDir(
basePath,
function (file) {
const newFileWithoutExt = path.basename(file, '.scss')
if (newFileWithoutExt.startsWith('_')) {
return // 按照scss規則,下劃線開頭的文件不會生成css
}
// exec可以讓nodejs執行外部命令
exec(`sass --no-cache --sourcemap=none --default-encoding utf-8 --style expanded ${file}:${newFileWithoutExt}.acss`, {
cwd: path.dirname(file) // 不寫這個會導致生成的文件出現在根目錄
}, (err, stdout, stderr) => {
if (err) {
console.log(err)
return
}
console.log(`stdout: ${stdout}`)
})
},
function() {
// console.log('xxx文件目錄遍歷完了')
}
)
在 package.json 里添加一條script:
"scripts": {
"scss": "node build/scss-convert",
},