乐趣区

关于webpack:react自适应布局-px转rem

引言

在 create-react-app 我的项目中配置相对单位 px 转换为绝对单位 rem, 其中应用 postcss-plugin-px2rem 转换 css/less/sass 文件(此插件不反对内联款式转换),应用编写的 loader 转换内联款式

1. 装置插件

npm i postcss-plugin-px2rem

2. 配置 webpack

  • 1 找到 config/webpack.config.js 里 postcss-loader,减少以下代码

     [
                                      'postcss-plugin-px2rem',
                                      {
                                          rootValue: 16,// 这是基准根元素的大小,用于计算 rem 单位。例如,如果你的 HTML 根元素的 font-size 设置为 16px,那么设置 rootValue 为 16 将会将 16px 转换为 1rem
                                          unitPrecision: 5,// 转换后的 rem 值的小数点位数。例如,如果设置为 5,那么转换后的 rem 值会保留小数点后的五位
                                          propWhiteList: [],// 哪些属性会被转换, 不填则是都转换
                                          propBlackList: [],// 哪些属性不会被转换
                                          exclude: ['/node_modules/'],// 排除文件
                                          selectorBlackList: ['noRem'], // 定义了哪些选择器不会被转换。例如,['noRem'] 示意带有类名为 noRem 的选择器不会被转换。ignoreIdentifier: false,// 是否疏忽选择器中的标识符。设置为 false 将会解决选择器中的标识符
                                          replace: true,// 是否替换原始的像素值为转换后的 rem 值。mediaQuery: false,// 是否在媒体查问中也进行转换
                                          minPixelValue: 0// 最小的像素值,小于这个值的像素值将不会被转换。}
                                  ]

    这样就实现了对非内联款式的转换

    3. 编写自定义 loader 转换内联款式

  • pxToRemLoader 代码

    module.exports = function(content, map, meta) {// let reg = /(\d+(\\.\d+)?)px/g
      let reg = /(?<num1>\d+)\.?(?<num2>\d+)?px/g  // 匹配所有 px 相干的字符
      let content1 = content.replace(reg,function(...data){ // px 转换为带小数的 rem
          var arr = data[data.length-1]
          var num1=0, num2=0;
          if(arr.num1)num1=parseFloat(arr.num1)
          if(arr.num2)num2=parseFloat(arr.num2)
          return  parseFloat(num1+'.'+num2)/16 + 'rem' // 这里以 16px 为 pc 端转换基数 适配 1920 分辨率
      })
      return content1
    };
    
  • webpack 批改原有配置

     {test: /\.(js|mjs|jsx|ts|tsx)$/,
                              include: paths.appSrc,
                              use: [
                                  {loader: require.resolve("babel-loader"),
                                      options: {
                                          customize: require.resolve("babel-preset-react-app/webpack-overrides"),
                                          presets: [
                                              [require.resolve("babel-preset-react-app"),
                                                  {runtime: hasJsxRuntime ? "automatic" : "classic",},
                                              ],
                                          ],
    
                                          plugins: [
                                              isEnvDevelopment &&
                                              shouldUseReactRefresh &&
                                              require.resolve("react-refresh/babel"),
                                          ].filter(Boolean),
                                          // This is a feature of `babel-loader` for webpack (not Babel itself).
                                          // It enables caching results in ./node_modules/.cache/babel-loader/
                                          // directory for faster rebuilds.
                                          cacheDirectory: true,
                                          // See #6846 for context on why cacheCompression is disabled
                                          cacheCompression: false,
                                          compact: isEnvProduction,
                                      },
                                  },
                                  {loader: path.resolve('./config/webpack/loader/pxToRemLoader.js')
                                  }
                              ]
                          },

    借鉴:
    https://juejin.cn/post/6994702713724338212
    https://juejin.cn/post/7068891300740726798

退出移动版