Rewrote Getting Started for an earlier, positive Ng2 experience

This commit is contained in:
Ward Bell 2015-10-03 12:04:11 -07:00 committed by Naomi Black
parent 6002389ff5
commit 849a6855e5
5 changed files with 345 additions and 204 deletions

View File

@ -0,0 +1,8 @@
// #docregion
import {Component, View, bootstrap} from 'angular2/angular2';
@Component({selector: 'my-app'})
@View({template: '<h1>My First Angular 2 App</h1>'})
class AppComponent { }
bootstrap(AppComponent);

View File

@ -1,19 +1,8 @@
// #docregion // #docregion
// #docregion import
import {Component, View, bootstrap} from 'angular2/angular2'; import {Component, View, bootstrap} from 'angular2/angular2';
// #enddocregion import
// #docregion class-w-annotations
@Component({
selector: 'my-app'
})
@View({
template: '<h1>My First Angular 2 App</h1>'
})
// #docregion class
class AppComponent { }
// #enddocregion class
// #enddocregion class-w-annotations
// #docregion bootstrap @Component({selector: 'my-app'})
@View({template: '<h1>My First Angular 2 App</h1>'})
class AppComponent { }
bootstrap(AppComponent); bootstrap(AppComponent);
// #enddocregion bootstrap

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<title>Getting Started</title>
<script src="https://code.angularjs.org/tools/traceur-runtime.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-alpha.37/angular2.dev.js"></script>
<script>
System.config({
transpiler: 'typescript',
typescriptOptions: { emitDecoratorMetadata: true }
});
System.import('./app.ts');
</script>
</head>
<body>
<my-app>loading...</my-app>
</body>
</html>

View File

@ -1,20 +1,25 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- #docregion --> <!-- #docregion -->
<html> <html>
<head> <head>
<script src="../node_modules/traceur/bin/traceur-runtime.js"></script> <title>Getting Started</title>
<!-- #docregion libraries -->
<script src="../node_modules/systemjs/dist/system.src.js"></script> <script src="../node_modules/systemjs/dist/system.src.js"></script>
<script src="../node_modules/angular2/bundles/angular2.dev.js"></script> <script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
</head> <!-- #enddocregion libraries -->
<!-- #docregion systemjs -->
<body>
<my-app>Loading...</my-app>
<script> <script>
System.config({ System.config({
packages: {'app': {defaultExtension: 'js'}} packages: {'app': {defaultExtension: 'js'}}
}); });
System.import('app/app'); System.import('app/app');
</script> </script>
<!-- #enddocregion systemjs -->
</head>
<body>
<my-app>Loading...</my-app>
</body> </body>
</html> </html>

View File

