使用typescript和gulp快速开始Angular 2开发
Angular2出来了一段时间,通过更简单和更简洁的概念,如基于组件的架构,新的依赖注入或内置模块化,新版本的框架要学习得简单得多。在这个分步教程中,您将了解如何使用TypeScript和Gulp开始使用Angular2。源代码在Github上可用。
本文是翻译codeleak.pl上的一篇文章。(英语很挫,错误在所难免)
原文地址:http://blog.codeleak.pl/2016/...
通用说明
更新日志
15/09/2016升级到2.0.0重新angular2文章,添加新的代码库中的代码来反映。添加快速入门指南。
06/09/2016 - 更新至 Angular2 to 2.0.0-rc.6
05/06/2016 - typings updated to 1.0.4. Section related to that part changed too.
05/05/2016 - Upgraded Angular2 to 2.0.0-rc.1
22/04/2016 - Upgraded Angular2 to 2.0.0-beta.15
26/03/2016 - Upgraded Angular2 to 2.0.0-beta.12
21/03/2016 - Upgraded Angular2 to 2.0.0-beta.11 (the post itself as well as the source code)
快速入门
如果你不感兴趣的一步一步的教程,只需按照以下步骤迅速启动。
1、环境要求
Nodejs 必须安装在您的系统和下面的全局节点包必须安装:
gulp
npm i -g gulp
gulp-cli
npm i -g gulp-cli
typings
npm i -g [email protected]
typescript
npm i -g [email protected]
ts-node
npm i -g [email protected]
2、克隆仓库
git clone https://github.com/kolorobot/angular2-typescript-gulp.git
3、定位至angular2-typescript-gulp目录
cd angular2-typescript-gulp
4、安装依赖
npm install
5、构建工程
npm run clean & npm run build
// 构建后会产生Build目录
6、启动应用
npm start
介绍
至今,Angular 1.X可能仍然是最流行的前端框架,毫无疑问Angular 1.X是一个伟大的框架。然而,这是非常难以掌握。复杂的API和许多概念推出以来,使人了解框架和有效地使用它确实很难。
angular2,另一方面,是一个新的开放。新版本的框架要简单得多,学习更简单和更简洁的概念,如基于组件的体系结构,新的依赖注入或内置模块化。
如果你想找一个比 angular.io 更好地 练习和开始学习Angular 2的地方,如果正在寻找用gulp构建来使用Angular 2的方式,那么这篇文档正适合你!
Note: 文章所使用的代码资源在github
https://github.com/kolorobot/...
工程预览
初始化的工程是基于Angular2 Quickstart:
对https://angular.io/docs/ts/la... 做了一些改变。
最重要的变化是将源文件与生成文件分离:SRC目录包含所有源文件并生成包含所有已编译和处理的文件。
服务器使用build目录作为基本目录来资源文件。
angular2-typescript-gulp
| .gitignore
| bs-config.json -> BrowserSync configuration
| gulpfile.ts -> Gulp in TypeScript
| package.json -> npm configuration
| tsconfig.json -> TypeScript configuration
| typings.json -> TypeScript typings definitions
| tslint.json -> tslint configuration
|
\---src
│ │ index.html -> Starting point for the application
│ │ systemjs.config.js -> SystemJS configuration
│ │
│ \---app -> Application modules
│ │ app.component.ts -> Main application component
│ │ app.html -> Main application template
│ │ app.module.ts -> Application module definition
│ │ app.routing.ts -> Routing configuration
│ │ main.ts -> Application bootstrap
│ │
│ \---about
│ │ └───components
│ │ about.components.ts
│ │ about.html
│ │
│ \---todo
│ ├───components
│ │ task-list.component.ts
│ │ task-list.css
│ │ task-list.html
│ │ task.component.ts
│ │ task.html
│ │
│ \---models
│ │ task.ts
│ │
│ \---services
│ task-service.ts
NPM全局依赖
假设Node和NPM已经安装,你可以通过调用下面的命令安装全局依赖:
npm i -g
为了运行工程必须安装的全局依赖:
gulp and gulp-cli
npm i -g gulp
npm i -g gulp-cli
typings
npm i -g [email protected]
typescript
npm i -g [email protected]
ts-node
npm i -g [email protected]
// Note: To check global dependencies use the following command:
npm -g –depth 0 ls
创建工程目录和文件
创建如上文所述的目录和文件结构
构建配置
1、typescript配置 - tsconfig.ts
编译文件会被保存至build/app;请注意gulpfile.ts要排除编译。
{
"compilerOptions": {
"outDir": "build/app",
"target": "es5",
"module": "system",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
},
"exclude": [
"gulpfile.ts",
"node_modules"
]
}
说明:如果你想导入你的工程到IDE(如IntelliJ),让这个IDE也使用这个文件。
2、Typings - typings.json
To get started we need some definitions to be installed. Run the following commands:
为了能够正常运行开始,我们需要的一些定义被安装。运行一下命令:
typings install –global –save dt~core-js
typings install –global –save dt~node
这些会被添加至typings.json
{
"globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160725163759",
"node": "registry:dt/node#6.0.0+20160909174046",
}
}
Typings will be download to typings directory and they will be downloaded on npm install.
Typings 会被下载到typings目录并且他们会通过npm instal的方式被下载下来。
3、npm包和脚本配置 - package.json
关于脚本命令的一些命令:
clean - 清除build目录
compile - TypeScript compilation (with sourcemaps)
build - 打包构建工程
start - 运行使用来自bs-config.json配置的lite服务器,它还使用监视任务同步源目录的任何更改
{
"name": "angular2-typescript-gulp",
"version": "1.0.0",
"description": "Angular2 with TypeScript and Gulp QuickStart",
"scripts": {
"clean": "gulp clean",
"compile": "gulp compile",
"build": "gulp build",
"start": "concurrent --kill-others \"gulp watch\" \"lite-server\"",
"postinstall": "typings install"
},
"repository": {
"type": "git",
"url": "https://github.com/kolorobot/angular2-typescript-gulp.git"
},
"author": "Rafał Borowiec",
"license": "MIT",
"bugs": {
"url": "https://github.com/kolorobot/angular2-typescript-gulp/issues"
},
"dependencies": {
"@angular/common": "2.0.0",
"@angular/compiler": "2.0.0",
"@angular/core": "2.0.0",
"@angular/forms": "2.0.0",
"@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0",
"@angular/router": "3.0.0",
"@angular/upgrade": "2.0.0",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.27",
"zone.js": "^0.6.23"
},
"devDependencies": {
"concurrently": "^2.2.0",
"del": "^2.2.0",
"gulp": "^3.9.1",
"gulp-sourcemaps": "^1.6.0",
"gulp-tslint": "^6.1.1 ",
"gulp-typescript": "^2.13.6",
"lite-server": "^2.2.2",
"tslint": "^3.5.0",
"typescript": "^2.0.2",
"typings": "^1.3.3",
"ts-node": "^1.3.0"
}
}
4、BrowserSync configuration - lite-server
默认情况下,内容从当前目录提供,因此需要更改;而且,由于Lite Server使用BrowserSync,足以提供配置服务器的bs-config.json来从构建目录提供内容。
{
"port": 8000,
"files": [
"build/**/*.{html,htm,css,js}"
],
"server": {
"baseDir": "build"
}
}
5、tslint(typescript语法检测配置) - tslint.json
TSLint检查TypeScript代码是否可读性,可维护性和功能错误,而Gulp可以与gulp-tslint插件一起使用。
tslint.json用于配置哪些规则可以运行。只需将文件添加到项目的根目录。您应该根据需要调整规则。您可以在这里找到有关规则的更多信息:http://palantir.github.io/tsl...
{
"rules": {
"class-name": true,
"curly": true,
"eofline": false,
"forin": true,
"indent": [
true,
4
],
"label-position": true,
"label-undefined": true,
"max-line-length": [
true,
140
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-key": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-eval": true,
"no-string-literal": false,
"no-trailing-whitespace": true,
"no-unused-variable": false,
"no-unreachable": true,
"no-use-before-declare": true,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"radix": true,
"semicolon": true,
"triple-equals": [
true,
"allow-null-check"
],
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator"
]
}
}
6、Gul构建配置- gulpfile.ts
要开始,我们需要一个编译TypeScript文件,将资产和依赖关系复制到构建目录的任务。为了实现这些任务需要几个任务。
注意:Gulp文件是以TypeScript而不是JavaScript创建的。它需要ts-node执行,如本教程开头所述。
"use strict";
const gulp = require("gulp");
const del = require("del");
const tsc = require("gulp-typescript");
const sourcemaps = require('gulp-sourcemaps');
const tsProject = tsc.createProject("tsconfig.json");
const tslint = require('gulp-tslint');
/**
* Remove build directory.
*/
gulp.task('clean', (cb) => {
return del(["build"], cb);
});
/**
* Lint all custom TypeScript files.
*/
gulp.task('tslint', () => {
return gulp.src("src/**/*.ts")
.pipe(tslint({
formatter: 'prose'
}))
.pipe(tslint.report());
});
/**
* Compile TypeScript sources and create sourcemaps in build directory.
*/
gulp.task("compile", ["tslint"], () => {
let tsResult = gulp.src("src/**/*.ts")
.pipe(sourcemaps.init())
.pipe(tsc(tsProject));
return tsResult.js
.pipe(sourcemaps.write(".", {sourceRoot: '/src'}))
.pipe(gulp.dest("build"));
});
/**
* Copy all resources that are not TypeScript files into build directory.
*/
gulp.task("resources", () => {
return gulp.src(["src/**/*", "!**/*.ts"])
.pipe(gulp.dest("build"));
});
/**
* Copy all required libraries into build directory.
*/
gulp.task("libs", () => {
return gulp.src([
'core-js/client/shim.min.js',
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'reflect-metadata/Reflect.js',
'rxjs/**',
'zone.js/dist/**',
'@angular/**'
], {cwd: "node_modules/**"}) /* Glob required here. */
.pipe(gulp.dest("build/lib"));
});
/**
* Watch for changes in TypeScript, HTML and CSS files.
*/
gulp.task('watch', function () {
gulp.watch(["src/**/*.ts"], ['compile']).on('change', function (e) {
console.log('TypeScript file ' + e.path + ' has been changed. Compiling.');
});
gulp.watch(["src/**/*.html", "src/**/*.css"], ['resources']).on('change', function (e) {
console.log('Resource file ' + e.path + ' has been changed. Updating.');
});
});
/**
* Build the project.
*/
gulp.task("build", ['compile', 'resources', 'libs'], () => {
console.log("Building the project ...");
});
7、安装依赖关系并检查构建
现在是安装所有依赖关系的时候了。运行:
npm install
应该在安装期间创建node_modules和typing目录。
构建工程
npm run clean & npm run build
build目录应在构建期间创建
注意:如果在编译期间看到以下内容,请确保至少有ts-node 1.3.0:
[00:49:42] Failed to load external module ts-node/register
[00:49:42] Failed to load external module typescript-node/register
[00:49:42] Failed to load external module typescript-register
[00:49:42] Failed to load external module typescript-require
工程配置
1. Index - src/index.html
库是在构建任务期间创建的lib目录的引用
Angular 2 TypeScript Gulp QuickStart
Loading...
2. SystemJS 配置 - src/systemjs.config.js
function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'lib/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);
3、应用组件
1. 主入口组件 - src/app/app.component.ts
import {Component, OnInit} from "@angular/core";
@Component({
selector: "app",
templateUrl: "./app/app.html"
})
export class AppComponent implements OnInit {
ngOnInit() {
console.log("Application component initialized ...");
}
}
他的模板 (src/app/app.html):
Angular 2 is running ...
2. About 模块
关于模块由两个基本构件 - 组件及其模板组成。
src/app/about/components/about.component.ts
import {Component} from "@angular/core";
import {OnInit} from "@angular/core";
@Component({
templateUrl: './app/about/components/about.html'
})
export class AboutComponent implements OnInit {
ngOnInit() {
}
}
src/app/about/components/about.html:
About
这是about
3. Todo 模块
Todo模块有点复杂 - 它包含组件,模型和服务。
src/app/todo/components/task.component.ts
import {Component} from "@angular/core";
import {Input} from "@angular/core";
import {Task} from "../models/task";
import {Output} from "@angular/core";
import {EventEmitter} from "@angular/core";
@Component({
selector: 'task',
templateUrl: './app/todo/components/task.html'
})
export class TaskComponent {
@Input() task:Task;
@Output() statusChanged:any = new EventEmitter();
toggleDone() {
this.task.toggleDone();
this.statusChanged.emit(null);
}
}
src/app/todo/components/task.html
src/app/todo/components/task-list.component.ts
import {Component} from "@angular/core";
import {Task} from "../models/task";
import {OnInit} from "@angular/core";
import {TaskService} from "../services/task-service";
import {TaskComponent} from "./task.component";
@Component({
selector: 'task-list',
templateUrl: './app/todo/components/task-list.html',
styleUrls: ['./app/todo/components/task-list.css'],
providers: [TaskService]
})
export class TaskListComponent implements OnInit {
todoCount:number;
selectedTask:Task;
tasks:Array;
constructor(private _taskService:TaskService) {
this.tasks = _taskService.getTasks();
this.calculateTodoCount();
}
ngOnInit() {
console.log("Todo component initialized with " + this.tasks.length + " tasks.");
}
calculateTodoCount() {
this.todoCount = this.tasks.filter(t => !t.done).length;
}
select(task:Task) {
this.selectedTask = task;
}
}
src/app/todo/components/task-list.css
li.selected {
background-color: #8a8a8a;
}
src/app/todo/components/task-list.html
Todo tasks ({{todoCount}})
src/app/todo/models/task.ts
export class Task {
constructor(public name:string, public done:boolean) {
}
toggleDone() {
this.done = !this.done;
}
}
src/app/todo/services/task-service.ts
import {Injectable} from "@angular/core";
import {Task} from "../models/task";
@Injectable()
export class TaskService {
private tasks:Array = [
new Task("Task 1", false),
new Task("Task 2", false),
new Task("Task 3", false),
new Task("Task 4", false),
new Task("Task 5", false)
];
getTasks():Array {
return this.tasks;
}
addTask(name:string) {
this.tasks.push(new Task(name, false));
}
}
4. Angular2 路由 - src/app/app.routing.ts
import {Routes, RouterModule} from '@angular/router';
import {TaskListComponent} from "./todo/components/task-list.component";
import {AboutComponent} from "./about/components/about.component";
import {ModuleWithProviders} from "@angular/core";
const appRoutes: Routes = [
{path: 'tasks', component: TaskListComponent, data: {title: 'TaskList'}},
{path: 'about', component: AboutComponent, data: {title: 'About'}}
];
export const appRoutingProviders: any[] = [];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes, { useHash: true });
5. 模块定义 - src/app/app.module.ts
Angular2模块有助于将应用程序整合到一个功能性的集合中。
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {AppComponent} from "./app.component";
import {TaskListComponent} from "./todo/components/task-list.component";
import {AboutComponent} from "./about/components/about.components";
import {TaskComponent} from "./todo/components/task.component";
import {routing, appRoutingProviders} from './app.routing';
import {FormsModule} from "@angular/forms";
@NgModule({
imports: [
BrowserModule,
FormsModule,
routing
],
declarations: [
AppComponent,
TaskComponent,
TaskListComponent,
AboutComponent
],
providers: [
appRoutingProviders
],
bootstrap: [AppComponent]
})
export class AppModule {
}
6. Application bootstrap - src/app/main.ts
//
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
构建运行
npm run clean & npm run build
npm start
您应该看到应用程序在浏览器中运行
关于IntelliJ的注意事项
IntelliJ处理建议的设置没有问题。如果IntelliJ中使用TypeScript编译器,则应使用该项目的tsconfig.json。在这种情况下,ts文件的更改将立即反映在构建目录中。
代码资源
https://github.com/kolorobot/...
下一步做什么?
需要更多的实际使用这个项目。因此,很快就会添加更多功能。如果您有任何建议,评论或添加Github问题。
angular2-seed
如果您需要更成熟的启动器,请查看angular2-seed项目
https://github.com/mgechev/angular2-seed
angular2-seed以更先进的方式使用gulp,并且已经支持生产和开发构建,单元和集成测试等等。