理论 | 可能是史上最全的weex踩坑攻略
Posted 腾讯IMWeb前端团队
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理论 | 可能是史上最全的weex踩坑攻略相关的知识,希望对你有一定的参考价值。
这是一篇有故事的文章 --- 来自一个weex在生产环境中相爱相杀的小码农
故事一: Build
虽然weex
的口号是一次撰写,多端运行, 但其实build
环节是有差异的, native
端构建需要使用weex-loader
, 而web
端则是使用vue-loader
,除此以外还有不少差异点, 所以webpack
需要两套配置。
最佳实践
使用webpack
生成两套bundle
,一套是基于vue-router
的web spa
, 另一套是native
端的多入口的bundlejs
首先假设我们在src/views
下开发了一堆页面:
build web配置
web端的入口文件有 render.js
main.js
App.vue
webpack.prod.conf.js
入口
build native配置
native端的打包流程其实就是将src/views
下的每个.vue
文件导出为一个个单独的vue
实例, 写一个node
脚本即可以实现。
webpack.build.conf.js
中生成并打包多入口:
最终效果:
故事二: 使用预处理器
在vue
单文件中, 我们可以通过在vue-loader
中配置预处理器, 代码如下:
而weex
在native环境下其实将css
处理成json
加载到模块中, 所以...
使用vue-loader配置的预处理器在web环境下正常显示, 在native中是无效的。
native环境下不存在全局样式, 在js文件中import 'index.css'也是无效的。
解决问题一
研究weex-loader
源码后发现在.vue
中是无需显示配置loader
的, 只需要指定<style lang="stylus">
并且安装stylus stylus-loader
即可,weex-loader
会根据lang
去寻找对应的loader
. 但因为scss
使用sass-loader
, 会报出scss-loader not found
, 但因为sass
默认会解析scss
语法, 所以直接设置lang="sass"
是可以写scss
语法的, 但是ide
就没有语法高亮了. 可以使用如下的写法:
语法高亮, 完美!
解决问题二
虽然没有全局样式的概念, 但是支持单独import
样式文件。
故事三: 样式差异
这方面官方文档已经有比较详细的描述, 但还是有几点值得注意的。
简写
weex
中的样式不支持简写, 所有类似margin: 0 0 10px 10px
的都是不支持的。
背景色
android
下的view是有白色的默认颜色的, 而ios如果不设置是没有默认颜色的, 这点需要注意。
浮点数误差
weex
默认使用750px * 1334px
作为适配尺寸, 实际渲染时由于浮点数的误差可能会存在几px
的误差, 出现细线等样式问题, 可以通过加减几个px
来调试。
嵌套写法
即使使用了预处理器, css
嵌套的写法也是会导致样式失效的。
故事四: 页面跳转
weex
下的页面跳转有三种形式:
native -> weex
:weex
页面需要一个控制器作为容器, 此时就是native
间的跳转。weex -> native
: 需要通过module形式通过发送事件到native来实现跳转。weex -> weex
: 使用navigator模块, 假设两个weex
页面分别为a.js, b.js
, 可以定义mixin
方法。
这样就组件里使用
this.push(url), this.pop()
来跳转。
跳转配置
iOS下页面跳转无需配置, 而
android
是需要的, 使用weexpack platform add android
生成的项目是已配置的, 但官方的文档里并没有对于已存在的应用如何接入进行说明。其实
android
中是通过intent-filter
来拦截跳转的。
然后我们新建一个
WXPageActivity
来代理所有weex
页面的渲染, 核心的代码如下:
故事五: 页面间数据传递
native -> weex
: 可以在native
端调用render
时传入的option
中自定义字段, 例如NSDictary *option = @{@"params": @{}}
, 在weex
中使用weex.config.params
取出数据。weex -> weex
: 使用storage。weex -> native
: 使用自定义module。
故事六: 图片加载
官网有提到如何加载网络图片 但是加载本地图片的行为对于三端肯定是不一致的, 也就意味着我们得给native
重新改一遍引用图片的路径再打包...
但是当然是有解决办法的啦。
Step 1
webpack
设置将图片资源单独打包, 这个很easy, 此时bundleJs
访问的图片路径就变成了/images/..
Step 2 那么现在我们将同级目录下的js文件夹与images文件夹放入
native
中, iOS中一般放入mainBundle
, Android一般放入src/main/assets
, 接下来只要在imgloader
接口中扩展替换本地资源路径的代码就ok了。
iOS
代码如下:
Android
代码如下:
故事七: 生产环境的实践
增量更新
方案一
可以使用google-diff-match-patch来实现, google-diff-match-patch拥有许多语言版本的实现, 思路如下:
服务器端构建一套管理前端
bundlejs
的系统, 提供查询bundlejs
版本与下载的api。客户端第一次访问
weex
页面时去服务端下载bundlejs
文件。每次客户端初始化时静默访问服务器判断是否需要更新, 若需更新, 服务器端
diff
两个版本的差异, 并返回diff
,native
端使用patch api
生成新版本的bundlejs
方案二
还可以参考很多ReactNative的成熟方案, 本质上都是js的热更新。
降级处理
一般情况下, 我们会同时部署一套web
端界面, 若线上环境的weex
页面出现bug, 则使用webview加载web
版, 推荐依赖服务端api来控制降级的切换。
总结
weex
的优势: 依托于vue
, 上手简单. 可以满足以vue
为技术主导的公司给native
双端提供简单/少底层交互/热更新需求的页面的需求。
weex
的劣势: 在native
端调整样式是我心中永远的痛.. 以及众所周知的生态问题, 维护组没有花太多精力解答社区问题, 官方文档错误太多, 导致我在看的时候就顺手提了几个PR。
扫码下方二维码,
随时关注更多前端干货文章!
▼
微信:IMWebTech
以上是关于理论 | 可能是史上最全的weex踩坑攻略的主要内容,如果未能解决你的问题,请参考以下文章