小程序框架工程构建之使用less(02)

656 阅读3分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

上一篇讲了如何使用less编写样式,但是小程序中样式编写有这么几个问题:

  1. 通常使用rpx响应式单位,在编写的时候每次要敲多一次R键,与web开发时使用px单位开发体验相割裂
  2. background-image属性不支持本地图片,只支持网络图片及base64格式,或者使用 <image> 标签代替

针对上面的问题,我们需要处理css中的内容。

在上一篇中,processStyle方法中提到了postcss可以利用各种插件完成对css内容的处理。针对问题1,有个npm包:postcss-pxtorpx-pro

可以帮助我们将px转化为rpx单位

先看下文档的例子方便理解:

// input
h1 {
    margin: 0 0 20px;
    font-size: 32px;
    line-height: 1.2;
    letter-spacing: 1px;
}
 
// output
h1 { 
  margin: 0 0 40rpx; 
  font-size: 64rpx; 
  line-height: 1.2; 
  letter-spacing: 2rpx; 
}

代码处理px转化为rpx

const pxtorpx = require('postcss-pxtorpx-pro');
​
// 样式文件处理
async function processStyle(filePath) {
    ...
  // 处理css
  const { css: wxss } = await postcss()
    .use(pxtorpx({ minPixelValue: 2 })) // 将px转为rpx
    .process(css, { map: false, from: undefined });
    ...
}
​

针对问题2,用到 postcss-url, 它可以帮助我们读取url()中的内容,然后针对url中的地址做相关处理。

处理background-image链接

针对不能访问本地图片的情况,开发环境下 我们可以通过开启本地服务通过http形式访问加载。处理流程如下:

  1. 判断是否以https或者data:开头,是则跳过不做处理
  2. 判断路径写法是绝对路径还是相对路径,处理获得服务地址

开启本地服务

这里用到了node child_process子进程下的spawn函数,用于调用系统的命令

const { spawn } = require('child_process');
...
spawn('serve', ['src'], { stdio: 'inherit', shell: true }); // 将src目录开启文件服务
dev()

添加上面代码后,我们重新npm run dev后可以发现控制台输出:

image-20210823111814883.png

这时我们在浏览器中打开上面显示的地址可以看到src目录内容:

image-20210823112108798.png 这也就意味着我们可以通过http形式访问静态资源内容了

相关代码build.js

const postcssurl = require("postcss-url");
const os = require('os'); // 直接引入const localPath = `http://${getLocalIP()}:5000/`;
​
​
// 获取本地IP
function getLocalIP() {
  const ifaces = Object.values(os.networkInterfaces());
  for (const iface of ifaces) {
    for (const alias of iface) {
      if (alias.internal || alias.family !== 'IPv4') continue;
      return alias.address;
    }
  }
}
​
// 样式文件处理
async function processStyle(filePath) {
    ...
  // 处理css
  const { css: wxss } = await postcss()
    .use(pxtorpx({ minPixelValue: 2 })) // 将px转为rpx
    .use(
      postcssurl({
        url(asset) {
          // 如果是网络图片或者base格式,则不处理
          if (/^https?:///.test(asset.url) || asset.url.startsWith("data:")) {
            return asset.url;
          }
          // 处理相对/绝对路径
          const absolutePath = asset.url.startsWith('/')
            ? path.resolve('src', asset.url.slice(1))
            : path.resolve(path.dirname(filePath), asset.url);
          const href = localPath + path.relative('src', absolutePath).replace(/\/g, '/');
          return href
        },
      })
    )
    .process(css, { map: false, from: undefined });
    ...
}

测试代码

  1. 我们在src目录下新建images文件夹,里面放一张图片

  2. 编辑src -> pages -> index -> index.wxml, 内容如下:

    <view class="container">
      <view class="userinfo"></view>
    </view>
    
  3. 编辑src -> pages -> index -> index.less,内容如下:

    .userinfo {
      width: 100%;
      height: 200px;
      background-image: url("../../images/host-cat.jpg");
      background-size: cover;
    }
    

    运行npm run dev,打开dist -> pages -> index -> index.wxss,生成代码如下: image-20210823134435423.png

    可以看到height高度由200px变为400rpx,background-image url地址也变为了服务地址访问。最后将dist目录导入开发者工具,运行效果如下:

image-20210823134821428.png

最后

以上对于background-image的处理是在开发环境下情况下,打包正式环境时,可以将图片资源转为base64格式。当然,图片体积较大的情况下,就需要将图片放置于服务器端,通过配置服务器地址统一修改图片基地址。对于正式打包的处理,将在后面文章中给出相关代码。

源码地址