極致追求,讓小程序代碼包立減 10% 的插件 weapp-css-modules

做者:凹凸曼-冥冥javascript

小程序的簡化版 css-modules,比標準 css-modules 代碼量更少的優化方案css

介紹

css-modules 是一種 css 模塊化方案,它在構建過程當中生成一個原類名與新類名的 map,根據 map 引用樣式,經過設定 hash 規則,實現了對 CSS 類名做用域的限定,它一般用來解決頁面類名衝突的問題。因爲微信小程序內組件樣式默認隔離,爲何要使用 css-modules 呢?java

有如下 2 個緣由:webpack

  • hash 化後能夠實現更短的命名,減小代碼包體積
  • 跨端項目須要兼顧非小程序環境,避免樣式衝突

weapp-css-modules 作了哪些事?git

  • 新類名單字母編排,減小代碼量
  • 移除類名映射 map,替換 js 和 wxml 中變量爲編譯後類名

標準 css-modules 方案:github

import style from './index.wxss'
<view class="{{style.banner}}"></view>
.index_banner_xkpkl { xx }
module.exports ={'banner' : 'index_banner_xkpkl'} // 額外生成的 map 文件

weapp-css-modules 編譯後效果:web

let style = {}
<view class="a"></view>
.a { xx }

安裝

目前只開發了適用於使用 gulp 編譯小程序的 gulp 插件,後續計劃開發 webpack 可用的插件實現相同功能npm

npm i gulp-weapp-css-modules gulp-sort
// gulpfile.js
const { weappCssModule, wcmSortFn } = require('gulp-weapp-css-modules')
const sort = require('gulp-sort');

gulp.task('css-module', () => {
    return gulp.src('./src/**/*')
        .pipe(sort(wcmSortFn))      // 因爲處理文件有順序依賴,須要先對文件排序
        .pipe(weappCssModule())
        .pipe(gulp.dest('./dist'))
})

使用

小程序頁面不具有隔離功能,所以只有具有樣式隔離的 Component 能夠改造使用 weapp-css-modulesgulp

一、css 文件更名字: weapp-css-modules 經過 css 文件是否帶 module 來識別須要替換的內容小程序

index.wxss -> index.module.wxss

// 或者使用 scss/其餘

index.scss -> index.module.scss

二、js 內新增樣式文件的引入,目的是創建 css-modules 的樣式與 js 關係

import styles from './index.module.wxss

data:{
   ...,
   styles:styles
}

三、修改 js 內類名的地方替換爲 styles 的間接引入

query.select('.banner')
.boundingClientRect()
.exec(function (res) {...})

// 改成
query.select('.' + styles['banner'])
.boundingClientRect()
.exec(function (res) {...})

四、修改 wxml 內類名的使用

4.1. 普通類名

<view class="banner"></view>
// 改成
<view class="{{styles.banner}}"></view>
// 或者
<view class="{{styles['banner']}}"></view>

4.2. 三目運算符

<view class="banner__dot {{ 'banner__dot--' + (index == swiperCurrent ? 'cur' : '')}"></view>

// 改成
<view class="{{styles['banner__dot'] + ' ' + (index == swiperCurrent ? styles['banner__dot--cur'] : '')}}"></view>
// 或者
<view class="{{`${style['banner__dot']} ${index == swiperCurrent ? style['banner__dot--cur'] : ''}`}}"></view>

這裏須要注意幾種有問題的寫法:

4.2.1. 類名間未加空格

<view class="{{styles['banner__dot'] + (index == swiperCurrent ? styles['banner__dot--cur'] : '')}}"></view>

4.2.2. 三目表達式未加括號,運算優先級不明

<view class="{{styles['banner__dot'] + ' ' + index == swiperCurrent ? styles['banner__dot--cur'] : ''}}"></view>

4.2.3. styles 的屬性須要是具體的字符串,不能使用變量表達式(這是 weapp-css-modules 須要單獨關注的地方,由於編譯階段會對 styles.xx 進行求值,因此不能把表達式寫在屬性位置)

<view class="{{styles['banner__dot'] + ' ' + styles[index == swiperCurrent ? 'banner__dot--cur': '']}}"></view>

五、構建過程當中關注腳本的紅色提示,相似於這種:

這是因爲在 js/wxml 內使用了一個banner__swiper_2,而 css 內並無定義banner__swiper_2,css-module 編譯的 map 文件是根據 css 內的樣式定義來生成 key 名的,所以styles['banner__swiper_2']undefined, 針對這種狀況有兩種處理方式:

5.1. 若是 js 內須要經過這個類名選擇到某個元素,可是 css 內不須要編寫樣式,那麼能夠將它視爲不須要編譯的類名,即:

query.selector('.banner__swiper_2') // 不改爲 styles.xx 的寫法
<view class="banner__swiper_2"></view> // 相應的元素也不索引到 styles
// 這樣實現了一個組件內不會被編譯的樣式

5.2. 若是 js 內無引用,那麼刪掉 wxml 內該類名的定義吧~

六、構建完進行檢查,關注樣式和交互是否正常

參考示例

  • gulp 項目:路徑 /demo/gulp-project-demo

聯繫反饋

  • 歡迎經過郵箱來跟我聯繫: smile123ing@163.com
  • 歡迎經過 GitHub issue 提交 BUG、以及其餘問題
  • 歡迎給該項目點個贊 ⭐️ star on GitHub ! 點擊文末「閱讀原文」直達,送出 Star

歡迎關注凹凸實驗室博客:aotu.io

或者關注凹凸實驗室公衆號(AOTULabs),不定時推送文章。

相關文章
相關標籤/搜索