因項目的需求,本身動手寫了一個 PostCSS 插件 postcss-px2vw,主要用於將 px
轉成 vw
和 rem
,rem
做爲回退模式。也恰好藉此機會總結一下 npm
包的發佈流程,文章還會介紹到七牛雲圖片的使用與上傳相關的技巧,以及期間遇到的一些問題。css
轉換 px
單位的插件有不少,知名的有 postcss-px-to-viewport 和 postcss-pxtorem,前者是將 px
轉成 vw
,後者是將 px
轉成 rem
。html
起初是看了大漠的一篇文章《如何在Vue項目中使用vw實現移動端適配》,因而懷着激動的心情,就在項目中也使用 vw
來作移動端的適配。該文章大力推行用 vw
代替 rem
作適配,在amfe-flexible 項目文檔中也推薦 vw
的替代方案。可是考慮到移動端對 vw
的支持狀況不如 rem
,因此仍有不少項目都選擇使用 rem
來佈局。因而就想到將 rem
做爲一種回退機制,或許以爲不必,直接放棄 vw
使用 rem
不就完了?確實,不過既然是折騰,也就不須要那麼多理由了,其實餓了麼平臺就用了此方案。前端
關於移動端適配方案,也有一些我的的親身體會,有時間另啓一篇文章詳細總結一下。vue
首先,得提一下 CSS 樣式的回退原理:當 CSS 遇到沒法識別的一些樣式時,不會報錯,而是忽略它。而且後面的樣式聲明比前面的樣式聲明權重要高(也就是會覆蓋前面的樣式)。因此,咱們要達到的效果是這樣的:node
.class {
margin-top: 2rem;
margin-top: 20vw;
}
複製代碼
瀏覽器會優先使用第二個 margin-top: 20vw;
,若是不支持該聲明就會直接忽略它,並使用第一個 margin-top: 2rem;
。git
要實現這樣的效果,一開始想到的是同時使用上面介紹到的兩款插件,設置 postcss-pxtorem 的參數 replace: false
,最後的結果是這樣的:程序員
.class {
margin-top: 20vw;
margin-top: 2rem;
}
複製代碼
雖然最後結果同時保留了兩種單位,可是優先使用的是 rem
,這並不能知足咱們的需求。緣由也很簡單,看 postcss-pxtorem
源碼就會知道,設置 replace: false
時,它會在當前樣式下面插入轉換後的結果。而 postcss-px-to-viewport
是不能設置 replace
的,因此,不管如何配置,rem
單位始終會在 vw
的下面。github
基於這個點,就能夠編寫咱們本身的代碼了。算法
打開 postcss-px-to-viewport 源碼,其實也就短短的幾十行代碼。就算沒寫過 PostCSS 插件,看到源碼,依葫蘆畫瓢,也能寫一個適合本身的插件來。這是修改事後的源碼:npm
'use strict';
var postcss = require('postcss');
var objectAssign = require('object-assign');
module.exports = postcss.plugin('postcss-px2vw', function (options) {
var opts = objectAssign({
viewportWidth: 750,
unitPrecision: 5,
rootValue: 75,
minPixelValue: 1
}, options);
var pxRegex = /"[^"]+"|'[^']+'|url\([^\)]+\)|(\d*\.?\d+)px/ig;
return function (css) {
css.walkDecls(function (decl, i) {
if (decl.value.indexOf('px') === -1) return;
var value = decl.value;
if (opts.viewportWidth) {
var pxReplaceForVw = createPxReplace(opts.viewportWidth / 100, opts.minPixelValue, opts.unitPrecision, 'vw');
decl.value = value.replace(pxRegex, pxReplaceForVw);
}
if (opts.rootValue) {
var pxReplaceForRem = createPxReplace(opts.rootValue, opts.minPixelValue, opts.unitPrecision, 'rem');
if (opts.viewportWidth) {
decl.parent.insertBefore(i, decl.clone({
value: value.replace(pxRegex, pxReplaceForRem)
}));
} else {
decl.value = value.replace(pxRegex, pxReplaceForRem);
}
}
});
};
});
function createPxReplace(perRatio, minPixelValue, unitPrecision, unit) {
return function (m, $1) {
if (!$1) return m;
var pixels = parseFloat($1);
if (pixels <= minPixelValue) return m;
return toFixed((pixels / perRatio), unitPrecision) + unit;
};
}
function toFixed(number, precision) {
var multiplier = Math.pow(10, precision + 1);
var wholeNumber = Math.floor(number * multiplier);
return Math.round(wholeNumber / 10) * 10 / multiplier;
}
複製代碼
合併了兩款插件的核心轉換功能,並去掉了一些不經常使用的功能和配置項,實現最初的目的就行,儘可能保持簡單易用的原則。該插件只保留了 4 個可配置參數(viewportWidth
、rootValue
、unitPrecision
、minPixelValue
),具體使用說明可查看 項目的README.md 文檔。
原本只是爲了項目的須要,沒打算從項目中獨立出現來的。一方面爲了熟悉一下 npm 的發佈流程,另外一方面也是爲了在本身的 github 倉庫中保留一份記錄。
整個流程很簡單,也就幾步:
npm init
,填寫相關參數說明;npm login
,輸入用戶名密碼以及郵箱。若是沒有帳號就去 npm官網 註冊一個;npm publish
,大功告成。不過現實每每沒有理論那麼容易,總會遇到一些問題。
nrm
的話,只需 nrm use npm
便可;package.json
中的 name
不能與倉庫中已有的項目重名。若是難以命名,可添加用戶名前綴,如:@moohng/postcss-px2vw
。添加用戶前綴是不能直接 publish
到公有倉庫中的,須要使用 npm publish --access=public
;package.json
中的版本號。爲何會使用到七牛雲?這本是八竿子也打不着的東西。其實,也就是爲了學別人在項目的 README.md
文檔最後貼一張我的的收款二維碼。先別想其餘,就貼一張圖自己而言,其實很簡單,就是在 markdown
語法中插入一張圖片連接地址。
爲了一張圖片的連接地址,就把七牛雲也整一遍?的確,就是出於這個目的因而就研究了一遍七牛雲這東西。簡單的上傳無外乎就是登錄到七牛雲平臺,而後拽一張圖片上去,連接地址就有了。但是,做爲一個高大上的程序猿,怎能如此將就,固然得有一套不一樣尋常的方式了。
最終要達到的效果就是獲得一張上傳圖片的連接地址:static.moohng.com/FrEihC8JSWM… + 圖片hash值。
要配置自定義域名,首先得擁有一個已經備案過的域名。而後在七牛雲的融合CDN菜單下能夠添加域名:
因掘金對圖片強制須要使用 https 連接,因此就不配圖了。其中要注意的一點就是源站配置必定要選擇七牛雲存儲和對應的存儲空間名稱。
接下來在域名管理平臺配置 CNAME,CNAME 值可在剛添加的域名下查看。如此一來,之後訪問七牛雲上的資源就能夠直接經過自定義域名來訪問了。
實現上傳最關鍵的就是要有一個 token,token 的生成在官方文檔中都有說明。不過咱們不用本身寫算法,官網已經用多種語言實現了封裝。前端可參考Node.js SDK,簡單實現:
新建一個項目 demo,初始化 npm init
,而後安裝七牛雲SDK npm install qiniu
。
// index.js
var qiniu = require('qiniu');
// 可在七牛雲查看
var accessKey = 'accessKey';
var secretKey = 'secretKey';
var mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
var options = {
scope: 'moohng', // 存儲空間名稱
};
var putPolicy = new qiniu.rs.PutPolicy(options);
var uploadToken = putPolicy.uploadToken(mac);
console.log(uploadToken);
複製代碼
其中,accessKey
和 secretKey
可在七牛雲我的中心查看。
在 Nodejs 環境下運行代碼,node index.js
,獲得 token。
上傳地址可在七牛雲開發者中心查看,不一樣地區的地址不同。例如,華南地區:http(s)://upload-z2.qiniup.com。
原本是想寫一個圖形化界面,用來上傳圖片。無賴本身比較懶,既然拿到了最關鍵的 token,也有了上傳地址,至於圖形化界面有時間再說吧。
做爲程序員,逼格最高的莫過於命令行了。因而,就想到了 Linux 下經常使用的 curl
命令。
$ curl http://upload-z2.qiniup.com -F "file=@./img_example.png" -F "token=這裏是生成的token"
複製代碼
而後一個優雅的回車,一切就結束了!不出意外會返回一個 key
,這個 key
拼接上以前自定義的域名,就能夠隨心所欲了。
關於 curl 命令,-F 表示上傳文件,文件參數與其餘參數必須分開寫,文件參數使用 @+文件路徑。
更多的使用說明及相關參數請參考七牛雲開發文檔。
七牛雲提供了多個圖片處理工具,裁剪、縮放、壓縮等。若是放到 github 上的圖片太大,可能會加載不出來,因此,對圖片進行縮放和壓縮是頗有必要的。
處理以前:static.moohng.com/FrEihC8JSWM… (85.1k)
處理以後:static.moohng.com/FrEihC8JSWM… (17.1k)
其效果仍是很明顯的。
關注我,不按期更新前端技術型文章。