当前位置: 首页 > news >正文

使用postcss-px-to-viewport-8-plugin将页面转响应式

使用postcss-px-to-viewport-8-plugin将页面转响应式

背景

公司最近接了个项目,其中要求部分页面在移动端正常显示,第一方案是使用响应式,但是设计稿最后出的和Web端差别较大同时两端的功能不是完全对齐的,所以决定使用两个模块去实现,通过路由来控制显示的页面。

说到这里第一时间想到的当然是大名鼎鼎的postcss-px-to-viewport插件咯,之前也用过不少次了,非常香,这次也理所当然的打算使用该方案。

postcss-px-to-viewport使用

因为我们使用的是next,next已经内置了postcss插件,所以我们下载postcss-px-to-viewport即可

pnpm install postcss-px-to-viewport --save-dev

然后在next项目的根目录创建postcss.config.js文件并添加如下配置

module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
      viewportWidth: 375, // 设计稿的视口宽度,假设设计稿宽度为 375px
      unitPrecision: 5, // 转换后的单位精度
      viewportUnit: 'vw', // 转换后的单位
      selectorBlackList: [], // 忽略的选择器
      minPixelValue: 1, // 最小的转换值
      mediaQuery: false, // 是否转换媒体查询中的 px
      exclude: /node_modules/, // 忽略的文件或文件夹
    },
  },
};

具体的配置网上很多了,这里贴一个文档地址吧,需要的可以自己选择自己的配置👉 https://github.com/evrone/postcss-px-to-viewport

postcss-px-to-viewport部分配置不生效

配置完毕以后打包,啊哦,出现了一个打包错误,让我们来看看:

image-20250329181403371

原来是一个类型错误,无伤大雅,我们解决了以后接着打包,怎么打包失败?
image-20250329182455256

原来是权限问题,我们用管理员运行然后打包,打包成功!,现在我们来检查一下打包产物里面的css有没有更改单位。
image-20250329182840967

非常好,已经成功转成vw响应式了,但是根据模块检查发现是所有的页面都转vw了,而我只想转部分页面的单位,我们检查一下是不是部分配置项没有生效?

因为postcss-px-to-viewport支持include配置,所以我在想是不是我配置写的有问题,于是在尝试好几次不同的正则写法后打包的产物依然没变,连文件指纹都不带改的。。。

因为打包的时候为了检测配置项是否正确加载了,所以我在配置文件加了一行打印

console.log('Loading postcss.config.js');

module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
      viewportWidth: 375, // 设计稿的视口宽度,假设设计稿宽度为 375px
      ...
    },
  },
};

然后我发现控制台出现了这样的信息:

Loading postcss.config.js
postcss-px-to-viewport: postcss.plugin was deprecated. Migration guide:
https://evilmartians.com/chronicles/postcss-8-plugin-migration

然后我看了下,发现是postcss8换写法了,得升级,于是我检查了一下next自带的postcss版本,发现是8.4.14的版本。这个时候我查了下,发现得换插件了,也就是postcss-px-to-viewport-8-plugin

postcss-px-to-viewport-8-plugin的使用

postcss-px-to-viewport-8-plugin使用和postcss-px-to-viewport是一样的,只需要将插件名称更改一下即可。

module.exports = {
  plugins: {
    'postcss-px-to-viewport-8-plugin': {
      viewportWidth: 375, // 设计稿的视口宽度,假设设计稿宽度为 375px
      unitPrecision: 5, // 转换后的单位精度
      viewportUnit: 'vw', // 转换后的单位
      ...
    },
  },
};

然后我们接着打包看看。OK打包完成,检查一下css,发现和上面一样,单位是转换了,但是是全局的,include并没有生效,事已至此没办法了,只能看看源码调试一下了。

排查include配置不生效

image-20250329184238689

