SPA 中微信 JSSDK 签名在 iOS 和 Android 中的差异

本文提及的各个环境版本为当前最新版本,若与各位看官版本不一致,可能出现差异:
微信:7.0.3
JSSDK:1.4.0
iOS:12.1.4(iPhone6s)
Android:EMUI 9.0.0(HUAWEI P20)

项目使用 React + Router 来管理路由,使用了 BrowserHistory,按文档说,访问每个页面的 URL 都会改变,因此每次都需要调用后端重新获取签名。下面是 app.jsx,位于入口。

上面的代码在 Android 中是正常的,但是在 iOS 中,第一次签名成功,而 URL 变更后会提示签名失败,该异常并没有在官方《iOS WKWebview 网页开发适配指南》中提出。这个问题可以在 vue 的 issues 中找到了一些提示《关于html5-History模式在微信浏览器内的问题》。iOS 下在每次页面 URL 变更,微信内置浏览器用于验证签名的 URL 是不会变的 😂(这也是为什么使用 HashHistory 方式不会出现签名失败的原因),因此在 history.listen 事件中,我们需要加一些判断,iOS 下仅需要签名一次就可以了。

为了避免长时间停留在 app 时,微信的 access token 可能存在超时,我们在一定时间内可以请求一次重签名。

wx.chooseImage 在 iOS 下的兼容性

在 iOS 下直接调用 wx.chooseImage 并不能直接获得本地图片资源(localId 不能直接用于 <img>backgroundImage),官方文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1483682025_enmey

开发者可以先判断微信注入的 __wxjs_is_wkwebview 以确认是否使用了 WKWebview,来做相应的处理

避免 postcss 规则删除旧的样式属性 (-webkit-box-orient)

React 中的 webpack 默认配置下,postcss 在 build 过程移除一些旧的样式属性,如 -webkit-box-orient

问题原链接:https://github.com/postcss/autoprefixer/issues/776

可以在代码中直接加上 /* autoprefixer: ignore next */ 来避免下一行执行 autoprefixer

Electron 在线热升级方案

一个项目正式交付客户使用了,对于版本的升级和代码更新是个一直困扰的问题,由于之前一直都是内部人员使用,可以让他们每次都下载完整压缩包(压缩后大概 40-50MB),但对于正式的终端用户,这个体验是不可接受。
参考过 Electron 官方文档,里面提及的方案兼容性并不好(Linux 不支持),需要准备的东西不少,而且交互上也不满意;以及参考了这篇 《我是如何实现electron的在线升级热更新功能的?》,最终按照里面的思路为该项目做了一个在线热升级的方案,本文介绍方案的细节及中间遇到的一些坑。

流程图

processon

关键步骤

  1. 通过 app.getVersion() 获取到 App 的本地版本号,这个版本号来源于 package.json
  2. 获取线上的 App 版本信息,此处我们设计了两个版本信息(如图例子);
    2.1. “1.3.0” 为核心版本号,该版本号用于判断是否需要重新下载完整包(图中所示的对应不同平台有不同的下载地址,为 zip 扩展名的压缩包,至于为什么用 zip,下文会提及),比如当 Electron 核心版本升级,或者增加了 node_modules 依赖等情况;
    2.2. “1.3.3” 为热更新版本号,这种情况只需要更新特定的文件列表(图中所示的 upgrade_1.3.3.tar.gz),通常包含 package.jsonsrc/* 等;
    2.3. description 分别表示核心版本和热更新版本的描述;
  3. 对比本地版本号 (appVersion) 和线上的版本号 (onlineVersion),下面是版本号比较的代码:

    3.1. 对比本地版本号和线上核心版本号 (onlineVersion.version),如果小于线上版本号,则激活浏览器并进入下载,同时退出 App;
    3.2. 否则进行对比本地版本号和热更新版本号 (onlineVersion.upgrade.version),如果小于线上版本号,则下载热更新包;
  4. 根据 (upgrade.url) 下载热更新包、升级、重启 App,全部代码:

  1. Windows 下可以直接把更新文件保存到 App 目录(没有权限问题),而在 Mac OSX 下,App 目录是无权写入的,而临时文件路径必须通过 app.getPath() 来获取,常用 temp 或者 userData 目录来保存解压文件;
  2. 压缩包我使用了 zip 一个原因是 Windows 下默认就能支持 zip 包解压,另一个主要原因是文件名编码问题,最初用 tar 来压缩文件,对于英文文件名是正常的,对于中文文件名,在 Mac OSX 下打包后在 Windows 是无法被正确解开的。而貌似 7z 生成的 zip 包会保存文件名字符集并能被 Windows 正确解开,所以在 gulp 中使用了 7z 来产生 zip 压缩包:

    而对于热更新包,由于源代码都是使用英文名,所以用 tar 来压缩没毛病:

webpack 怎样生成 inline (内联) 的 style 或 script

背景

最近一个项目用到 React,默认配置下,样式和脚本都通过混淆压缩合并后生成一个 css 或 js 文件(通过 ExtractTextPlugin ),并插入到 index.html 中,详细的配置可查看 eject 后的 webpack 配置文件。

而由于输出的 css 和 js 文件都有数十 KB,在第一次加载页面时,会出现一个白屏的情况,所以我在 index.html 中加了一个 Loading 效果,但是由于 Loading 的样式也是在 css 文件内的,并没有达到预期的效果,所以想是不是可以把一些基础样式单独抽出来放到 index.html 中内联。

ExtractTextPlugin

这个插件可以把符合条件的内容输出到一个独立的文件当中,详细配置查看 https://doc.webpack-china.org/plugins/extract-text-webpack-plugin/,在 webpack.config.prod.js 配置中已经包含了该 plugin,仅用于输出外部引入的 css 文件,我们可以修改下。

此处定义了两个实例,把 extractCss 用于处理原有的 css 文件输出,extractInlineCss 用于处理需要 inline 的 css,下面是常见的 webpack 配置内容,我们在 css 处理器前加上 inline css 的处理

完成这个步骤后,build 过程会对 inline.css 结尾的文件合并并输出到 main.inline.css

HtmlWebpackInlineSourcePlugin

这个插件可以把符合条件的 css 或 js 内联到 index.html 中,详细配置查看 https://github.com/DustinJackson/html-webpack-inline-source-plugin,这里我们需要把 inline.css 结尾的文件内联进来。

最后,build 完的结果是把这些 inline.css 的内容都内潜入 index.html 中,以致在未加载完独立 css 和 js 时也可以把 Loading 显示正确。

下一页 →