2016年4月21日,阿里巴巴在Qcon大会上宣布开源跨平台移动开发工具Weex,Weex能够完美兼顾性能与动态性,让移动开发者通过简捷的前端语法写出Native级别的性能体验,并支持iOS、安卓、YunOS及Web等多端部署。
对于移动开发者来说,Weex主要解决了频繁发版和多端研发两大痛点,同时解决了前端语言性能差和显示效果受限的问题。开发者可通过Weex官网申请内测。(http://alibaba.github.io/weex/) 开发者只需要在自己的APP中嵌入Weex的SDK,就可以通过撰写HTML/CSS/JavaScript来开发Native级别的Weex界面。Weex界面的生成码其实就是一段很小的JS,可以像发布网页一样轻松部署在服务端,然后在APP中请求执行。
与 现有的开源跨平台移动开放项目如Facebook的React Native和微软的Cordova相比,Weex更加轻量,体积小巧。因为基于web conponent标准,使得开发更加简洁标准,方便上手。Native组件和API都可以横向扩展,方便根据业务灵活定制。Weex渲染层具备优异的性 能表现,能够跨平台实现一致的布局效果和实现。对于前端开发来说,Weex能够实现组件化开发、自动化数据绑定,并拥抱Web标准。
快速上手
参考文档:开发文档
Weex 是一套简单易用的跨平台开发方案,能以 web 的开发体验构建高性能、可扩展的 native 应用,为了做到这些,Weex 与 Vue 合作,使用 Vue 作为上层框架,并遵循 W3C 标准实现了统一的 JSEngine 和 DOM API,这样一来,你甚至可以使用其他框架驱动 Weex,打造三端一致的 native 应用。
Vue 是什么?
Vue.js 是 Evan You 开发的渐进式 JavaScript 框架。开发者能够通过撰写 *.vue 文件,基于 <template>, <style>, <script> 快速构建组件化的 web 应用。
Hello World
Playground App
尝试 Weex 最简单的方法是使用 Playground App 和在 dotWe 编写一个 Hello World 例子。你不需要考虑安装开发环境或编写 native 代码,只需要做下面两件事:
为你的手机安装 Playground App,当然,Weex 是跨平台的框架,你依然可以使用浏览器进行预览,只是这样你就无法感受到 native 优秀的体验了。
在新标签页中打开 Hello World 例子,点击预览,然后用 Playground 扫码即可。
<template>
<div>
<text class="text">{{text}}</text>
</div>
</template>
<style>
.text {
font-size: 50;
}
</style>
<script>
export default {
data () {
return {
text: 'Hello World.'
}
}
}
</script>
搭建开发环境
第一步:安装依赖
brew install node
npm install -g weex-toolkit
国内开发者可以考虑使用淘宝的 npm 镜像 —— cnpm 安装 weex-toolkit
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
$ cnpm install -g weex-toolkit
第二步:初始化
然后初始化 Weex 项目:
$ weex init awesome-project
执行完命令后,在 awesome-project 目录中就创建了一个使用 Weex 和 Vue 的模板项目。
第三步:开发
之后我们进入项目所在路径,weex-toolkit 已经为我们生成了标准项目结构。
在 package.json 中,已经配置好了几个常用的 npm script,分别是:
build: 源码打包,生成 JS Bundle
dev: webpack watch 模式,方便开发
serve: 开启静态服务器
debug: 调试模式
我们先通过 npm install 安装项目依赖。之后运行 npm run dev 和 npm run serve 开启watch 模式和静态服务器。
然后我们打开浏览器,进入 http://localhost:8080/index.html 即可看到 weex h5 页面。
初始化时已经为我们创建了基本的示例,我们可以在 src/foo.vue 中查看。
代码如下所示:
<template>
<div class="wrapper">
<text class="weex">Hello Weex !</text>
<text class="vue">Hello Vue !</text>
</div>
</template>
<style scoped>
.wrapper {
flex-direction: column;
justify-content: center;
}
.weex {
font-size: 60px;
text-align: center;
color: #1B90F7;
}
.vue {
font-size: 60px;
text-align: center;
margin-top: 30px;
color: #41B883;
}
</style>
关于 Weex 语法部分,你可以直接参考 Vue Guide
集成到 iOS
通过cocoaPods 集成 Weex iOS SDK到你的项目
首先假设你已经完成了安装 iOS 开发环境 和 CocoaPods
第一步:添加依赖
导入 Weex iOS SDK 到你已有的项目, 如果没有,可以参考新建项目在继续下面内容之前,确保你已有的项目目录有名称为 Podfile
文件,如果没有,创建一个,用文本编辑器打开
集成 framework
WeexSDK 在 cocoaPods 上最新版本 可以在这获取
在 Podfile
文件中添加如下内容
source 'git@github.com:CocoaPods/Specs.git'
target 'YourTarget' do
platform :ios, '7.0'
pod 'WeexSDK', '0.9.5' ## 建议使用WeexSDK新版本
end
源码集成
首先 拷贝 ios/sdk
目录到你已有项目目录 (此处以拷贝到你已有项目的根目录为例子),然后在 Podfile
文件中添加
source 'git@github.com:CocoaPods/Specs.git'
target 'YourTarget' do
platform :ios, '7.0'
pod 'WeexSDK', :path=>'./sdk/'
end
第二步:安装依赖
打开命令行,切换到你已有项目 Podfile
这个文件存在的目录,执行 pod install
,没有出现任何错误表示已经完成环境配置。
第三步:初始化 Weex 环境
在 AppDelegate.m
文件中做初始化操作,一般会在 didFinishLaunchingWithOptions
方法中如下添加。
//business configuration
[WXAppConfiguration setAppGroup:@"AliApp"];
[WXAppConfiguration setAppName:@"WeexDemo"];
[WXAppConfiguration setAppVersion:@"1.0.0"];
//init sdk enviroment
[WXSDKEngine initSDKEnviroment];
//register custom module and component,optional
[WXSDKEngine registerComponent:@"MyView" withClass:[MyViewComponent class]];
[WXSDKEngine registerModule:@"event" withClass:[WXEventModule class]];
//register the implementation of protocol, optional
[WXSDKEngine registerHandler:[WXNavigationDefaultImpl new] withProtocol:@protocol(WXNavigationProtocol)];
//set the log level
[WXLog setLogLevel: WXLogLevelAll];
第四步:渲染 weex Instance
Weex 支持整体页面渲染和部分渲染两种模式,你需要做的事情是用指定的 URL 渲染 Weex 的 view,然后添加到它的父容器上,父容器一般都是 viewController。
#import <WeexSDK/WXSDKInstance.h>
- (void)viewDidLoad
{
[super viewDidLoad];
_instance = [[WXSDKInstance alloc] init];
_instance.viewController = self;
_instance.frame = self.view.frame;
__weak typeof(self) weakSelf = self;
_instance.onCreate = ^(UIView *view) {
[weakSelf.weexView removeFromSuperview];
[weakSelf.view addSubview:weakSelf.weexView];
};
_instance.onFailed = ^(NSError *error) {
//process failure
};
_instance.renderFinish = ^ (UIView *view) {
//process renderFinish
};
NSURL *url = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"js"]
[_instance renderWithURL:url options:@{@"bundleUrl":[self.url absoluteString]} data:nil];
}
WXSDKInstance 是很重要的一个类,提供了基础的方法和一些回调,如 renderWithURL
, onCreate
, onFailed
等,可以参见 WXSDKInstance.h
的声明。
第五步:销毁 Weex Instance
在 viewController 的 dealloc 阶段 销毁掉 Weex instance,释放内存,避免造成内存泄露。
- (void)dealloc
{
[_instance destroyInstance];
}
导入 Weex SDK framework 到工程
可以通过源码编译出 Weex SDK,可以在新的 feature 或者 bugfix 分支,尝试最新的 feature。
参考此处直接导入 weexSDK。
工作原理
整体架构
Weex 表面上是一个客户端技术,但实际上它串联起了从本地开发环境到云端部署和分发的整个链路。开发者首先可以在本地像撰写 web 页面一样撰写一个 app 的页面,然后编译成一段 JavaScript 代码,形成 Weex 的一个 JS bundle;在云端,开发者可以把生成的 JS bundle 部署上去,然后通过网络请求或预下发的方式传递到用户的移动应用客户端;在移动应用客户端里,WeexSDK 会准备好一个 JavaScript 引擎,并且在用户打开一个 Weex 页面时执行相应的 JS bundle,并在执行过程中产生各种命令发送到 native 端进行的界面渲染或数据存储、网络通信、调用设备功能、用户交互响应等移动应用的场景实践;同时,如果用户没有安装移动应用,他仍然可以在浏览器里打开一个相同的 web 页面,这个页面是使用相同的页面源代码,通过浏览器里的 JavaScript 引擎运行起来的。
本地开发环境
Weex 的本地开发环境基于 web 开发体验而设计,web 开发者可以通过自己熟悉的 HTML/CSS/JavaScript 技术和语法实现移动应用的界面。同时 Weex 也对 Vue.js 这一非常优秀的前端框架做了官方的支持。
除此之外,Weex 的工程设计也是 web 开发者非常熟悉的,首先 web 开发者可以使用自己熟悉的 npm 进行依赖管理;其次 web 开发者在通过项目脚手架初始化工程、开发、调试、质量控制等各个环节,都可以参考 web 开发已有的最佳实践。
和如今 web 开发的最佳实践一样,Weex 会把一个页面的源代码全部编译打包成一个 JS bundle,在浏览器中,我们需要把这个 JS bundle 作为一段 <script>
载入网页,在客户端里,我们把这段 JS bundle 载入本地,并通过 WeexSDK 直接执行。
云端部署和分发
Weex 的 JS bundle 可以作为 web 开发中的一段静态资源进行部署和下发。几乎可以复用 HTML5 所有的工程体系和最佳实践。比如在本地开发环境通过部署工具将 JS bundle 部署到 CDN、通过 CMS 或搭建平台把业务数据和模块化的前端组件自动化拼接生成 JS bundle、通过服务端 JS bundle 的流量和日志统计页面的访问情况、通过 AppCache 或类似的方式对 JS bundle 在客户端进行缓存或预加载以降低网络通信的成本等。
客户端 JavaScript 引擎
Weex 的 iOS 和 Android 客户端中都会运行一个 JavaScript 引擎,来执行 JS bundle,同时向各端的渲染层发送规范化的指令,调度客户端的渲染和其它各种能力。我们在 iOS 下选择了 JavaScriptCore 内核,而在 Android 下选择了 UC 提供的 v8 内核。无论是从性能还是稳定性方面都提供了强有力的保障。
为了让整个移动应用的资源利用得更好,我们在客户端提供的 JavaScript 引擎是单例的,即所有 JS bundle 公用一个 JavaScript 内核实例,同时对每个 JS bundle 在运行时进行了上下文的隔离,使得每个 JS bundle 都能够高效安全的工作。我们还把 Vue 2.0 这样的 JS Framework 做了预置,开发者不必把 JS Framework 打包在每个 JS bundle 里,从而大大减少了 JS bundle 的体积,也就进一步保障了页面打开的速度。
客户端渲染层
Weex 目前提供了 iOS 和 Android 两个客户端的 native 渲染层。每个端都基于 DOM 模型设计并实现了标准的界面渲染接口供 JavaScript 引擎调用。并且结合 web 标准和 native 的特点和优势实现了一套统一的组件和模块。Weex 在性能方面的表现也是非常优异的,尤其是界面首屏加载时间、native 下长列表的资源开销和复用情况、CPU、内存、帧率 等关键指标。当然,尽管 Weex 官方已经提供了一组开发者最常用的组件和模块,但面对丰富多样的移动应用研发需求,团队也难免会力不从心,为此我们提供了灵活自由的横向扩展能力,开发者可以根据自身的情况定制属于自己的客户端组件和模块,进一步丰富 Weex 在客户端上的能力。
浏览器渲染
Weex 除了提供 iOS 和 Android 的客户端渲染层之外,还基于 Vue 2.0 对官方的所有组件和模块进行了封装,开发者可以基于 Vue 2.0 用同一套源代码构建出在浏览器中相同效果的页面。并且同样可以横向扩展。
一次撰写,多端运行
Weex 提供了多端一致的技术方案。
首先 web 开发体验在各端当中是相同的。包括语法设计和工程链路。
其次,Weex 的组件、模块设计都是 iOS、Android、Web 的开发者共同讨论出来的,有一定的通用性和普遍性。
Weex 开发同一份代码,可以在不同的端上分别执行,避免了多端的重复研发成本。
Weex 页面结构
一个 Weex 页面就是一个相对独立解耦的移动应用界面,它不仅包括了界面展示、更包含了逻辑处理、设备能力使用、生命周期管理等部分。
界面
DOM 模型
Weex 页面通过类似 HTML DOM 的方式管理界面,首先页面会被分解为一个 DOM 树,,每个 DOM 结点都代表了一个相对独立的 native 视图的单元。然后不同的视图单元之间通过树形结构组合在了一起,构成一个完整的页面。
相关链接
Weex Native DOM APIs
组件
Weex 支持文字、图片、视频等内容型组件,也支持 div、list、scroller 等容器型组件,还包括 slider、input、textarea、switch 等多种特殊的组件。Weex 的界面就是由这些组件以 DOM 树的方式构建出来的。
相关链接
Weex 组件列表
布局系统
Weex 页面中的组件会按照一定的布局规范来进行排布,我们这里提供了 CSS 中的盒模型、flexbox 和 绝对/相对/固定/吸附布局这三大块布局模型。
盒模型:通过宽、高、边框、内外边距、边框等 CSS 属性描述一个组件本身的尺寸。
flexbox:通过 CSS 3 Flexbox 布局规范定义和描述组件之间的空间分布情况。
position:支持 CSS position 属性中的 absolute
, relative
, fixed
, sticky
位置类型,其中 relative
是默认值。
功能
Weex 提供了非常丰富的系统功能 API,包括弹出存储、网络、导航、弹对话框和 toast 等,开发者可以在 Weex 页面通过获取一个 native module 的方式引入并调用这些客户端功能 API。
生命周期
每个 Weex 页面都有其自身的生命周期,页面从开始被创建到最后被销毁,会经历到整个过程。这是通过对 Weex 页面的创建和销毁,在路由中通过 SDK 自行定义并实现的。
使用 weex-toolkit
weex-toolkit 是官方提供的一个脚手架命令行工具,你可以使用它进行 Weex 项目的创建,调试以及打包等功能。
安装
weex-toolkit
支持预览你当前开发的weex页面(.we
或者.vue
),你只需要指定预览的文件路径即可:
$ weex src/foo.vue
浏览器会自动弹出页面,这个时候你可以看到你所编辑的 Weex页面的具体效果和页面布局。如果你使用 Playground 扫描右边的二维码,就能够看到 Weex 在 Android/IOS 设备上的效果了。
如果你需要预览整个项目目录,你可以输入这样的命令:
$ weex src --entry src/foo.vue
你需要在传入的参数指定预览的目录和入口文件。
打包weex项目
如果开发完成后,你可以使用 weex compile
通过命令行工具进行单个文件或者整个项目的打包。
weex compile src/foo.vue dist
命令行需要两个参数,你的源码文件或者目录, 以及你生成打包后的目录地址。
调试 Weex 页面
weex-toolkit支持调试工具。weex devtools ,它是专门为Weex定制的一款实现了 Chrome Debugging Protocol 的 inspect/debug 工具,能够帮助你快速查看 app 运行状态和调试 Weex 中的 JS 代码,当前支持 IOS 和 Android 两个平台。
用法
weex debug [options] [we_file|bundles_dir]
选项:
-h, --help 显示帮助
-V, --verbose 显示 debug 服务器运行时的各种 log
-v, --version 显示版本
-p, --port [port] 设置 debug 服务器端口号 默认为8088
-e, --entry [entry] debug 一个目录时,这个参数指定整个目录的入口 bundle 文件,这个 bundle 文件的地址会显示在 debug 主页上(作为二维码)
-m, --mode [mode] 设置构建 we 文件的方式,transformer 最基础的风格适合单文件, loader:webpack 风格 适合模块化的多文件 . 默认为 transformer
$ weex debug
单纯启动一个调试服务器,并同时唤起Chrome浏览器打开调试主页
。这个调试主页
上会有一个二维码,使用 Playground App 扫这个二维码可以开启 Playground 调试。开启调试后,设备列表中会出现您的设备,根据提示进行后续的调试操作。
调试 .we
| .vue
文件
$ weex debug your_weex.vue
这个命令会将 your_weex.vue
编译成 JS Bundle
文件 部署到 debug 服务器;并启动debug服务器如上述命令那样打开的调试vue主页
会多显示一个二维码,使用 Playground App扫这个二维码码可以加载 your_weex.we
(注意要先扫描开启调试的那个二维码码)。这个命令会自动检测 your_weex.we
文件变动,如果发现内容被修改则立即重新编译部署,并刷新 debugger
页面。.
调试整个bundle/we文件夹
同样你也可以调试整个目录的文件,你只需要传入目录的路径和入口文件即可;
$weex debug your/we/path -e index.we
这个命令会编译你指定目录下的所有的 .we
文件,并把编译好的 JS Bundle 部署到 debug 服务器,他们的地址会映射到 http://lcoalhost:8088/weex/ 下比如 your/we/path/index.we
可以通过 http://lcoalhost:8088/weex/index.js 访问。your/we/path/demo/test.we
可以通过 http://lcoalhost:8088/weex/demo/index.js 。
-e
参数可以指定一个入口的 .we
文件,这个文件的地址会显示在调试主页
上(作为二维码)。
Weex和React Native的异同
相同点:
都采用Web的开发模式,使用JS开发;
都可以直接在Chrome中调试JS代码;
都支持跨平台的开发;
都可以实现hot reload,边更新代码边查看效果;
不同点:
JS引擎
什么是JS引擎
学习成本
1.环境配置:ReactNative需要按照文档安装配置很多依赖的工具,相对比较麻烦。 weex安装cli之后就可以使用
2.vue vs react:上面已经做过对比react模板JSX学习使用有一定的成本 vue更接近常用的web开发方式,模板就是普通的html,数据绑定使用mustache风格,样式直接使用css
社区支持
Weex开源较晚,互联网上相关资料还比较少,社区规模较小;
React Native社区则比较活跃,可以参考的项目和资料也比较丰富
一张图:从渲染时间,内存使用,CPU占用,帧率(图形处理器每秒钟能够刷新几次,高的帧率可以得到更流畅、更逼真的动画。每秒钟帧数 (fps) 愈多,所显示的动作就会愈流畅。)