Sencha Cmd学习笔记
Sencha Cmd是一套跨平台的命令行工具,用于支持整个ExtJS开发的生命周期。它包含以下功能:
- 代码生成工具:可以生成整个应用程序,并且使用MVC模式扩展应用程序
- JS编译器:此编译器理解Sencha的ExtJS/Touch框架,可以减少应用程序加载时间
- Web服务器:一个轻量级的,开发用Web服务器
- 包管理系统:分布式的包管理系统,可以方便的集成其它用户开发的、发布到Sencha Package Repository的包(例如ExtJS主题)到当前应用程序
- 工作区管理:辅助跨越多个应用的框架、包、代码共享
- 构建脚本:自动生成应用的构建脚本,并且暴露before、after扩展点
- 支持与Cordova/Phone集成
- 图形捕获:为支持遗留浏览器,可以将CSS3特性转换为图片
- 优化工具:强大的代码选择工具,用于微调、确定哪些被包含在最终的构建中;确定跨越多个页面的公共代码并共享
- 灵活的配置系统
- 日志系统:详尽的日志,让你可以了解命令的内部工作步骤
1 2 3 4 |
# 一般命令调用格式 sencha [category] [command] [options...] [arguments...] # 帮助 sencha help [module] [action] |
选项 | 说明 |
--debug --info --quiet |
设置调试日志的级别 --quiet 仅仅显示警告、错误 |
--strict | 把警告作为错误看待 |
--plain | 禁止调试日志中的高亮 |
--beta | 启用Beta版本的包仓库 |
--cwd | 设置命令执行的“当前目录” |
--nologo | 禁止输出版本信息 |
--sdk-path | 对于非app类子命令,指定ExtJS SDK的目录 |
--time | 显示命令的执行耗时 |
这类子命令执行多种应用程序的构建处理:
命令 | 说明 | ||
upgrade | 自动生成的应用程序中,有两类文件与Cmd有关:构建脚本(scaffold)、ExtJS/Touch SDK。偶尔的情况下,你需要更新这些内容:
|
||
init | 初始化当前目录为一个Sencha Cmd应用程序,可以从空白目录开始:
|
||
install | 确保不完整的Sencha Cmd应用程序变得可以运行(补充缺失的文件):
|
||
build | 构建应用程序:
|
||
refresh | 执行部分构建,仅仅构建脚本相关的部分 |
生成模型、控制器或者其它组件,甚至整个应用程序:
命令 | 说明 | ||
app | 生成一个起步应用程序:
|
||
controller | 为当前应用程序生成一个控制器:
|
||
form | 为当前应用生成一个表单,仅Touch | ||
model | 为当前应用生成一个模型:
|
||
package | 生成一个起步的本地包,存放到packages/local下:
|
||
profile | 为当前应用程序生成一个配置,仅Touch | ||
theme | 为slice操作生成一个主题页面,仅ExtJS | ||
view | 为当前应用程序生成一个视图相关组件
|
||
workspace | 生成一个新的工作区 |
这一类子命令用于管理包的远程仓库:
命令 | 说明 | ||
list | 列出可用的远程仓库 | ||
add | 添加一个远程仓库:
|
||
remove | 删除一个远程仓库 |
命令 | 说明 | ||
upgrade | 升级Sencha Cmd本身。示例:
|
可以使用下面的命令生成一个Universal应用的脚手架:
1 |
sencha -sdk /home/alex/JavaScript/extjs/6.2.0 generate app MyApp MyApp |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
. ├── app # 当前应用有关文件的目录 │ ├── Application.js # 当前应用的实现类,扩展Ext.app.Application │ ├── model # 视图模型、模型存放目录 │ ├── store # 存储存放目录 │ └── view # 视图控制器、控制器存放目录 ├── app.js # 应用入口点定义 ├── app.json # 应用描述符文件 ├── bootstrap.js # 自举文件,其中包含微加载器 ├── build # 构建结果存放目录 │ ├── development # 构建环境:development的构建结果 │ └── temp ├── build.xml ├── classic # 针对classic toolkit的源代码 │ ├── sass │ └── src # 组件,主要是UI组件 ├── ext # 复制来的ExtJS SDK完整目录 ├── index.html # 入口点网页 ├── modern # 针对modern toolkit的源代码 │ ├── sass │ └── src # 组件,主要是UI组件 ├── overrides # 对组件的重写存放在此 ├── packages # 依赖的包存放在此 ├── resources # 资源文件存放在此 ├── .sencha │ ├── app │ │ ├── defaults.properties # 构建属性的默认值和说明 │ │ ├── development.defaults.properties # 针对构建环境development的默认构建属性 │ │ ├── development.properties # 针对构建环境development的构建属性 │ │ ├── ext.properties # 针对ExtJS的构建属性 │ │ ├── sencha.cfg # Sencha Cmd配置文件 └── workspace.json # 工作区描述符文件 |
执行下面的命令构建当前应用:
1 |
sencha app build |
该命令会构建你的HTML页面、JS代码和主题到build目录中。
Sencha Cmd根据你的app.json,生成自举脚本(bootstrap)。自举脚本向动态类加载器(Ext.Loader以及微加载器)传递必要的信息,后者负责加载程序代码。自举脚本不会被你的JS代码的变动影响,因此你需要执行编辑 - 保存 - 重新载入 这样的工作流程。
要保证自举脚本与最新的源码文件匹配,可以基于以下两种途径之一:
- 使用 sencha app watch ,该命令启动一个Web服务器,并且监控源码,在源码改变后立即执行一次开发环境构建(development build)。该方式支持Fashion的Live Update功能
- 手工构建并更新:
1234# 除了更新JS部分,还继续样式的编译,并生成CSSsencha app build development# 仅仅更新bootstrap与JS相关的部分sencha app refresh
Cmd 6引入了此组件,用于支持快速开发ExtJS 6主题。联合使用app watch可以启用所谓实时更新(Live Update)的特性。
实时更新利用Fashion来编译Scss,并且将其生成的最新CSS注入到浏览器页面。Fashion基于JavaScript实现,不需要Ruby的支持。
Fashion扩展了Sass语言,添加了新的特性,以便Sencha Inspector之类的工具可以可视化的查看、编辑主题、应用中定义的变量。
配置app.json以启用实时更新:
1 2 3 4 5 |
"development": { "tags": [ "fashion" ] }, |
也可以不指定上述配置,直接修改URL来启用实时更新: ?platformTags=fashion:1
启用实时更新时,加载到浏览器的是Sass而非生成的CSS,当Sass发生变化时,Fashion会立即编译之并更新页面上的CSS。
动态变量是Fashion对Sass的语言扩展。在Fashion中动态变量非常重要,动态变量类似于普通变量,但是其值被 dynamic() 标记包围。动态变量之间的交互方式与普通变量不同:
1 2 3 4 5 |
$bar: dynamic(blue); $foo: dynamic($bar); // 变量$foo依赖于$bar $bar: dynamic(red); @debug $foo; // $foo的值为red而不是blue |
可以注意到,动态变量的值并非在逐行处理过程中确定的。对动态变量的处理分为赋值、估算两个阶段。
赋值阶段的处理类似于普通变量,按照级联的顺序赋值。对动态变量的赋值只能在文件范围(位于任何控制块的外面)进行:
1 2 3 4 5 6 7 |
$bar: dynamic(blue); @if something { $bar: dynamic(red); // 非法 } $bar: dynamic(if(something, red, blue)); // 合法 |
这一限制是动态变量估算、提升行为(hoisting behaviors)所需。
在声明之后,再次对动态变量赋值,必须要附带dynamic():
1 2 3 4 |
$bar: dynamic(blue); $bar: red; // bar被赋值为red $bar: green !default; // 重新赋值为green @debug $bar; // green |
在该阶段,根据依赖顺序(而不是声明顺序)确定动态变量的实际值,例如:
1 2 |
$bar: dynamic(mix($colorA, $colorB, 20%)); $bar: dynamic(lighten($colorC, 20%)); |
由于对$bar进行了再次赋值,$bar依赖于$colorC,因此仅当$colorC的值被估算出来后,$bar的值即可确定,至于$colorA、$colorB何时估算,与$bar无关。
为了实现估算阶段的逻辑,Fashion收集所有动态变量,在执行任何Sass代码之前统一的估算它们。这意味着类似于JavaScript变量,Fashion动态变量也是被提升到作用域最前面的。
当一个变量用于给动态变量赋值,其本身也被升级为动态变量:
1 2 |
$foo: blue; // 尽管$foo作为普通变量声明,但是由于动态变量$bar依赖于它,因此$foo被升级为动态变量 $bar: dynamic($foo); |
你可以通过编写JS代码来扩展Fashion,要在Sass中包含这些扩展代码,可以:
1 2 |
require("my-module"); require("../path/file.js"); |
在内部,Fashion使用ES6的System.import加载标准的JS模块。
一个扩展的代码可以如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// ES6以前的版本 exports.init = function(runtime) { runtime.register({ magic: function (first, second) { } }); }; // ES6 module foo { export function init (runtime) { runtime.register({ magic: function (first, second) { } }); } } |
编译器是Sencha Cmd的主要组件。此编译器并不类似于:
- YUI压缩器
- Google Closure编译器
- UglifyJS
上述工具解决JS开发者面临的不同问题,但是它们不能理解Sencha框架,例如Ext.define用于定义类。
编译器用于提供框架相关的优化、诊断,一旦代码通过了此编译器,其它一般性的工具可以继续处理它。这类优化可以极大的改善ExtJS的加载时间,特别是针对遗留浏览器。
为了编译器能够最优化的操作, 你必须遵循一系列的编码约定,这样编译器才能理解你的代码,进而执行优化操作。
Cmd生成的动态加载器,以及之前的JSBuilder,都假设代码按照一定的规则组织。你应该保证:
- 每个JavaScript源文件应该在全局作用域包含一个Ext.define 语句
- 源文件的文件Base名必须和ExtJS类的Simple name匹配
- ExtJS类的命名空间应当映射为源码子目录
- 为了让编译器能够自由的在类级别选择代码,应当确保一个类对应一个文件
第2、3两条类似于Java的包与文件系统的映射规则。
编译器能够识别Ext.define的以下关键字(keywords)并进行优化处理:requires、uses、extend、mixins、statics、alias、singleton、override、alternateClassName、xtype
除了Ext.define最常用的调用方法——第二个参数传递简单对象以外,编译器也能够识别以下几种调用变体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// 指定第二个参数为函数 Ext.define('Foo.bar.Thing', function (Thing) { return { // 这里声明关键字 extend: '...', }; }); // 指定第二个参数为函数调用 Ext.define('Foo.bar.Thing', function () { return { // 这里声明关键字 extend: '...' }; }()); |
从ExtJS 4.1/Touch 2.0开始,Ext.define能够管理重写。在历史版本中,重写用于打补丁以解决BUG或者增强功能。在引入动态加载器后,情况变得复杂,因为 Ext.override 的执行需要时间。在大量使用重写的应用程序中,并非所有重写都被所有页面或者build使用。
现在,编译器能够理解重写,以及它们对依赖、加载顺序的影响。在未来的版本中,编译器在消除dead code(被override替换)时会更加激进。遵循本节的规则,你可以在未来版本获得益处。
标准的重写代码范例如下:
1 2 3 4 5 |
// 尽管这里选定的名字空间是任意的,但是最好遵循下文说明的规则 Ext.define('MyApp.patches.grid.Panel', { override: 'Ext.grid.Panel', ... }); |
通过重写来打补丁是最常见的应用。你应当把所有补丁的命名空间与它针对的目标类的命名空间对应,例如MyApp.patches对应Ext。
除了打补丁,重写还可以用做不完整类(Partial Classes)。当你使用Sencha Architect之类的代码生成器时,一个类通常分类两个部分:机器生成部分、人工编写部分,这种划分有助于机器部分的重新生成。不完整类的用法示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// 自动生成的类 Ext.define( 'Foo.bar.Thing', { // NOTE: This class is generated - DO NOT EDIT... requires: [ 'Foo.bar.custom.Thing' ], method: function () { }, } ); // 重写,作为部分类 Ext.define( 'Foo.bar.custom.Thing', { override: 'Foo.bar.Thing', method: function () { this.callParent(); // 调用自动生成的方法 }, } ); |
重写的最后一种用法是作为切面(Aspect) 。OOP会导致的一个问题就是过度肥胖的基类,这是因为它包含过多的公共逻辑。使用override,可以分离出其中的逻辑,而仅仅在需要使用的时候,才require之:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// 作为切面的重写 Ext.define('Foo.feature.Component', { override: 'Ext.Component' }); // 作为切面的重写,与Foo.feature.Component提供一个产品族 Ext.define('Foo.feature.grid.Panel', { override: 'Ext.grid.Panel', requires: [ 'Foo.feature.Component' // 由于重写不产生继承关系,这里必须显式require ] }); // 需要使用上述切面的客户代码: requires: [ 'Foo.feature.grid.Panel' ] // 或者 requires: [ 'Foo.feature.*' ] |
注意:在重写时,你可以调用 callSuper() 来绕过对被重写方法的调用,而调用其父版本。
除了JavaScript、CSS、HTML以外,Web应用程序往往包含很多代码无关的资源文件(也叫资产,Asset)——图片、视频、数据文件。Cmd将这些资产分类并提供多种管理它们的选项。
资源文件一般都放在名为resources的目录下,这些目录可能来自:
- 对于单Toolkit应用,位于应用根目录,例如MyApp/resources
- 对于Universal应用,位于应用根目录,以及各Toolkit下,例如MyApp/resources、MyApp/classic/resources
- 主题附带的资源文件,位于主题的根目录,例如theme-neptune/resources
- 软件包附带的资源文件,位于软件包的根目录
你可以应用程序描述符app.json中的resources数组,用来定制应用程序资源的来源:
1 2 3 |
"resources" [{ "path": "resources", // 改变此配置以便在其它目录中存放资源 }] |
对于单Toolkit应用,仅该数组的第一个元素作为实际的资源路径,其它元素、第一个元素的output设置都被忽略。
对于Universal应用,该数组可以指定多个元素,并且使用output来指定使用哪个资源池:
1 2 3 4 5 6 |
"resources": [{ "path": "resources", "output": "shared" # 使用shared资源池 }, { "path": "${toolkit.name}/resources" # 使用默认资源池 }], |
这样,可以被多个Toolkit共享的资源,就可以放在(默认)应用根目录的resources目录下,而Toolkit独有的资源则放在与Toolkit同名的目录的resources子目录下。
对于包,支持像Universal应用那样声明多个资源目录、使用哪个资源池。
app.json的顶级output元素, 声明在构建后的应用程序文件被输出到何处:
1 2 3 4 |
"output": { "base": "${workspace.build.dir}/${build.environment}/${app.name}", // 例如 ./workspace/build/production/MyApp }, |
对于Universal应用,可以定义资源池(resource pools):
1 2 3 4 5 6 7 8 9 10 11 |
"output": { "base": "${workspace.build.dir}/${build.environment}/${app.name}", // 资源池定义 "resources": { // 默认资源池,对应buildId下的resources目录 "path": "${build.id}/resources", // 名为shared的共享资源池,对应应用程序的根目录下的resources子目录 "shared": "resources" } }, |
应用、主题、包中的资源文件,都输出到某个资源池中:
- 单Toolkit应用、主题中的资源文件,输出到默认资源池
- Universal应用,默认的,应用根目录下resources输出到共享资源池;toolkit.name/resources输出到默认资源池
- 包的资源输出到资源池的package.name子目录下。这是应用程序构建为包提供的沙盒
多个不同来源的资源文件,可能存在路径名相同的情况,此时会按照一定的规则覆盖:
- 由于主题支持继承,因此子主题中的同名资源,自动覆盖父主题中的资源
- 在应用的resources目录中(如果是Universal应用,则必须是toolkit.name/resources目录中)的文件,可以覆盖同路径的来自主题、包的资源文件
与应用类似,包也具有自己的描述符package.json:
1 2 3 4 5 6 |
// 构建输出 "output": "${package.dir}/build", // 资源路径 "resources": [{ "path": "resources" }] |
为了让非Cmd应用使用包,可以单独构建之: sencha package build 。注意包的构建不区分development/production,其build目录中的东西可以被script、link等元素引用。
为了防止不同包中同名资源被意外的覆盖,应用程序构建(App build)为包中的资源提供沙盒,即,为每个包的资源提供resources的子目录,子目录以包名为名称。
由于应用程序资源、包资源路径处理方式的不同,因此在CSS中引用时,需要注意。Cmd提供了API来获取资源的正确路径:
1 2 3 4 5 6 |
.arrow-button { // 不使用资源池,或者使用默认资源池时: background-image: url(get-resource-path('images/arrow.png')); // 使用资源池时: background: url(get-resource-path('images/foo.png', $pool: 'shared')); } |
在JavaScript中,也有类似的API:
1 2 3 4 |
image.setSrc( // 第二个参数为资源池的名称 Ext.getResourcePath('images/arrow.png', null, 'arrow-button') ); |
Sencha Cmd应用的packages目录包含local、remote两个子目录,分别存放本地、远程包。
你可以在app.json中使用requires声明对包的依赖。sencha app build、sencha app refresh命令会自动把包集成到应用程序中。
执行下面的命令可以生成一个本地包:
1 |
sencha generate package common |
此包的内容放置在packages/local/common目录中。此包的packages.json中会自动添加 local: true 配置,该配置可以放置Cmd下载远程包并覆盖此本地包。
远程包的管理是基于包仓库(package repositories)进行的,Cmd会自动生成一个本地的包仓库,用于缓存、发布包。
执行下面的命令,可以查看可用的远程仓库列表: sencha repository list ,你可以使用 sencha repository add 、 sencha repository remove 命令来添加、删除远程仓库。
sencha-*、ext-*、touch-*、cmd-*这些前缀的包名被内部使用。
可以指定当前包的版本号,以及它和什么样的历史版本兼容:
1 2 3 4 5 6 |
{ // 当前版本 "version": "n.n.n", // 兼容的最低版本 "compatVersion": "2.4.2", } |
在应用描述符的requires里,可以附加版本要求: "requires": [ "ext-easy-button@1.0" ] 。版本要求语法:
示例 | 说明 |
-1.2 | 最高1.2 |
1.0- 1.0+ |
最低1.0 |
1.0-1.2 | 版本在1.0到1.2之间 |
1.0-1.2? | 版本在1.0到1.2之间,或者1.0-1.2的兼容版本 |
Cmd引入工作区的概念,以便管理多个需要共享框架、代码、样式、资源的应用程序。
构建一个大型应用程序的步骤与构建一个单页应用程序的起始步骤一样。一旦应用程序扩展到多个页面,以下常见问题将会出现:
- 如何共享的使用同一框架
- 如果跨页面共享代码
- 如果共享第三方包
为了解决这些问题,Cmd引入了工作区的概念。一个工作区是包含了多个页面(在Sencha的术语里叫应用,Application,因为应用一般都是单页面的,一个应用只进行一次Ext.application调用)、框架(不同版本)、包以及其它共享代码/文件的目录。工作区的根目录通常会纳入版本控制。
如果在工作区内组织各页面的目录并不重要,但是通常把它们的目录作为工作区根目录的直接子目录。
执行下面的命令可以创建一个工作区:
1 2 3 4 5 6 7 8 9 10 11 12 |
sencha generate workspace /path/to/workspace # 生成的目录结构如下: . ├── packages ├── .sencha # Sencha Cmd相关文件 │ ├── .cvsignore │ ├── .gitignore │ └── workspace # 工作区相关文件 │ ├── plugin.xml │ └── sencha.cfg # Sencha Cmd配置 └── workspace.json # 工作区描述符 |
所谓微加载器(Microloader)是Sencha的数据驱动的JavaScript/CSS动态加载器。微加载器由Cmd提供,并作为生成的应用程序的一部分。
ExtJS 6的微加载器实现与ExtJS 5或者Touch不同,它增强了一些功能,这些功能可以在app.json中配置。执行 sencha app upgrade 时微加载器会被一同升级。
Cmd会把app.json转换为manifest供微加载器在运行时使用。你也可以在运行时调用 Ext.manifest 获得此manifest的引用。ExtJS6本身利用此manifest完成一些工作,例如兼容性层(Compatibility Layer)。
有三种方式来指定微加载器使用什么Manifest:
- 嵌入式Manifest,配置:
12345"output": {"manifest": {"embed": true}}可以在构建期间把Manifest嵌入到bootstrap.js文件中
- 命名Manifest,你可以指定从哪个文件中加载Manifest,默认app.json:
12345<script type="text/javascript">var Ext = Ext || {};Ext.manifest = 'foo'; // 从./foo.json加载</script><script id="microloader" data-app="f72c0f68" type="text/javascript" src="bootstrap.js"></script> - 动态指定Manifest,你可以动态的设置Ext.manifest为任意字符串为应用描述符文件的basename
微加载器负责解析app.json并生成manifest,大概步骤如下:
- 读取app.json,其中内容被后续步骤解析
- 获取app.json中与当前构建环境(production/testing/development)匹配的设置,作为基础manifest
- 获取app.json中与当前构建配置匹配(builds.***)的设置,覆盖上面的manifest
- 读取app.json中与当前Toolkit匹配(classic/modern)的设置,覆盖上面的manifest
- 读取app.json中与当前packager匹配的设置,覆盖上面的manifest
- 开始处理依赖包,如果package.json中声明了js、css,则它们按照包的依赖顺序,插入上面manifest['js']或者manifest['css']数组的最前面。package.json中其它内容被置入manifest的packages属性中
Cmd生成的脚手架代码中已经引用的微加载器:
1 |
<script id="microloader" data-app="12345" type="text/javascript" src="bootstrap.js"></script> |
其中data-app为应用的UUID,该ID会在LocalStorage中作为Key使用,避免多个页面的数据混乱在一起。
由Cmd自动生成的app.json叫做应用描述符,该描述符会被微加载器使用,并且在运行时暴露为 Ext.manifest。你可以定制其中的很多配置项,以改变应用的行为。下表列出最常用的配置项:
indexHtmlPath 应用的HTML文档文件路径,此路径相对于app.json文件。默认值是index.html,可以根据需要修改。修改后应该同时指定output配置 | ||||||
framework 使用什么框架,可选值ext、touch,或者工作区自定义的框架名 | ||||||
theme 对于ExtJS应用,此配置用于指定主题名。例如 "theme": "ext-theme-crisp" | ||||||
classpath 指定源码目录。例如:
|
||||||
js 一个数组,指定需要被微加载器自动加载的JavaScript文件,默认脚手架生成如下内容:
上述配置实际上指定了应用程序的入口点。bundle=true意味着此配置条目被构建出的concatenated classes代替。 你可以继续增加配置:
所有JavaScript文件必须按照其执行顺序在此声明 对于应用程序的依赖,应该在requires配置中声明,而不是此配置 |
||||||
css 一个数组,指定微加载器需要按顺序加载的CSS文件。默认内容:
此默认值仅仅是一个导入sass目录构建结果的存根 |
||||||
requires 此数组引用应用所依赖的包的名称,当Cmd处理此数组时,会自动下载、抽取缺失的软件包到工作区中。包可以在自己的package.json中声明依赖,这样的传导依赖也会被下载、抽取。你可以同时指定包的版本 | ||||||
output 控制构建的如何输出、在哪里输出。此配置可以控制构建输出的多个方面。例如,修改indexHtmlPath为../page.jsp后,你需要继续设置output:
你可以指定appCache属性,来控制哪些资产可以被浏览器缓存供离线使用:
|
||||||
LocalStorage缓存 除了浏览器自带的应用程序缓存(通过appCache配置),微加载器还支持通过LocalStorage缓存每一个资产文件。在尝试进行任何远程获取之前,微加载器会首先使用UUID查询LocalStorage,如果文件没有变化则直接使用缓存,这可以让应用程序的加载变得非常块。微加载器还支持增量补丁——即仅仅资产、CSS、JS变化的比特通过网络下载,然后合并到LocalStorage中。 要启用LocalStorage缓存,你需要逐个设置资产的update属性,取值full表示全量更新,delta表示增量更新:
除了在资产上设置update,要让缓存生效,还必须声明全局的cache配置:
在开发阶段,常常把全局缓存设置为false,仅仅在产品构建时才设置为true 你还可以设置: "cache": { "deltas": true } 这样所有update=delta资产的变化会出现在构建结果的detas目录中,如果设置deltas为字符串,则此字符串对应的目录代替deltas目录的功能 一旦微加载器检测到Application Cache、LocalStorage缓存的内容存在更新,会立即发布全局事件,你可以监听此事件并作出反应:
|
||||||
builds 此配置用于声明一个或者多个构建配置(Build Profiles) 如果应用程序存在多个变体,你就可以添加一个新的构建配置。例如:
builds中的每一个属性称为一个构建配置,此属性的值会在执行使用此配置构建时,覆盖app.json中的配置项以生成最终有有效的manifest |
||||||
production / testing / development 对应不同的构建环境(Build Environment)的特定配置信息 |
||||||
classic / modern 对应不同的Toolkit的特定配置信息 |
||||||
locales 指定支持的区域配置: "locales": [ "en", "he" ] 。在同时使用builds时,最终的构建配置的名称不再是classic,而是classic-en、classic-he等 |
||||||
tags 你可以指定多个标记:
这些标记被检测到后,将覆盖自动检测到的值 |
PhoneGap基于Cordova构建,并提供一些辅助工具,例如远程构建服务。
基于Sencha Cmd构建时,仅能构建DEBUG版本的Cordova/PhoneGap应用,要构建能够在应用商店下载的APP你需要使用Android Studio/XCode。
首先,按照一般性步骤创建Cmd应用:
1 2 |
mkdir MyApp && cd MyApp sencha app init --ext=/home/alex/JavaScript/extjs/6.2.0 MyApp --universal |
当开发ExtJS 6 Universal应用时,则上述生成的应用结构的app.json中已经包含了builds块,这种情况下sencha cordova/phonegap子命令无法修改此块,因此你需要手工的修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
"builds": { "classic": {}, "modern": { "toolkit": "modern", "theme": "theme-triton", // 如果使用Cordova,可以添加: "cordova": { "config": { "platforms": "ios", "id": "cc.gmem.myappid" } }, // 如果使用PhoneGap,可以添加: "packager": "phonegap", "phonegap": { "config": { "platform": "ios", "id": "cc.gmem.myappid" } } } }, |
然后进入工程目录,初始化Cordova/PhoneGap支持:
1 2 3 |
sencha phonegap init cc.gmem.myappid MyApp # 或者 sencha cordova init cc.gmem.myappid MyApp |
当开发ExtJS Modern应用程序时,上述命令会自动生成如下builds块:
1 2 3 4 5 6 7 8 9 10 11 |
// native仅仅是一个构建配置名(build-name),你可以将其修改为任意值 "native": { "packager": "cordova", "cordova": { "config": { "platforms": "ios android", // 需要支持的移动平台 "id": "cc.gmem.myappid2", // 用于唯一识别应用程序的标识符 "name": "MyApp2" // 应用程序名称 } } } |
上述命令执行完毕后,在工程目录会出现cordova或者phonegap子目录。 这些子目录的内容与普通Cordova/PhoneGap工程一致。
下面的Cmd子命令可以用于构建出Native软件包:
1 2 3 4 5 6 7 8 |
# 首先构建Sencha应用程序,然后构建Native应用 sencha app build {build-name} # 首先构建,然后尝试在连接上来的设备上运行程序 sencha app run {build-name} # 首先构建,然后尝试在模拟器上运行程序 sencha app emulate {build-name} # 构建Sencha应用程序,然后拷贝到Cordova/PhoneGap指定目录,准备后续的Native构建 sencha app prepare {build-name} |
使用PhoneGap远程构建服务,可以避免很多麻烦的问题,例如下载SDK、工具,购买Mac电脑。你仅仅需要把自己的Web应用上传到PhoneGap服务器,Adobe就可以自动的把Native应用生成给你。在开始之前,你需要到PhoneGap网站申请一个免费账号。如果要构建iOS应用,你需要在PhoneGap网站上填写一系列的credentials信息。
要启用远程构建,需要配置app.json:
1 2 3 4 5 6 7 8 9 10 11 12 |
"builds": { "native": { "packager": "phonegap", "phonegap" : { "config": { "platform": "ios", "remote": true, // 远程构建 "id": "com.mydomain.MyApp" } } } } |
为了向Cmd提供你的PhoneGap网站账号信息,你需要在应用根目录创建一个local.properties文件:
1 2 |
phonegap.username=name@me.com phonegap.password=passwd |
远程构建完毕后,你可以到PhoneGap门户去下载安装包,或者将其发布到应用商店。
新的安装器 此版本的安装程序自带了运行Cmd所需的JRE,并且移除了对Ruby的依赖(由于引入了Fasion)。新的安装器不再需要root权限 如果你使用老的框架版本,例如ExtJS 4/5、Touch2。你还是需要Ruby以及Compass包以便编译Sass代码 |
Fashion Fashion是Sencha新开发的,用于其扩展的Sass语言的编译器。Cmd调用Fashion为ExtJS应用程序、主题构建Sass。当使用sencha app watch时,你可以获得实时更新(Live Update)—— 应用程序的CSS自动与最新代码同步,而不需要刷新浏览器 由于引入了Fashion,Cmd不再依赖于Ruby来生成主题 |
工作区改进 为了支持基于包的代码共享,Cmd6将不同的包分离到子目录中(原先一律放在packages目录):
remote目录可以安全的从CVS中忽略 从Cmd6开始,工作区的根目录存在一个workspace.json文件,此文件应该在CVS中存储 |
Microloader 微加载器是首先由Touch框架引入的,并且在Cmd 5中开始支持ExtJS 5应用程序 Cmd 6对微加载器进行了改进,添加了基于localStorage的缓存支持,并且可以在app.json中禁用缓存 |
框架与工作区管理 当项目规模增大后,在一个工作区中同时开发多个应用程序,并且使用多个ExtJS版本的可能性增加。在6.1之前,一个工作区仅仅可以使用单个版本的ExtJS,则要求所有应用程序必须升级使用的ExtJS版本。 现在,你可以在workspace.json中声明多个ExtJS版本:
frameworks的每一个子项,其值对应工作区中的一个子目录,其键可以供应用程序的app.json引用:
你可以随时的添加新的框架版本到工作区:
添加完新框架后, 框架的代码会自动拷贝到工作区中。你可以使用新添加的框架,来创建一个应用程序:
执行下面的命令可以删除一个框架版本:
可以升级工作区内的应用程序,让其使用特定的框架版本:
在任何时候,你都可以列出当前工作区可用的框架版本:
|
app init子命令 允许初始化当前目录为一个Sencha Cmd应用程序。你可以从空白目录开始,执行下面的命令生成完整的HelloWorld程序结构:
执行构建后,应用程序可以在任意Web服务器上部署: sencha app build |
||
app install子命令 确保不完整的Sencha Cmd应用程序变得可以运行(补充缺失的文件),示例:
|
||
workspace init子命令 确保当前目录是Sencha Cmd工作区或者工作区的一部分 |
||
workspace install子命令 确保不完整的Sencha Cmd工作区变得可以运行(补充缺失的文件),示例:
|
||
workspace cleanup子命令 从workspace.json中移除已经不存在于工作区的应用程序条目 |
ES6支持 Cmd 6.5的主要变化就是支持ES6,即使是ExtJS 4.1.1+、Touch 2.1.x+也可以使用ES6来编写代码了 Cmd能够把ES6代码编译(Transpile)为老版本的JavaScript,这样老的浏览器可以被很好的支持。由于Transpile处理本身的特性,它必须在产品构建时执行,因此,你必须使用支持ES6的现代浏览器才能使用开发者模式(Developer Mode) 产品构建支持的浏览器包括IE8+和其它主流浏览器 如果你对那些老浏览器没兴趣,可以禁止Transpile:
|
Leave a Reply