开发者技术前线 ,汇集技术前线快讯和关注行业趋势,大厂干货,是开发者经历和成长的优秀指南。
Python 学习路线思维导图, 经典收藏!
支付宝海量支付背后的架构揭秘!
作者:mcuking(杭州个推) https://juejin.im/post/5d759f706fb9a06afa32adec
组件库[6]
JSBridge[7]
路由堆栈管理(模拟原生 APP 导航)[8]
请求数据缓存[9]
构建时预渲染[10]
Webpack 策略[11]
基础库抽离[12]
手势库[13]
样式适配[14]
表单校验[15]
阻止原生返回事件[16]
通过 UA 获取设备信息[17]
mock 数据[18]
调试控制台[19]
抓包工具[20]
异常监控平台[21]
常见问题[22]
需要配置在每次构建时都不参与编译的静态依赖,并在首次构建时为它们预编译出一份 JS 文件(后文将称其为 lib 文件),每次更新依赖需要手动进行维护,一旦增删依赖或者变更资源版本忘记更新,就会出现 Error 或者版本错误。
无法接入浏览器的新特性 script type="module",对于某些依赖库提供的原生 ES Modules 的引入方式(比如 vue 的新版引入方式)无法得到支持,没法更好地适配高版本浏览器提供的优良特性以实现更好地性能优化。
将所有资源预编译成一份文件,并将这份文件显式注入项目构建的 HTML 模板中,这样的做法,在 HTTP1 时代是被推崇的,因为那样能减少资源的请求数量,但在 HTTP2 时代如果拆成多个 CDN Link,就能够更充分地利用 HTTP2 的多路复用特性。
开发时都是在浏览器进行开发调试的,所以需要避免调用 native 的接口,因为这些接口在浏览器环境根本不存在;
有些情况需要区分所在环境是在 android webview 还是 ios webview,做一些针对特定平台的处理;
当 h5 版本已经更新,但是客户端版本并没有同步更新,那么如果之间的接口调用发生了改变,就会出现调用出错。
设备兼容或网络异常导致只有部分情况下才出现的 bug,测试无法全面覆盖
无法获取出现 bug 的用户的设备,又不能复现反馈的 bug
部分 bug 只出现几次,后面无法复现,不能还原事故现场
静态资源加载异常
接口异常(包括与后端和 native 的接口)
js 报错
网页崩溃
npm install sentry-cli
)命令行工具进行上传,命令如下:iOS WKWebView cookie 写入慢以及易丢失
现象:
原因:WKWebView 对 NSHTTPCookieStorage 写入 cookie,不是实时存储的。从实际的测试中发现,不同的 IOS 版本,延迟的时间还不一样。同样,发起请求时,也不是实时读取,无法做到和 native 同步,导致页面逻辑出错。
两种解决办法:
各位可以选择适合自己项目的方式,有更好的处理方式欢迎留言。
客户端手动干预一下 cookie 的存储。将服务响应的 cookie,持久化到本地,在下次 webview 启动时,读取本地的 cookie 值,手动再去通过 native 往 webview 写入。但是偶尔还有 spa 的页面路由切换的时候丢失 cookie 的问题。
将 cookie 存储的 session 持久化到 localSorage,每次请求时都会取 localSorage 存储的 session,并在请求头部添加 cookieback 字段,服务端鉴权时,优先校验 cookieback 字段。这样即使 cookie 丢失或存储的上一次的 session,都不会有影响。不过这种方式相当于绕开了 cookie 传输机制,无法享受 这种机制带来的安全特性。
iOS 登陆后立即进入网页,会出现 cookie 获取不到或获取的上一次登陆缓存的 cookie
重启 App 后,cookie 会丢失
input 标签在部分安卓 webview 上无法实现上传图片功能
因为 Android 的版本碎片问题,很多版本的 WebView 都对唤起函数有不同的支持。我们需要重写 WebChromeClient 下的 openFileChooser()(5.0 及以上系统回调 onShowFileChooser())。我们通过 Intent 在 openFileChooser()中唤起系统相机和支持 Intent 的相关 app。
相关文章:【Android】WebView 的 input 上传照片的兼容问题[85]
input 标签在 iOS 上唤起软键盘,键盘收回后页面不回落(部分情况页面看上去已经回落,实际结构并未回落)
input 焦点失焦后,ios 软键盘收起,但没有触发 window resize,导致实际页面 dom 仍然被键盘顶上去--错位。解决办法:全局监听 input 失焦事件,当触发事件后,将 body 的 scrollTop 设置为 0。
document.addEventListener('focusout', () => {
document.body.scrollTop = 0;
});
唤起软键盘后会遮挡输入框
当 input 或 textarea 获取焦点后,软键盘会遮挡输入框。解决办法:全局监听 window 的 resize 事件,当触发事件后,获取当前 active 的元素并检验是否为 input 或 textarea 元素,如果是则调用元素的 scrollIntoViewIfNeeded 即可。
window.addEventListener('resize', () => {
// 判断当前 active 的元素是否为 input 或 textarea
if (
document.activeElement!.tagName === 'INPUT' ||
document.activeElement!.tagName === 'TEXTAREA'
) {
setTimeout(() => {
// 原生方法,滚动至需要显示的位置
document.activeElement!.scrollIntoView();
}, 0);
}
});
唤起键盘后 position: fixed;bottom: 0px;
元素被键盘顶起
解决办法:全局监听 window 的 resize 事件,当触发事件后,获取 id 名为 fixed-bottom 的元素(可提前约定好如何区分定位在窗口底部的元素),将其设置成 display: none
。键盘收回时,则设置成 display: block;
。
const clientHeight = document.documentElement.clientHeight;
window.addEventListener('resize', () => {
const bodyHeight = document.documentElement.clientHeight;
const ele = document.getElementById('fixed-bottom');
if (!ele) return;
if (clientHeight > bodyHeight) {
(ele as HTMLElement).style.display = 'none';
} else {
(ele as HTMLElement).style.display = 'block';
}
});
点击网页输入框会导致网页放大通过 viewport 设置 user-scalable=no 即可,(注意:当 user-scalable=no 时,无需设置 minimum-scale=1, maximum-scale=1,因为已经禁止了用户缩放页面了,允许的缩放范围也就不存在了)。代码如下:
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,user-scalable=0,viewport-fit=cover"
/>
webview 通过 loadUrl 加载的页面运行时却通过第三方浏览器打开,代码如下
// 创建一个 Webview
Webview webview = (Webview) findViewById(R.id.webView);
// 调用 Webview loadUrl
webview.loadUrl("http://www.baidu.com/");
解决办法:在调用 loadUrl 之前,设置下 WebviewClient 类,当然如果需要也可自己实现 WebviewClient(例如通过拦截 prompt 实现 js 与 native 的通信)
webview.setWebViewClient(new WebViewClient());
mattermost-mobile: https://github.com/mattermost/mattermost-mobile
[2]mobile-web-best-practice: https://github.com/mcuking/mobile-web-best-practice
[3]vue-cli3: https://cli.vuejs.org/
[4]typescript: http://www.typescriptlang.org/
[5]react: https://reactjs.org/
[6]组件库: #组件库
[7]JSBridge: #jsbridge
[8]路由堆栈管理(模拟原生 APP 导航): #路由堆栈管理模拟原生-app-导航
[9]请求数据缓存: #请求数据缓存
[10]构建时预渲染: #构建时预渲染
[11]Webpack 策略: #webpack-策略
[12]基础库抽离: #基础库抽离
[13]手势库: #手势库
[14]样式适配: #样式适配
[15]表单校验: #表单校验
[16]阻止原生返回事件: #阻止原生返回事件
[17]通过 UA 获取设备信息: #通过-ua-获取设备信息
[18]mock 数据: #mock-数据
[19]调试控制台: #调试控制台
[20]抓包工具: #抓包工具
[21]异常监控平台: #异常监控平台
[22]常见问题: #常见问题
[23]vant: https://youzan.github.io/vant/#/zh-CN/intro
[24]vux: https://github.com/airyland/vux
[25]mint-ui: https://github.com/ElemeFE/mint-ui
[26]cube-ui: https://github.com/didi/cube-ui
[27]less-loader: https://github.com/webpack-contrib/less-loader
[28]less: http://lesscss.org/
[29]modifyVars: http://lesscss.org/usage/#using-less-in-the-browser-modify-variables
[30]定制主题: https://youzan.github.io/vant/#/zh-CN/theme
[31]Vue 常用组件库的比较分析(移动端): https://blog.csdn.net/weixin_38633659/article/details/89736656
[32]DSBridge-IOS: https://github.com/wendux/DSBridge-IOS
[33]DSBridge-Android: https://github.com/wendux/DSBridge-Android
[34]WebViewJavascriptBridge: https://github.com/marcuswestin/WebViewJavascriptBridge
[35]mobile-web-best-practice-container: https://github.com/mcuking/mobile-web-best-practice-container
[36]JSBridge: https://github.com/mcuking/JSBridge
[37]JSBridge 实现原理: https://github.com/mcuking/JSBridge
[38]vue-page-stack: https://github.com/hezhongfeng/vue-page-stack
[39]vue-navigation: https://github.com/zack24q/vue-navigation
[40]vue-stack-router: https://github.com/luojilab/vue-stack-router
[41]vue-router: https://router.vuejs.org/
[42]【vue-page-stack】Vue 单页应用导航管理器 正式发布: https://juejin.im/post/5d2ef417f265da1b971aa94f
[43]Vue 社区的路由解决方案:vue-stack-router: https://juejin.im/post/5d4ce4fd6fb9a06acd450e8c
[44]mem: https://github.com/sindresorhus/mem
[45]nuxt.js: https://github.com/nuxt/nuxt.js
[46]next: https://github.com/zeit/next.js
[47]Puppeteer: https://github.com/GoogleChrome/puppeteer
[48]Phantomjs: https://github.com/ariya/phantomjs
[49]prerender-spa-plugin: https://github.com/chrisvfritz/prerender-spa-plugin
[50]vue 预渲染之 prerender-spa-plugin 解析(一): https://blog.csdn.net/vv_bug/article/details/84593052
[51]使用预渲提升 SPA 应用体验: https://juejin.im/post/5d5fa22ee51d4561de20b5f5
[52]webpack-dll-plugin: https://webpack.docschina.org/plugins/dll-plugin/
[53]Externals: https://webpack.docschina.org/configuration/externals/
[54]Webpack 优化——将你的构建效率提速翻倍: https://juejin.im/post/5d614dc96fb9a06ae3726b3e
[55]hammer.js: https://github.com/hammerjs/hammer.js
[56]AlloyFinger: https://github.com/AlloyTeam/AlloyFinger
[57]H5 案例分享:JS 手势框架 —— Hammer.js: https://www.h5anli.com/articles/201609/hammerjs.html
[58]使用 require.context 实现前端工程自动化: https://www.jianshu.com/p/c894ea00dfec
[59]postcss-px-to-viewport: https://github.com/evrone/postcss-px-to-viewport
[60]Viewport Units Buggyfill: https://github.com/rodneyrehm/viewport-units-buggyfill
[61]flexible: https://github.com/amfe/lib-flexible
[62]postcss-pxtorem: https://github.com/cuth/postcss-pxtorem
[63]Autoprefixer: https://github.com/postcss/autoprefixer
[64]browserslist: https://github.com/browserslist/browserslist
[65]Viewport Units Buggyfill: https://github.com/rodneyrehm/viewport-units-buggyfill
[66]rem-vw-layout: https://github.com/imwtr/rem-vw-layout
[67]细说移动端 经典的 REM 布局 与 新秀 VW 布局: https://www.cnblogs.com/imwtr/p/9648233.html
[68]如何在 Vue 项目中使用 vw 实现移动端适配: https://www.jianshu.com/p/1f1b23f8348f
[69]async-validator: https://github.com/yiminghe/async-validator
[70]vee-validate: https://github.com/baianat/vee-validate
[71]Mock: https://github.com/nuysoft/Mock
[72]eruda: https://github.com/liriliri/eruda
[73]vconsole: https://github.com/Tencent/vConsole
[74]charles: https://www.charlesproxy.com/
[75]fiddler: https://www.telerik.com/fiddler
[76]解锁 Charles 的姿势: https://juejin.im/post/5a1033d2f265da431f4aa81f
[77]sentry: https://github.com/getsentry/sentry
[78]sentry-javascript: https://github.com/getsentry/sentry-javascript
[79]sentry-webpack-plugin: https://github.com/getsentry/sentry-webpack-plugin
[80]babel-plugin-try-catch-error-report: https://github.com/mcuking/babel-plugin-try-catch-error-report
[81]babel-plugin-try-catch-error-report: https://github.com/mcuking/babel-plugin-try-catch-error-report
[82]babel: https://babeljs.io/
[83]如何监控网页崩溃?: https://juejin.im/entry/5be158116fb9a049c6434f4a
[84]sentry-webpack-plugin: https://github.com/getsentry/sentry-webpack-plugin
[85]【Android】WebView 的 input 上传照片的兼容问题: https://juejin.im/post/5a322cdef265da43176a2913
开发者技术前线 ,汇集技术前线快讯和关注行业趋势,大厂干货,是开发者经历和成长的优秀指南。