[译文] APP以原生的方式在Web和移动端工作
[译文] APP以原生的方式在Web和移动端工作
原文 Apps That Work Natively on the Web and Mobile
Shared Project今天,我们非常高兴地宣布了一种将Angular与NativeScript结合起来构建web和移动端应用的令人激动的新方式。
首先,介绍一些背景:从Angular一开始,你就可以使用NativeScript结合Angular来创建移动应用。
NativeScript是一个使用JavaScript创建真实原生移动端应用的开源框架。它让你可以使用已有的Angular技术构建项目,最终得到的结果具有iOS和Android原生的UI和性能表现。
但是,如果你需要同时构建web和原生移动应用,你还是得创建、开发和维护两个分离的项目。虽然这样也能完成任务,但显然我们可以比这做得更好。
代码共享的梦想
这一挑战引出一个梦想——代码共享项目。这是一个允许你将Web和移动应用的代码保存在同一处的项目。它也可以让我们在web、iOS和Android之间共享业务逻辑,同时保证在需要时包含平台特殊代码的灵活性。
随着 Schematics 和 ng add 的出现,我们有了一整套全新的可能性。
为了实现代码共享项目,Angular和NativeScript团队联手创建了 nativescript-schematics,一个能够从单一项目构建web和移动应用的程式示意图。
请注意要使用@nativescript/schematics,必须保证@angular/cli是6.1.0以上版本。
我们来看看哪些场景可以使用 Angular CLI 和 {N} Schematics:
- 使用代码共享结构创建的新项目
- 将已有web项目转换成代码共享结构
然后:
- 将已存在组件和模块转化成代码共享格式
- 生成新的代码共享格式的组件和模块
共享或不共享
这套工具的目的是尽可能多的共享代码,分离平台专有代码到单独的文件中。
这通常是说我们可以为下列功能共享代码:
- 实现导航的路由
- 为公共业务逻辑提供的服务
- 管理组件公共行为的组件类定义
同时我们分离下列文件:
- UI表现层(样式表和html文件))——因为在web和NativeScript构建的原生APP中需要使用不同的用户界面。
- angular模块——这样我们可以导入平台专有的模块,避免web和移动端冲突。(例如,Angular Material Design——仅供Web)。
下面这张示意图让我们能够从更高层面一览构建逻辑。
Project开始
你可以从创建一个代码共享结构的新项目开始。只需要执行 ng new
,并制定collection变量为 @nativescript/schematics。
如下:
ng new --collection=@nativescript/schematics --name=my-app --shared
注意,你需要先安装 @nativescript/schematics:
npm install --global @nativescript/schematics
或者我们可以扩展现有的web项目,使其能够使用NativeScript构建移动应用程序
ng add @nativescript/schematics
这条命令添加了以下 NativeScript专有文件:
- npm模块
- AppModule定义
- AppComponent定义
- tsconfig
构建过程
为了完成工作,我们还需要一个能够使用共享文件和平台专有文件的构建过程,来提供web或移动应用。
Shared Project构建Web
构建Web应用跟往常的一样,使用Angular CLI来完成工作。
当执行 ng serve
或 ng build
时,Angular CLI会忽略NativeScript专有文件——因为web文件不会引用任何.tns标识的文件。
ng serve
-> 以代码共享目录启动web应用的服务
"exclude": [
"**/*.ns.ts",
"**/*.tns.ts",
"**/*.android.ts",
"**/*.ios.ts"
]
构建移动应用
用 NativeScript 构建iOS或Android应用,我们需要使用NativeScript CLI 和 NativeScript Webpack plugin。
调用:
-
tns run ios --bundle
——构建iOS应用 -
tns run android --bundle
——构建Android应用
在构建时,Webpack 会处理有提供了.tns标识的文件,然后隐藏web版的文件(实际上,像home.component.tns.html这样的文件,会被当作home.component.html来处理)。同时NativeScript CLI 的职责是构建原生移动应用。
代码分离
在共享代码之前,我们需要知道怎么分离Web和移动端代码。这非常重要,这样我们便可以简单无冲突地创建平台专有代码。
我们可以使用一个简单的 命名空间 来达到这个目的。通过在文件扩展名之前添加 .tns,用来表示这个文件是NativeScript专有的,同时没有使用 .tns 扩展的文件就被认为是Web专有的。如果我们只有一个文件没有使用 .tns 扩展,它就被当做一个共享文件。
组件——代码共享的格式
最常见的场景是一个组件的代码,我们经常有这些文件:
- name.component.ts——组件类定义共享文件
- name.component.html——Web专有模板
- name.component.tns.html——移动专有模板
- name.component.css——Web专有样式表
- name.component.tns.css——移动专有模板
同样值得注意的是,在@Component装饰器中,templateUrl和styleUrls指向的文件不包括.tns扩展,因为这是由构建过程处理的。
@Component({
selector: 'app-name',
templateUrl: './name.component.html',
styleUrls: ['./name.component.css'],
})
Angular模块的代码分离方式:HttpClient
配合NgModules来分离代码是非常有用的,因为你经常需要导入Web或NativeScript专有的模块。
一个非常好的例子是当你需要调用一个HTTP请求时,在Web应用中,你需要导入 HttpClientModule 模块,它提供了 HttpClient 的实现。
但是,浏览器里HTTP请求的执行方式与在iOS和Android里不同,在NativeScript中,你需要使用 NativeScriptHttpClientModule 模块,它提供了与 HttpClient 等价的执行。
现在,你可以使用代码分离技术创建两个版本的@NgModule——每个版本使用不同版本的 HttpClientModule 模块——然后在依赖注入的帮助下向服务提供正确的 HttpClient 实现。
Code Sparation- my.module.ts——导入 HttpClientModule 的Web版模块文件
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
HttpClientModule,
…
]
…
})
- my.module.tns.ts——导入 NativeScriptHttpClientModule 的移动端版模块文件
import { NativeScriptHttpClientModule } from 'nativescript-angular/http-client';
@NgModule({
imports: [
NativeScriptHttpClientModule,
…
]
…
})
export class MyModule { }
- my.service.ts——注入HttpClient 的共享服务文件
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class MyService {
constructor(private http: HttpClient) { }
…
}
模块的代码分离是一种简单而优雅的解决方案。它使你能够将具有不同实现(针对Web和移动端应用)的功能整合到一起,从而最大化共享代码。
示例项目
如果你有兴趣看看实现了如下功能的共享项目:
- 共享导航
- 懒加载
- 授权保护
- 基于NgModule的Angular Material组件和NativeScript UI插件的代码分离
- 一个独立的用户服务
- 共享组件和分离的UI组件
- 可爱宠物领养
可以访问我们的示例项目pet-bros-lite,它展示了所有这些代码共享概念的实际应用!
总结
如你所见,通过一个项目同时构建Web和移动应用相当简单。你可以从一个新项目开始(使用ng new),或者向已有项目中添加移动端代码(使用ng add)。还有一个简单的命名空间约定来支持代码分离,它使你可以覆盖到多数应用场景。
尝试一下代码分离,它是如此的简单。你与在Angular中进行代码分离只有简单的 ng add
或 ng new
一步。