react-native只保留3x图原理解析

   2023-02-07 学习力0
核心提示:目录引言1. 输出构建产物2. RN如何决定加载哪张scale图片?3. repo中是否可以只保留3x图?3.1 资源上传3.2 资源下载4. 结论引言我们的react-native项目中,一张图片一般会存在1x, 1.5x, 2x, 3x几种尺寸(1.5x是android特有的),以便在不同屏幕尺寸的手机加载

引言

我们的react-native项目中,一张图片一般会存在1x, 1.5x, 2x, 3x几种尺寸(1.5x是android特有的),以便在不同屏幕尺寸的手机加载对应尺寸的图片。

1. 输出构建产物

如果我们在代码中引入了一张图片,例如

// index.js
import bg from './bg.png';
.
├── index.js
├── bg.png
├── bg@1.5x.png
├── bg@2x.png
└── bg@3x.png

通过以下命令构建bundle

ios

react-native bundle --entry-file ./index.ts --platform ios --bundle-output ios.js --assets-dest ./ios

android

react-native bundle --entry-file ./index.ts --platform android --bundle-output android.js --assets-dest ./android

打包出来的图片资源如下

react-native只保留3x图原理解析

react-native只保留3x图原理解析

drawable-mdpi: 1x

drawable-hdpi: 1.5x

drawable-xhdpi: 2x

drawable-xxhdpi: 3x

可以看到,ios会将图片都放入同一个文件夹,通过scale后缀区分。而android则将不同的scale文件分别放入对应的scale文件夹,文件名都是一样的。

如果当前图片只存在3x图,打包出来的文件夹结构如下

react-native只保留3x图原理解析

react-native只保留3x图原理解析

2. RN如何决定加载哪张scale图片?

那么RN是如何决定加载哪张scale图片呢?

// react-native/Libraries/Image/AssetUtils.js
// metro打包时会检查当前图片存在哪些scale,将它们从小到大排序组成一个scales数组
// 比如上面的bg.png对应的scales为[1, 1.5, 2, 3]
export function pickScale(scales: Array<number>, deviceScale?: number): number {
  if (deviceScale == null) {
    deviceScale = PixelRatio.get();
  }
  // Packager guarantees that `scales` array is sorted
  for (let i = 0; i < scales.length; i++) {
    if (scales[i] >= deviceScale) {
      return scales[i];
    }
  }
  // If nothing matches, device scale is larger than any available
  // scales, so we return the biggest one. Unless the array is empty,
  // in which case we default to 1
  return scales[scales.length - 1] || 1;
}

通过源码得知,RN根据当前手机的ratio加载对应的scale图片。如果当前手机的ratio没有匹配到正确的scale图片,则会获取第一个大于当前手机ratio的scale图片。

例如当前手机的scale为2,如果存在2x图片,则返回2x图片。如果没有2x图,则会向上获取3x图。

3. repo中是否可以只保留3x图?

既然如此,那么我们能否在repo中仅仅保留3x图呢?这样打包出来的assets资源就可以变小了。

如果是低ratio的手机,当不存在低scale图片时,RN也会加载到3x图。

3.1 资源上传

在我们项目打包构建bundle和生成对应的assets资源后,需要将它们都上传cdn。

在上传之前,会先将bundle和不同的scale图片分别压缩到对应zip中

android 直接将不同的drawable文件夹压缩,比如 drawable-xxhdpi > hash.1.5x.zip

ios会从assets目录中找出所有同样的scale图片进行压缩。 比如

a@3x.png, b@3x.png > hash.3x.zip

然后将1x.zip, 1.5x.zip, 2x.zip, 3x.zip都上传cdn。

react-native只保留3x图原理解析

3.2 资源下载

native侧发现有新的RN更新时会下载对应的zip。这里我们native侧做了一个优化,他们不是下载全量的scale.zip, 而是根据当前手机的ratio下载对应的scale.zip。即如果当前手机ratio为2,则只会下载2x.zip(根据手机屏幕ratio下载,资源更小,下载速度更快,占用内存更小)。