@ -1,7 +1,7 @@
include ../../../../_includes/_util-fns include ../../../../_includes/_util-fns
:markdown :markdown
Let's start from zero and build a simple Angular 2 application in TypeScript. Let's start from zero and build a super simple Angular 2 application in TypeScript.
.callout.is-helpful .callout.is-helpful
header Don't want TypeScript? header Don't want TypeScript?
@ -9,43 +9,247 @@ include ../../../../_includes/_util-fns
Although we're getting started in TypeScript, you can also write Angular 2 apps Although we're getting started in TypeScript, you can also write Angular 2 apps
in JavaScript and Dart by selecting either of those languages from the combo-box in the banner. in JavaScript and Dart by selecting either of those languages from the combo-box in the banner.
:markdown .l-main-section
We'll do it in short steps
1. Install the prerequisites for Angular TypeScript development :markdown
1. Create the application project structure # The shortest, quickest ...
1. Install the npm packages our app needs
1. Prepare for TypeScript compilation Let's put something on the screen in Angular 2 as quickly as we can.
1. Create an **`index.html`**
1. Write the root component for our application in **`app.ts`** .l-sub-section
1. Bootstrap the app :markdown
1. Compile the TypeScript to JavaScript While we are about to describe steps to take on your development machine,
1. Run it you could take these same steps in an interactive, online coding environment
such as [plunker](http://plnkr.co/ "Plunker"). You won't have to
install a static server to run the app there.
If you like what you see - and we think you will - you can repeat this
exercise on your own machine later.
:markdown
**Create a new folder** to hold our application project, perhaps like this:
```
mkdir angular2-getting-started
cd angular2-getting-started
```
## Our first Angular component
**Add a new file** called **`app.ts`** and paste the following lines:
+makeExample('gettingstarted/ts/src/app/app.ts', null, 'app.ts')
:markdown
We've just defined an Angular 2 **component**,
one of the most important beasts in the Angular zoo.
Components are our primary means of creating application views
and supporting them with application logic.
Ours is an empty, do-nothing class class named `AppComponent`.
It would expand with properties and application
logic when we're ready to build a substantive application.
Above the class we see the `@Component` decoration.
.l-sub-section
:markdown
The `@` symbol before the method name identifies `Component` as a decoration.
A "decoration" is a TypeScript language feature
for creating metadata about the class. Angular finds this metadata
in the transpiled JavaScript and responds appropriately.
:markdown
`@Component` tells Angular that this class *is an Angular component*.
The configuration object passed to the `@Component` method
specifies a CSS selector for an HTML element named `my-app`.
When Angular sees `my-app`, it will know to
create and display an instance of our component.
`@View` is another decoration that describes how our
component renders on the screen. This one is dead simple,
a single line of HTML announcing "My First Angular App".
The `bootstrap` line tells Angular to start the application with this
component at the application root.
We'd be correct to guess that someday our application will
consist of more components arising in tree-like fashion from this root.
In the top line we imported the `Component`, `View`, and `bootstrap` methods
from the Angular 2 library. That's the way we do things now.
We no longer expect to find our code or any library code in a global namespace.
We `import` exactly what we need, as we need it, from named file and library resources.
## Add `index.html`
**Create** an `index.html` file.
**Paste** the following lines into it ... and we'll discuss them:
+makeExample('gettingstarted/ts/src/index.1.html', null, 'index.html')
:markdown
We see three noteworthy sections of HTML:
1. We load JavaScript libraries from the web.
Let's take them on faith without further discussion.<br/><br/>
2. We configure something called `System` and ask it to import the
application file with our `AppComponent` that we just wrote.
`System` is the module loader (from the `system.js` library),
a tool that can `import` code;
remember the `import` statement in our `AppComponent`?
We're also asking `system.js` to "transpile" (AKA "compile") our
TypeScript source code into JavaScript ... right here in the browser.<br/><br/>
3. We note the `<my-app>` tag in the `<body>`.
That's the custom HTML element we identified in the `@Component` decoration
adorning our `AppComponent` class.
## Run it!
We need a static file server to serve our application to the browser.
.l-sub-section
:markdown
Don't have a static file server handy? Let's install one of our favorites
called [live-server](https://www.npmjs.com/package/live-server "Live-server").
We'll use the **npm package manager** to install it. Don't have npm?
[Go get it](https://docs.npmjs.com/getting-started/installing-node "Installing Node.js and updating npm")
because we're going to use it now and repeatedly throughout the guide.
Once you have `npm` installed, open a terminal window and enter
pre.prettyprint.lang-bash
code npm install -g live-server
:markdown
Open a terminal window and enter
pre.prettyprint.lang-bash
code live-server
:markdown
In a few moments, a browser tab should open and display
figure.image-display
img(src='/resources/images/devguide/getting-started/my-first-app.png' alt="Output of getting started app")
:markdown
Congratulations! We are in business.
.l-main-section .l-main-section
:markdown :markdown
## Prerequisites ## What's wrong with this?
We'll need a base of tools for our application development throughout this guide: We were up and running in a hurry and we could explore Angular
in this manner for quite some time.
For a number of reasons this isn't a good approach for building an application.
* Transpiling TypeScript in the browser becomes tediously slow when our
app grows beyond a few files. We certainly won't do that in production.
We should learn to compile locally and
push the generated JavaScript to the server. We'll need some tools for that.
* We are writing TypeScript because we want strong-typing and some information
about the APIs we're using. If we wrote `AppComponent` in a TypeScript-aware editor,
we saw lots of red squiggly lines complaining about our code and
we received no guidance about what `Component`, `View`, and `bootstrap` can do.
We'll want to load TypeScript definition files to improve our coding experience.
* Downloading JavaScript libraries from the web is OK for demos but
it slows our development. Every time our app reloads, it must refetch these libraries.
Don't count on browser caching.
Our debugging and live-reload techniques will bust the browser cache.
Loading libraries from the web also prevents us from developing our
application offline or where connectivity is poor.
Let's learn to download the libraries to our machine and serve
them locally.
* We want our development cycle to be as fast and friction-free as possible.
When we change our code, we want to see the results in the browser immediately.
We have tools and procedures for that.
.l-main-section
:markdown
# Upping our game
Let's take a few more steps to put our development on a better foundation. We will
1. Revise the application project structure for future growth
1. Install a few tools and packages
1. Prepare for local TypeScript compilation
1. Revise the **`index.html`** to use local library resources
1. Compile the TypeScript locally and watch for changes
Shut down the `live-server` running in the terminal window (Ctrl-C) and proceed as follows.
.l-main-section
:markdown
## Revise the application project structure
At the moment we're dumping everything into the "angular2-getting-started" **root folder**.
Not bad when there are only two files. Not good as our application evolves.
Let's give our project a little structure.
We'll add a sub-folder - `src` - to hold project source code and a sub-sub-folder - `src/app` -
to hold the application source code.
In OS/X and Linux:
pre.prettyprint.lang-bash
code mkdir src/app
:markdown
In Windows:
pre.prettyprint.lang-bash
code mkdir src\app
:markdown
**Move `index.html`** into the **`src`** folder.
**Move `app.ts`** into the **`src/app`** folder.
Our project folders should look like this.
```
angular2-getting-started
└── src
├── app
│ └── app.ts
└── index.html
```
.l-main-section
:markdown
## Install tools and application packages
We'll need a set of tools for our application development throughout this guide.
We've already installed **`live-server`**. Let's install two more:
- the **TypeScript compiler** - the **TypeScript compiler**
- the [**tsd package manager**](https://www.npmjs.com/package/tsd "TSD Package Manager") so we can access - the [**tsd package manager**](https://www.npmjs.com/package/tsd "TSD Package Manager") so we can access
[TypeScript type definition files](http://definitelytyped.org/ "Definitely Typed") ("`.d.ts`" files). [TypeScript type definition files](http://definitelytyped.org/ "Definitely Typed").
- **live-server**, a *static server* that runs our app in the browser and reloads the browser when any of the files change. **Open** a terminal window and issue the following `npm` command to install both packages globally:
**Open** a terminal (or Windows/Linux command line) and issue the following `npm` command to install them all:
pre.prettyprint.lang-bash pre.prettyprint.lang-bash
code npm install -g typescript tsd live-server code npm install -g typescript tsd
.l-sub-section .l-sub-section
:markdown :markdown
We depend upon [**node** and **npm**](https://docs.npmjs.com/getting-started/installing-node "Installing Node.js and updating npm") Now might be a good time to ensure that we're installing Angular-compatible versions of our tools.
to install packages such as these global tools.
We must be sure that we're installing Angular-compatible versions of these packages.
Issue the following commands in that same terminal window to confirm that we have the appropriate versions: Issue the following commands in that same terminal window to confirm that we have the appropriate versions:
table table
tr tr
@ -72,63 +276,65 @@ include ../../../../_includes/_util-fns
code live-server -v code live-server -v
td 0.8+ td 0.8+
.l-main-section
:markdown :markdown
## Create the application project structure ### Install local packages
Create a new folder to hold our application project, perhaps like this: We'll replace the web-based scripts in our `index.html` with
``` scripts resident on our local machine. We get those scripts by installing two `npm` packages into our project.
mkdir angular2-getting-started
cd angular2-getting-started
```
:markdown
We'll refer to this as our application's **root folder**.
Now add a sub-folder - `src` - to hold project source code and a sub-sub-folder - `src/app` -
to hold to hold the application source code.
In OS/X and Linux:
pre.prettyprint.lang-bash
code mkdir src/app
:markdown
In Windows:
pre.prettyprint.lang-bash
code mkdir src\app
:markdown
Our project folders should look like this.
```
angular2-getting-started
├── src
└──── app
```
.l-main-section
:markdown
## Install npm packages
We need to install two JavaScript library packages:
>***angular.js***, the Angular 2 library. >***angular.js***, the Angular 2 library.
>***system.js***, an open-source library that provides module loading. >***system.js***, an open-source library that provides module loading.
We'll install these package with `npm` and create an npm **`package.json`** configuration file In a terminal window at our application's **root folder** type:
to maintain them as our application evolves.
In a terminal window, go to the **root** folder and type:
``` ```
npm init -y npm init -y
npm i angular2@2.0.0-alpha.38 systemjs@0.19.2 --save --save-exact npm i angular2@2.0.0-alpha.38 systemjs@0.19.2 --save --save-exact
``` ```
These commands both *install* the packages and *create* an npm `package.json` that will
help us develop and maintain our application in future.
The essence of our `package.json` should look like this: The essence of our `package.json` should look like this:
+makeJson('gettingstarted/ts/package.json', { paths: 'name, version, dependencies '}) +makeJson('gettingstarted/ts/package.json', { paths: 'name, version, dependencies '})
.l-main-section
:markdown
## Update `index.html`
**Replace** the library scripts section with references to
scripts in the packages we just installed.
+makeExample('gettingstarted/ts/src/index.html', 'libraries')
:markdown
**Update** the `System` configuration script as follows.
+makeExample('gettingstarted/ts/src/index.html', 'systemjs')
.l-sub-section
:markdown
We won't be transpiling TypeScript in the browser anymore.
We'll do that on our machine and ship the generated JavaScript
files to the server.
We have to re-configure `system.js` to expect JavaScript files
with a `.js` extension by default.
Someday we might add a `Foo` class to our application in a `foo.ts`
file and import it like this
pre.prettyprint.lang-bash
code import {Foo} from './app/foo'
:markdown
`system.js`will know to look for a file named `foo.js` in the `src/app` folder.
That's exactly what we're doing in the last line. We're
importing our main application file `app` (the generated `app.js` to be precise)
from the `src/app/` folder (we moved it there, remember?)
:markdown
Here's the final version
+makeExample('gettingstarted/ts/src/index.html', null, 'index.html')
.l-main-section .l-main-section
:markdown :markdown
## Prepare for TypeScript Compilation ## Prepare for TypeScript Compilation
@ -169,108 +375,17 @@ include ../../../../_includes/_util-fns
+makeJson('gettingstarted/ts/src/tsconfig.json', null, 'tsconfig.json') +makeJson('gettingstarted/ts/src/tsconfig.json', null, 'tsconfig.json')
:markdown :markdown
Our project folder structure should now look like this: Our final project folder structure should look like this:
``` ```
angular2-getting-started angular2-getting-started
├── node_modules ├── node_modules
├── src ├── src
│ ├── app │ ├── app
| │ └── app.ts
│ ├── typings │ ├── typings
│ │ ├── tsd.d.ts │ │ └──tsd.d.ts
│ ├── tsconfig.json
└── package.json
```
.l-main-section
:markdown
## Create an `index.html`
While in the **`src`** directory we
add a new `index.html` file with the following content
+makeExample('gettingstarted/ts/src/index.html', null, 'index.html')
.l-sub-section
:markdown
We're loading the library scripts in the `<head>` element from the `node_modules`
that we installed earlier with npm.
In the `<body>` is the app root element called `<my-app>` where Angular displays our application content.
The final inline script configures the **`system.js`** module loader and tells it
to import the *application file* named `app` from within the *folder* named `app/`.
**`app.ts`** is our main application file. We haven't written it yet. Let's do so now.
.l-main-section
:markdown
## Write the main application file, `app.ts`
**Change to the `src/app`** directory and **create an `app.ts` file**.
Add an empty class to it called `AppComponent` as follows:
+makeExample('gettingstarted/ts/src/app/app.ts', 'class')(format=".")
:markdown
We won't ask this class to do anything. It's just an empty, meaningless class until we tell
Angular about it by decorating it with some *annotations*.
Import the `component` and `view` *annotations* that we need from the Angular library at the top of the file:
+makeExample('gettingstarted/ts/src/app/app.ts', 'import')(format=".")
:markdown
Apply those annotations to the `AppComponent` class by writing the following lines
just above the class definition:
+makeExample('gettingstarted/ts/src/app/app.ts', 'class-w-annotations')
.l-sub-section
:markdown
TypeScript recognizes the `@` symbol as a prefix for a class annotation.
The **`@Component`** annotation tells Angular this class is a component
that controls the element named "my-app".
You may remember we added such an element to our *index.html* above.
The **`@View`** annotation identifies the "view" - the HTML template -
that defines the visual appearance of this component. We're writing the HTML template inline
in this example. Later we'll move the HTML to a view template file and
assign the template's filename to the `templateUrl`.
We'll prefer that practice for all but the most trivial templates.
.l-main-section
:markdown
## Bootstrap the app
Finally, we tell Angular to start running our app
with an instance of the `AppComponent` class as the root component.
We call this "bootstrapping the app".
+makeExample('gettingstarted/ts/src/app/app.ts', 'bootstrap')(format=".")
:markdown
Here is the complete `app.ts`
+makeExample('gettingstarted/ts/src/app/app.ts', null, 'app.ts')
.l-main-section
:markdown
## Confirm the final project and file structure
It should look like this
```
angular2-getting-started
├── node_modules
├── src
│ ├── app
│ │ ├── app.ts
│ ├── typings
│ │ ├── tsd.d.ts
│ ├── index.html │ ├── index.html
── tsconfig.json │ └── tsconfig.json
└── package.json └── package.json
``` ```
@ -278,8 +393,8 @@ include ../../../../_includes/_util-fns
:markdown :markdown
## Compile the TypeScript to JavaScript ## Compile the TypeScript to JavaScript
We've written our app in TypeScript but the browser only understands JavaScript. We are no longer transpiling TypeScript to JavaScript in the browser.
We must run the TypeScript compiler to produce JavaScript for the browser. We're compiling it on our machine instead.
Open a terminal window in the **root of the application folder** (not *src*) and enter: Open a terminal window in the **root of the application folder** (not *src*) and enter:
@ -295,19 +410,20 @@ include ../../../../_includes/_util-fns
.l-main-section .l-main-section
:markdown :markdown
## Run it! ## Run the app!
Now we are ready to see this app in action. Now we are ready to see this app in action.
Open a another terminal window in the **root of the application folder** (not *src*) and Open another terminal window in the **root of the application folder** (not *src*) and
launch a node static server such as the *live-server* we recommended earlier: launch `live-server` again although this time we add command line
arguments telling it to **serve from the application's new location in `src`**:
pre.prettyprint.lang-bash pre.prettyprint.lang-bash
code live-server --open=src code live-server --open=src
:markdown :markdown
**live-server** loads the browser for us, serves the HTML and JavaScript files, and we should see it display our **live-server** loads the browser for us, serves the HTML and JavaScript files, and we should see it display our
application message: application message once more:
figure.image-display figure.image-display
img(src='/resources/images/devguide/getting-started/my-first-app.png' alt="Output of getting started app") img(src='/resources/images/devguide/getting-started/my-first-app.png' alt="Output of getting started app")
@ -323,33 +439,32 @@ include ../../../../_includes/_util-fns
.l-main-section .l-main-section
:markdown :markdown
## Why so complicated? ## What have we done?
To display a single line of text we Our first application doesn't do much. It's basically "Hello, World" for Angular 2.
* installed a bunch of unfamiliar tools We kept it simple in our first pass: we wrote a little Angular component,
* loaded a couple of libraries we added some JavaScript libraries to `index.html`, and launched with a
* wrote configuration files for both `npm` and TypeScript static file server. That's about all we'd expect to do for a "Hello, World" app.
* configured something called `system.js` in our `index.html` and
told it to import our main file
* are compiling TypeScript in one terminal window and running the server in another
Perhaps we were expecting something simpler: an Angular library,
our application script, and a little HTML. This is all a bit much for a "Hello, World" app.
**We have greater ambitions.** **We have greater ambitions.**
We won't ask Angular to build "Hello, World". We won't ask Angular to build "Hello, World".
We are asking it to help us build sophisticated applications with sophisticated requirements. We are asking it to help us build sophisticated applications with sophisticated requirements.
We're making strategic technology investments to reach our goals
* writing the app in TypeScript for team So we made some strategic technology investments to reach our larger goals
productivity and maintainability.
* designing with modules that we can load features dynamically * our application loads faster with libraries installed locally and
using the latest JavaScript `import` and `export` verbs. we can develop offline if we wish.
* running compiler and live-server commands that give us immediate feedback as we make changes. * we added TypeScript definition files to enhance team
productivity and code maintainability.
* we're pre-compiling our TypeScript.
* we're running the compiler and live-server with commands that give us immediate feedback as we make changes.
The good news is that the overhead of setup is (mostly) behind us. The good news is that the overhead of setup is (mostly) behind us.
We're about to build a small application that demonstrates the great things We're about to build a small application that demonstrates the great things
we can build with Angular 2. Join us on the [Tour of Heroes]. we can build with Angular 2.
Join us next on the [Tour of Heroes].