升级 macOS 10.15.6 后,发现 php 版本号已经升级到了 php7.3

运行 php -v

PHP 7.3.11 (cli) (built: Jun  5 2020 23:50:40) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies

问题

但是比较坑的是默认没有安装 zip 扩展,而 Laravel 是需要 ext-zip 扩展包的:

composer global require laravel/installer

QQ20200901-170526@2x.png

brew 安装 [email protected]

brew update
brew install [email protected]
brew link [email protected] --force

必须要使用 force

编译安装 [email protected]

本文不再展开,参考这篇文章:https://segmentfault.com/a/1190000022699382

查考资料

discussions.apple.com
install-ext-zip-for-mac

我们在使用 function base component 的时候可以使用 useParams 来获取参数, 类似这样:

const { id } = useParams()

当我们使用 class base component 的时候该如何写好类型呢?

先说结论

import { RouteComponentProps } from 'react-router';

// example route
<Route path="/products/:name" component={ProductContainer} />

interface MatchParams {
    name: string;
}

interface Props extends RouteComponentProps<MatchParams> {
}

查看源代码

// from typings
export interface RouteComponentProps<P> {
  match: match<P>;
  location: H.Location;
  history: H.History;
  staticContext?: any;
}

export interface match<P> {
  params: P;
  isExact: boolean;
  path: string;
  url: string;
}

当我们升级 package.json 包后,容易出现下面的错误:

npm WARN [email protected] requires a peer of [email protected]>= 4.12.1 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of @typescript-eslint/[email protected] but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of @typescript-eslint/[email protected] but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of [email protected] but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of [email protected] but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of [email protected]^5.0.0 || ^6.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of [email protected]>=6.1.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of [email protected] - 6.x but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of [email protected]^3 || ^4 || ^5 || ^6 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of [email protected]^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of [email protected]^1.8.18 but none is installed. You must install peer dependencies yourself.

audited 2211 packages in 7.724s

69 packages are looking for funding
  run `npm fund` for details

found 4992 low severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details

问题分析

package-lock.json 中锁定的包版本和新的包依赖的版本有冲突,所以 npm 不知道如何处理这些冲突。

解决办法

rm package-lock.json && rm -rf node_modules/ && npm install

注意⚠️

任何版本升级都可能产生新的问题,建议充分测试后才能上线运行

版本信息

react native: 0.62.2
react-native-apk-manager: ^1.1.0

错误摘要

java.lang.RuntimeException: Package manager has died at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:156)

错误信息

java.lang.RuntimeException: Package manager has died
    at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:139)
    at com.superhao.react_native_apk_manager.ApkManagerModule.isAppInstalled(ApkManagerModule.java:210)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
    at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
    at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
    at android.os.Looper.loop(Looper.java:148)
    at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
    at java.lang.Thread.run(Thread.java:818)
Caused by: android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
    at android.os.BinderProxy.transactNative(Native Method)
    at android.os.BinderProxy.transact(Binder.java:503)
    at android.content.pm.IPackageManager$Stub$Proxy.getPackageInfo(IPackageManager.java:2272)
    at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:134)
    ... 11 more
android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
    at android.os.BinderProxy.transactNative(Native Method)
    at android.os.BinderProxy.transact(Binder.java:503)
    at android.content.pm.IPackageManager$Stub$Proxy.getPackageInfo(IPackageManager.java:2272)
    at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:134)
    at com.superhao.react_native_apk_manager.ApkManagerModule.isAppInstalled(ApkManagerModule.java:210)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
    at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
    at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
    at android.os.Looper.loop(Looper.java:148)
    at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
    at java.lang.Thread.run(Thread.java:818)

设备分布

image

问题解决

re: https://github.com/1556173267/react-native-apk-manager/issues/6

  1. 需要避免同时多个线程调用 getPackageInfo,这样容易导致内存溢出 (主要解决方案)
  2. 避免获取过多 package 信息,如下所示
pm.getPackageInfo("com.tencent.mm", PackageManager.GET_ACTIVITIES);
// 修改为 👇
pm.getApplicationInfo("com.tencent.mm", PackageManager.GET_META_DATA);

参考文档

Android 获取 PackageInfo 引发 Crash 填坑
Package Manager Died
Android Package manager has died with TransactionTooLargeException
分析 Package manager has died

最近遇到了很多停更的 github 仓库,作者已明显放弃了维护。当我们需要修改软件包源代码的时候,就麻烦了。如果自己 fork 后发布重新发布新包,维护成本比较高。对于这种情况,更高效的办法是通过打 patch 的方式来修正软件包的代码。

下面介绍一下具体的实现办法:

为单个文件生成补丁

复制源文件,并修改复制后的文件内容,然后运行 diff 命令:

diff -up path/to/source.ext path/to/source.copy.ext > filename.patch

这条命令会产生类似如下的输出, 你将它重定向到一个文件中, 这个文件就是patch.

patch.png

参数详解:
-u 显示有差异行的前后几行(上下文), 默认是前后各3行, 这样, patch中带有更多的信息
-p 显示代码所在的c函数的信息

为多个文件生成补丁

diff -uprN path/to/source/ path/to/source_copy/ > patch

这条命令对比了 path/to/source/ 和 path/to/source_copy/ 两个目录下的所有源码差异.