所以假如我们在repo中只保留3x图,那么打包后上传cdn时,只有3x.zip存在图片资源,其他scale zip是空的。那么假如用户当前手机的ratio为2, 那么只会下载2x.zip, 而RN此时加载一张图片时,发现找不到对应的2x图,就会尝试加载3x图,然而native并没有下载3x图,导致在ratio为2的手机中加载图片失败。

如上分析,如果repo只保留3x图,对于ratio为3的手机其实没有影响,只影响低ratio的手机

4. 结论

终上所述在repo中我们不能仅仅只保留3x图(除非不支持低ratio的手机,或者native全量下载图片资源)。

更多阅读: react-native 图片解析流程

以上就是react-native只保留3x图原理解析的详细内容,更多关于react-native保留3x图的资料请关注其它相关文章!

原文地址:https://juejin.cn/post/7187415010941861946
 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • react-native start 启动错误解决方法
    ERRORError watching file for changes: EMFILE{"code":"EMFILE","errno":"EMFILE","syscall":"Error watching file for changes:","filename":null}Error: Error watching file for changes: EMFILE
    03-08
  • react-native关闭所有黄色警告 react native st
     将以下这两句话加在index.js(入口文件)中,放在AppRegistry.registerComponent('App', () = App)之前即可1 console.ignoredYellowBox = ['Warning: BackAndroid is deprecated. Please use BackHandler instead.','source.uri should not be an empty str
    03-08
  • react-native 配置 在mac 上找不到.npmrc
    打开终端,切换到根路径一、open .npmrc(会提示找不到该文件,没关系)二、npm config set registry https://registry.npm.taobao.org三、再次跳到步骤一,就能看到npmrc文件中已经设置好了registry
    03-08
  • 使用react-native-blur
    使用react-native-blur
    1.npm install react-native-blur --savereact-native link react-native-blur2.在安卓上只是link还是不够,还要配置,否则安装成功后还是闪退  打开android/app/build.gradle,添加加黑的代码  android {// make sure to use 23.0.3 or greaterbuildTool
    03-08
  • react-native ViewPagerAndroid 坑1
    ViewPagerAndroid组件 在更新新的data时 页面显示空解决办法  在data发生变化时 传入新的data的长度ViewPagerAndroidkey={this.props.children.length}style={{ flex: 1 }}onPageScroll={this.onPageScroll}onScrollBeginDrag={this._onScrollBegin}scrollEn
    03-08
  • react-native 调用原生Activity页面
    1. index.android.jsimport React, {Component} from 'react';import {AppRegistry,StyleSheet,Text,View,NativeModules,} from 'react-native'; class www extends Component {render() {return (View style={styles.container}Text style={styles.inst
    03-08
  • react-native 调用原生方法
    基于RN0.40。1. MyNativeModule.javapackage com.www;//路径名字 import android.content.Context;import android.widget.Toast; import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;im
    03-08
  • react-native 生命周期
    react-native 生命周期
      1 import React, { Component } from 'react'; 2 import { 3 AppRegistry, 4 StyleSheet, 5 Text, 6 View 7 } from 'react-native'; 89 export default class mykblearn extends Component {10constructor(props){11 super(props)12 this.state={times
    03-08
  • windows下react-native环境配置的那些坑 reactnative环境搭建
    windows下react-native环境配置的那些坑 reactn
    React Native 在Windows下的坑超级多,我从16号开始爬到20号,终于把所有的坑都爬完了。基本别人遇到的问题我都遇到了,别人没遇到的我也遇到了!所以在这里分享一下我的努力成果。首先推荐两篇文章(首推第一篇):史上最全Windows版本搭建安装React Native
    03-08
  • 学习react-native 学习英语
    1.一般来说,需要在constructor中初始化state,然后在需要修改时调用setState方法。2.样式使用驼峰命名法,建议使用StyleSheet.create来集中定义组件的样式。后声明的属性会覆盖先声明的同名属性。3.尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素
    03-08
点击排行