插件的目录很清晰,我们可以看到入口文件是lib文件夹下的index.js

    css.walkRules(rule => {
        // Add exclude option to ignore some files like 'node_modules'
        const file = rule.source?.input.file || '';
        if (opts.exclude && file) {
          if (Object.prototype.toString.call(opts.exclude) === '[object RegExp]') {
            if ((0, _utils.isExclude)(opts.exclude, file)) return;
          } else if (
            // Object.prototype.toString.call(opts.exclude) === '[object Array]' &&
            opts.exclude instanceof Array) {
            for (let i = 0; i < opts.exclude.length; i++) {
              if ((0, _utils.isExclude)(opts.exclude[i], file)) return;
            }
          } else {
            throw new Error('options.exclude should be RegExp or Array.');
          }
        }
      ....

可以看到exclude的配置如上所示,但是并没有include的配置,难不成这个配置不在index.js吗,但是没有找到,这里先暂且按下不表,先检查一下include的正则匹配有没有问题,打印上面的file以及正则匹配结果,发现无法匹配

const reg = /\/src\/app\/mobile\//

有经验的应该一眼就能看出来,是因为windows系统的路径符号导致的,windows应该用下面的正则:

const reg = /\\src\\app\\mobile\\/

现在是可以匹配了,但是打包产物依然不生效,我现在怀疑include配置根本就没有实现,于是我们去仓库看看他的源码。👉传送门

找了一圈,发现确实没有实现include,然后我就想这么大的问题别人没有发现吗,看了下Issues是有的https://github.com/lkxian888/postcss-px-to-viewport-8-plugin/issues/40

解决

最好的方式当然是提PR了,但是时间紧任务重啊,只能先改插件了。

1.直接修改插件

在项目的node_modules中找到postcss-px-to-viewport-8-plugin文件夹,然后在该文件夹下的lib文件夹下的index.js中的css.walkRules的参数方法中(也就是第60行)添加下面的代码:

 if (opts.include && file) {
          if (Object.prototype.toString.call(opts.include) === '[object RegExp]') {
            if (!(0, _utils.isExclude)(opts.include, file)) return;
          } else if (opts.include instanceof Array) {
            let included = false;
            for (let i = 0; i < opts.include.length; i++) {
              if ((0, _utils.isExclude)(opts.include[i], file)) {
                included = true;
                break;
              }
            }
            if (!included) return;
          } else {
            throw new Error('options.include should be RegExp or Array.');
          }
        }

其实就是和exclude反着来就行。

2. 使用exclude

因为我们打包部署用的是容器,所以改本地文件是不行嘞,那就只能退而求其次选择使用exclude了

module.exports = {
  plugins: {
    'postcss-px-to-viewport-8-plugin': {
      viewportWidth: 375, // 设计稿的视口宽度,假设设计稿宽度为 375px
      unitPrecision: 5, // 转换后的单位精度
      viewportUnit: 'vw', // 转换后的单位
      selectorBlackList: [], // 忽略的选择器
      minPixelValue: 1, // 最小的转换值
      mediaQuery: false, // 是否转换媒体查询中的 px
      // exclude: /node_modules/, // 忽略的文件或文件夹
      exclude: /^(?:(?!mobile).)*$/, 
    },
  },
};

这下路径有mobile的文件都不会被插件应用。

http://www.dtcms.com/a/98699.html

相关文章:

  • git | 版本切换的相关指令
  • Qt Creator 中文 “error: C2001: 常量中有换行符“ 问题解决方法
  • 树的基础_遍历(蓝桥云课)
  • Qt之Service开发
  • 复盘与导出工具最新版V20.0版本更新--覆盖标记新增龙头标记---连板标记--普通标记3种选择
  • 深度学习4.4笔记
  • 游戏AI实现-GOAP
  • 【华为OD技术面试真题 - 技术面】- Java面试题(16)
  • 【免费】中国电子学会2025年03月份青少年软件编程Python等级考试试卷六级真题(含答案)
  • 解决obsidian无法加载社区的解决的尝试
  • DeepSeek-R1国产大模型实战:从私有化部署到内网穿透远程使用全攻略
  • 【Java】Java核心知识点与相应面试技巧(七)——类与对象(二)
  • c++游戏开发第一期
  • 【大模型基础_毛玉仁】5.3 附加参数法:T-Patcher
  • 《新凯来 :中国半导体设备制造行业从“跟随者”向“挑战者”的角色转变》
  • 【蓝桥杯速成】| 15.完全背包
  • docker pull lss233/one-api:latest 在哪里运行,作用是什么
  • 【VUE】day08黑马头条小项目
  • (三)点亮LED
  • ngx_http_core_merge_srv_conf
  • 外观模式(Facade Pattern):复杂系统的“统一入口”
  • Qwen-0.5b linux部署
  • 订单超时自动关闭:电商系统的技术难题与解决方案
  • 常用登录Linux系统的方法以及操作指南
  • Spring Cloud Gateway详细介绍简单案例
  • Js 主线程和异步队列哪个先执行
  • Yolo系列之Yolov4的改进及网络框架
  • Java入门知识总结——章节(二)
  • bluecode-20240913_1_数据解码
  • 【Kafka】分布式消息队列的核心奥秘