从 PostCSS 插件,体验编码到发布全过程

栏目: CSS · 发布时间: 6年前

内容简介:因项目的需求,自己动手写了一个转换起初是看了大漠的一篇文章

因项目的需求,自己动手写了一个 PostCSS 插件 postcss-px2vw ,主要用于将 px 转成 vwremrem 作为回退模式。也刚好借此机会总结一下 npm 包的发布流程,文章还会介绍到七牛云图片的使用与上传相关的技巧,以及期间遇到的一些问题。

为什么需要它

转换 px 单位的插件有很多,知名的有 postcss-px-to-viewportpostcss-pxtorem ,前者是将 px 转成 vw ,后者是将 px 转成 rem

起初是看了大漠的一篇文章 《如何在Vue项目中使用vw实现移动端适配》 ,于是怀着激动的心情,就在项目中也使用 vw 来做移动端的适配。该文章大力推行用 vw 代替 rem 做适配,在 amfe-flexible 项目文档中也推荐 vw 的替代方案。但是考虑到移动端对 vw 的支持情况不如 rem ,所以仍有很多项目都选择使用 rem 来布局。于是就想到将 rem 作为一种回退机制,或许觉得没必要,直接放弃 vw 使用 rem 不就完了?确实,不过既然是折腾,也就不需要那么多理由了,其实饿了么平台就用了此方案。

关于移动端适配方案,也有一些个人的亲身体会,有时间另启一篇文章详细总结一下。

实现方案

首先,得提一下 CSS 样式的回退原理:当 CSS 遇到无法识别的一些样式时,不会报错,而是忽略它。并且后面的样式声明比前面的样式声明权重要高(也就是会覆盖前面的样式)。所以,我们要达到的效果是这样的:

.class {
    margin-top: 2rem;
    margin-top: 20vw;
}
复制代码

浏览器会优先使用第二个 margin-top: 20vw; ,如果不支持该声明就会直接忽略它,并使用第一个 margin-top: 2rem;

要实现这样的效果,一开始想到的是同时使用上面介绍到的两款插件,设置 postcss-pxtorem 的参数 replace: false ,最后的结果是这样的:

.class {
    margin-top: 20vw;
    margin-top: 2rem;
}
复制代码

虽然最后结果同时保留了两种单位,但是优先使用的是 rem ,这并不能满足我们的需求。原因也很简单,看 postcss-pxtorem 源码就会知道,设置 replace: false 时,它会在当前样式下面插入转换后的结果。而 postcss-px-to-viewport 是不能设置 replace 的,所以,无论如何配置, rem 单位始终会在 vw 的下面。

基于这个点,就可以编写我们自己的代码了。

代码实现

打开 postcss-px-to-viewport 源码,其实也就短短的几十行代码。就算没写过 PostCSS 插件,看到源码,依葫芦画瓢,也能写一个适合自己的插件来。这是修改过后的源码:

'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 个可配置参数( viewportWidthrootValueunitPrecisionminPixelValue ),具体使用说明可查看 项目的README.md 文档。

发布到 npm 仓库

本来只是为了项目的需要,没打算从项目中独立出现来的。一方面为了熟悉一下 npm 的发布流程,另一方面也是为了在自己的 github 仓库中保留一份记录。

整个流程很简单,也就几步:

  1. 要发布到 npm 仓库,首先得新建一个项目。运行 npm init ,填写相关参数说明;
  2. 登录 npm 账号: npm login ,输入用户名密码以及邮箱。如果没有账号就去npm官网 注册一个;
  3. 发布: npm publish ,大功告成。

不过现实往往没有理论那么容易,总会遇到一些问题。

  1. 如果你使用的是淘宝源,需要先切回官方源,使用 nrm 的话,只需 nrm use npm 即可;
  2. package.json 中的 name 不能与仓库中已有的项目重名。如果难以命名,可添加用户名前缀,如: @moohng/postcss-px2vw 。添加用户前缀是不能直接 publish 到公有仓库中的,需要使用 npm publish --access=public
  3. 每次更新发布必须增加 package.json 中的版本号。

七牛云的使用

为什么会使用到七牛云?这本是八竿子也打不着的东西。其实,也就是为了学别人在项目的 README.md 文档最后贴一张个人的收款二维码。先别想其他,就贴一张图本身而言,其实很简单,就是在 markdown 语法中插入一张图片链接地址。

为了一张图片的链接地址,就把七牛云也整一遍?的确,就是出于这个目的于是就研究了一遍七牛云这东西。简单的上传无外乎就是登陆到七牛云平台,然后拽一张图片上去,链接地址就有了。可是,作为一个高大上的程序猿,怎能如此将就,当然得有一套不同寻常的方式了。

最终要达到的效果就是得到一张上传图片的链接地址: static.moohng.com/FrEihC8JSWM… + 图片hash值。

域名配置

要配置自定义域名,首先得拥有一个已经备案过的域名。然后在七牛云的融合CDN菜单下可以添加域名:

因掘金对图片强制需要使用 https 链接,所以就不配图了。其中要注意的一点就是 源站配置一定要选择七牛云存储和对应的存储空间名称

接下来在域名管理平台配置 CNAME,CNAME 值可在刚添加的域名下查看。如此一来,以后访问七牛云上的资源就可以直接通过自定义域名来访问了。

图片上传

获取上传 token

实现上传最关键的就是要有一个 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);
复制代码

其中, accessKeysecretKey 可在七牛云个人中心查看。

在 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 表示上传文件,文件参数与其他参数必须分开写,文件参数使用 @+文件路径。

更多的使用说明及相关参数请参考七牛云开发文档。


以上所述就是小编给大家介绍的《从 PostCSS 插件,体验编码到发布全过程》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Servlet和JSP学习指南

Servlet和JSP学习指南

Budi Kurniawan / 崔毅、俞哲皆、俞黎敏 / 机械工业出版社华章公司 / 2013-4-14 / 59.00元

本书是系统学习Servlet和JSP的必读之作。由全球知名的Java技术专家(《How Tomcat Works》作者)亲自执笔,不仅全面解读Servlet 和JSP 的最新技术,重点阐述Java Web开发的重要编程概念和设计模型,而且包含大量可操作性极强的案例。 本书共18章:第1章介绍Servlet API和几个简单的Servlet;第2章讨论Session追踪,以及保持状态的4种技术......一起来看看 《Servlet和JSP学习指南》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具