参数详解:

-r 递归地对比一个目录和它的所有子目录(即整个目录树).
-N 如果某个文件缺少了, 就当作是空文件来对比。如果不使用本选项, 当diff发现旧代码或者新代码缺少文件时, 只简单的提示缺少文件。如果使用本选项, 会将新添加的文件全新打印出来作为新增的部分。

打补丁

我们将所有生成的 patch 文件放到 patches 目录后就可以使用脚本批量打补丁了。

#/bin/bash

# patch all file in patches dir
for i in $(find ./patches -name '*.patch');
do
  patch -N -p0 < $i > /dev/null 2>&1 &
done

通过 proxy_pass 代理的时候,如果文件比较大就会出现文件还没有传输完毕就被关闭的情况,只需要在 nginx 站点配置增加这个就可以解决了:

server {
    ...

    location / {
        ...
        proxy_buffers 8 1024k;  
        proxy_buffer_size 1024k;
    }
}

该绑定到哪个端口

这对于每一个编写服务器的程序员而言都是一个非常重要的考量。应该选择随机端口吗?该如何知道是否已经有其他的程序将某个端口宣为己有?

任何在 0~65535 之间的端口都可以使用,但是在选用之前别忘了一些重要的约定。

规则1: 不要使用 0~1024 之间的端口。

这些端口是作为熟知 (well-known)端口并保留给系统使用的。例如HTTP默认使用端口80, SMTP默认使用端口25,rsync默认使用端口873。绑定到这些端口通常需要root权限。

规则2: 不要使用 49000~65535 之间的端口。

这些都是临时 (ephemeral) 端口 。通常是由那些不需要运行在预定义端口,而只是需要一些端口作为临时之需的服务使用。它们也是后面所要讲到的连接协商 (connection negotiation) 过程的一部分。选择该范围内的端口可能会对一些用户造成麻烦。除此之外,1025~48999 之间端口的使用是一视同仁的。如果你打算选用其中的一个作为服务器端口,那你应该看一下 IANA 的注册列表,确保你的选择不会和其他流行的服务器冲突。

require 'socket'

# 该套接字将会绑定在环回接口,只侦听来自本地主机的客户端。
local_socket = Socket.new(:INET, :STREAM)
local_addr = Socket.pack_sockaddr_in(4481, '127.0.0.1')
local_socket.bind(local_addr)

# 该套接字将会绑定在所有已知的接口,侦听所有向其发送信息的客户端。
any_socket = Socket.new(:INET, :STREAM)
any_addr = Socket.pack_sockaddr_in(4481, '0.0.0.0')
any_socket.bind(any_addr)

# 该套接字试图绑定到一个未知的接口,结果导致Errno::EADDRNOTAVAIL。
error_socket = Socket.new(:INET, :STREAM)
error_addr = Socket.pack_sockaddr_in(4481, '1.2.3.4')
error_socket.bind(error_addr)

influence.jpg

影响力的武器

动物可能会因为看到某种颜色的羽毛而变得具有攻击性或听到某种叫声就对自己的天敌呵护有加。动物这种愚蠢可笑的机械反应在人类身上也有,当某一个触发特征出现时,我们会不假思索的做出相应的反应。之所以会这样,就是因为我们被难以观察到的影响力武器摆布了。

互惠

互惠原理认为,我们应该尽量以类似的方式报答他人为我们所做的一切。简单地说,就是对他人的某种行为,我们要以一种类似的行为去加以回报。如果人家施恩于你,你就应该以恩情报之,而不能不理不睬,更不能以怨报德。于是,我们身边这一最有效的影响力武器,就被某些人利用了。

承诺和一致

承诺和一致原理认为,一旦做出了一个选择或采取了某种立场,我们就会立刻碰到来自内心和外部的压力,迫使我们的言行与它保持一致。在这样的压力之下,我们会想方设法地以行动证明自己先前的决定是正确的。

社会认同

社会认同原理认为,在判断何为正确时,我们会根据别人的意见行事,尤其是当我们在特定情形下判断某一行为是否正确时。如果看到别人在某种场合做某件事,我们就会断定这样做是有道理的。

喜好

我们大多数人总是更容易答应自己认识和喜爱的人所提出的要求,对于这一点,恐怕不会有人感到吃惊。令人吃惊的是,有些我们完全不认识的人却想出了上百种方法利用这条简单的原理,让我们顺从他们的要求。

权威

权威所具有的强大力量会影响我们的行为,即使是具有独立思考能力的成年人,也会为了服从权威的命令做出一些完全丧失理智的事情来。

稀缺

“机会越少见,价值似乎就越高“的稀缺原理会对我们行为的方方面面造成影响,对失去某种东西的恐惧似乎比对获得同一物品的渴望,更能激发人们的行动力。

即时影响力

正常情况下,促使我们做出顺从决策的几个最常用的信息,都可以引导我们做出正确的决策,这就是为什么我们在决策时频繁、机械地使用互惠、承诺和一致、社会认同、喜好、权威以及稀缺原理的原因。每个原理本身都能够极为可靠地提示我们,什么时候说“是”比说“不”更加有利。但现实中,大量的、极易伪造的信息被人利用,他们借此引诱我们做出机械的反应并从中获利,我们不得不防。