最全的weex踩坑攻略-出自大量实践与沉淀
在自己的业务环境中使用,并开放给第三方isv,企业开发者使用,这是一篇有内涵有故事的文章。
如果你对weex微应用感兴趣,也在开发着微信小程序,不妨来看看为了让你减少顾虑而准备的技术对比表格,是的,开发钉钉的weex微应用是如此的简单。
访问这个链接阅读: 钉钉Weex微应用与微信小程序技术对比表格 。
技术概述
weex
是阿里开源的一套构建高性能移动界面的原生跨平台技术框架,它的上层由Vue
,Rax(非常类似React的开发框架)
实现数据驱动,底层由iOS,Android实现render engine来驱动界面的最终落地。类比React Native
它的优势在于难得的一次编写,多端运行
,是的,它也很好的支持着移动Web端。
构建-build
Native
使用weex-loader
,Web
则需要使用vue-loader
,在Web
端上vue-loader
目前仅支持^11.3.3
版本,以及weex-vue-render
需要>= 0.11.50
,并且vue-loader
的配置做如下修改:
webpack 1.x
module: { loaders: [ { test: /\.vue(\?[^?]+)?$/, loaders: ['vue-loader'] } ] }, vue: { /** * important! should use postTransformNode to add $processStyle for * inline style normalization. */ compilerModules: [ { postTransformNode: el => { el.staticStyle = `$processStyle(${el.staticStyle})` el.styleBinding = `$processStyle(${el.styleBinding})` } } ] }
webpack 2.x
module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { compilerModules: [ { postTransformNode: el => { el.staticStyle = `$processStyle(${el.staticStyle})` el.styleBinding = `$processStyle(${el.styleBinding})` } } ] } } ] }
最佳的实践是推荐你使用目前为止我们内部评价最高的一份脚手架工程(支持三端一致,意味着处理了降级。):dingtalk-templates/webpack,你可以直接下载它,自行修改package.json
文件中的{{}}
配置,或者安装 open-dingtalk/weex-dingtalk-cli 这个命令行工具来玩转脚手架,这个命令行工具就像你使用vue-cli
一样的简单:
$ npm install -g weex-dingtalk-cli
样式-style
weex支持的样式属于css子集
必须写完整,如
background:#000
需要写成background-color:#000
样式不允许提取文件,必须写在
Vue
的单组件中原则上不推荐使用
预处理器
,因为无法预期转译出来的样式符合weex的css子集布局只能使用Flexbox
如果要显示文本必须使用
text
组件,并且你想改变字体大小必须写在text
组件上只支持
class
,不允许继承单位只支持
px
不支持背景图片
基于
750px
进行缩放,会有浮点
级别的误差样式需要声明
scoped
属性Android上处理圆角,必须在外层
div
中设置border-radius
如果你想动态的替换
class
,只能使用数组表达式,<div :class=['name', a? 'b': 'c']></div>
如果你想使用预处理器
(只是不推荐),可以如下配置:
{ test: /\.vue$/, loader: 'vue-loader', options: { loaders: { scss: 'vue-style-loader!css-loader!sass-loader' } } }
<style lang="sass"> @import './common.scss' // ... </style>
如果你想使用更精准的适配(无法忍受浮点级别的误差),可以获取scale
,deviceWidth
自行进行适配,推荐在loader
阶段去处理(自行开发转换工具)。
JavaScript与内存管理-JavaScript and memory manage
由于JS运行在JavaScriptCore/V8中,此与Web有较大差异。
如下:
jquery
,axios
之类的原来Web开发领域的库都不可以使用不支持DOM操作
虽然提供了Native DOM可以操作界面的渲染,原则上不推荐使用,方法与DOM操作类似
既然不支持DOM操作,更改界面的方式应该使用数据驱动
仅支持部分事件
weex SDK
>= 0.10.0
的才支持事件冒泡没有window,document,location,history等对象
runtime是一个“全局环境”,不允许往全局环境中挂载对象,因为无法释放且所有weex页面共享
只有scroller和list组件可以滚动
不允许在Vue中操作
style
,遍历是很耗性能的Vue中的
v-show
等原来操作Dom的指令或Api都不可以使用vue-router 只允许使用
abstract
模式vuex必须在初始化之前使用
Vue.use
注入native端只能使用网络图片,解决的方式是在最后上线时统一替换成CDN
热更新以及增量更新的方式都可以参考React Native目前成熟的方案
iOS由于使用了同一套URL System,UIWebView的cookie是会共享到weex中的,同理weex中的cookie也是会共享的,只有WKWebView不会。原则上,你不应该使用cookie来处理用户体系的问题
weex native 与 weex web 之间的差异较大,那么怎么办?
我们提供了一套抹平一些常见差异的库,你也可以在weex
环境中使用,https://github.com/open-dingtalk/weex-dingtalk-journey。
在说内存(memory)之前,大家先来看一副图,weex的内存分布:
正常情况下,Native memory 业务开发人员是无法处理的,而运行在js core 中的内存,我们知道如果不断开引用,js是无法回收释放内存的。
不允许往
runtime
里去挂载对象业务代码中的一些引用在
beforeDestroy
中断开设置为null
学会使用工具分析内存泄漏的问题,https://webkit.org/downloads/
不要随意的使用函数递归,缩短对象方法的执行路径(传统JS领域的内存管理最佳实践也适用一部分)
由于界面的渲染需要依赖
createInstance(id, code, config, data)
,sendTasks(id, tasks)
,receiveTasks(id, tasks)
发送指令的方式进行通信,你应该减少通信的次数,在更新界面时,合并不必要的通信指令的发送。如果你使用vue-router的方式,尽量减少组件之间的共享。
转场方式-navigator
由于weex
的特殊性,它的转场方式有几种构成。
weex
toweex
,如果你需要支持钉钉js-api,那么你应该使用openLink
。(如果是你自己实现,使用weex自带的navigator模块)weex
toh5
依然使用openLink
,(如果是你自己实现,那么可以通过module
的方式来打开一个WebViewController| UIWebView or WKWebView)Native
toweex
直接alloc weex 容器的Controller传入Url即可
如果你使用vue-router
,那么配置好你的路由path,使用push
,go
方法即可,唯一可惜的是使用vue-router
的方式较为生硬。
页面级别的数据传输-Page level data transfer
页面级别的数据传输基本很少会发生,钉钉的开发者推荐统一使用domainStorage方案。
weex
toweex
通过URL传参数(携带的数据量有限),通过weex storage moduleweex
toh5
,h5
toweex
通过URL传参数Native
toweex
通过alloc weex 容器中的option或者data传入,前者可以在weex.config中获取,后者可以在vm上下文中获取weex
toNative
定义一个跳转native的module,使用native的属性或者init时传入
调试工具-Debug Kit used
weex的调试工具需要额外安装weex-toolkit
,weex-devtool
,以及在你的Native工程中集成对应的WXDevtool(iOS)
。
如果你运行weex debug
遇到如下的错误:
Error: EACCES: permission denied, open '/Users/xxx/.xtoolkit/node_modules/weex-devtool/frontend/weex/weex-bundle.js' at Error (native)
(非Windows用户)使用sudo
即可。
不集成
WXDevtool SDK
首先,你需要安装Weex Playground
,可自行在各大市场中下载安装。
不需要指明文件路径,在终端输入:
$ weex debug
先使用 Weex Playground
扫码(启动成功后会弹出一个界面),然后将你的业务代码贴到 这里,注意:
不允许出现
import
等导入模块的语法安装了
Weex Playground
的设备和你的电脑必须在同一局域网内
最后用安装了Weex Playground
的设备扫码(业务代码贴过去那里的右侧会出现的二维码)。
集成
WXDevtool SDK
[WXDevTool setDebug:YES]; [WXDevTool launchDevToolDebugWithUrl:@"ws://192.168.1.108:8088/debugProxy/native"];
ws:// xxx.xx..x 这个地址是在用weex debug 在终端里给你输出出来的,如果setDebug为YES会开启debugger模式,反之亦然。
注意setDebug
设置为YES
。
原生开发-Native
请直接阅读 技术 | Weex入坑之旅 ,这是用iOS视角写的一篇文章,大概在半年之前。
写在最后
希望大家可以用一个开放的心态来看待weex
,它的设计,实现有很多是值得学习的地方,比如多framework
支持,共享runtime
,module
,component
,handler
等等,非常的自由领域,相当于它设计好了一个render engine
,理论上你可以学习它的几个关键接口,知道Native DOM指令后,也能开发出替代Vue的上层框架,不信?你看看Rax即明白了。
weex
也有一些不足的地方,开发者数量少,社区活跃度不高,很多问题并不一定能被google搜录到。文档确实有一点不完善,native的实现也有一定的bug数量,你看react
这么多年了,依然有bug,只要在逐步改进迭代修复,我觉得它就是非常棒的,万事没有十全十美,美中不足的一点瑕疵,说不定才是完美呢。