569 lines
22 KiB
Plaintext
569 lines
22 KiB
Plaintext
block includes
|
||
include _util-fns
|
||
- var _Install = 'Install'
|
||
- var _prereq = 'Node.js'
|
||
- var _angular_browser_uri = '@angular/platform-browser-dynamic'
|
||
- var _angular_core_uri = '@angular/core'
|
||
- var _appDir = 'app'
|
||
- var _indexHtmlDir = 'project root'
|
||
|
||
:marked
|
||
Our QuickStart goal is to build and run a super-simple
|
||
Angular 2 application in #{_Lang}, and
|
||
establish a development environment for the remaining documentation samples
|
||
that also can be the foundation for real world applications.
|
||
|
||
.callout.is-helpful
|
||
header Don't want #{_Lang}?
|
||
p.
|
||
Although we're getting started in #{_Lang}, you can also write Angular 2 apps
|
||
in #{_docsFor == 'ts' ? 'Dart' : 'TypeScript'} and JavaScript.
|
||
Just select either of those languages from the combo-box in the banner.
|
||
|
||
h1 Try it!
|
||
p
|
||
| Try the #[+liveExampleLink2('live example', 'quickstart')] which loads the sample app
|
||
+ifDocsFor('ts')
|
||
| in #[a(href="http://plnkr.co/" title="Plunker" target="_blank") plunker]
|
||
| and displays the simple message:
|
||
|
||
figure.image-display
|
||
img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="Output of QuickStart app")
|
||
|
||
h1 Build this app!
|
||
:marked
|
||
- [Prerequisite](#prereq): Install #{_prereq}
|
||
- [Step 1](#create-and-configure): Create the app’s project folder and
|
||
define package dependencies and special project setup
|
||
- [Step 2](#root-component): Create the app’s Angular root component
|
||
- [Step 3](#main): Add `main.#{_docsFor}`, identifying the root component to Angular
|
||
- [Step 4](#index): Add `index.html`, the web page that hosts the application
|
||
- [Step 5](#build-and-run): Build and run the app
|
||
- [Make some changes to the app](#make-some-changes)
|
||
- [Wrap up](#wrap-up)
|
||
|
||
.l-main-section
|
||
h2#prereq Prerequisite: #{_prereq}
|
||
|
||
block setup-tooling
|
||
:marked
|
||
Install **[Node.js® and npm](https://nodejs.org/en/download/)**
|
||
if they are not already on your machine.
|
||
|
||
block download-source
|
||
.l-main-section
|
||
.callout.is-helpful
|
||
header Download the source
|
||
:marked
|
||
Instead of following each step of these instructions, we can
|
||
[download the QuickStart source](https://github.com/angular/quickstart/blob/master/README.md)
|
||
from github and follow its brief instructions.
|
||
|
||
.l-main-section
|
||
button(class="verbose off md-primary md-button md-ink-ripple", type="button", onclick="verbose(false)").
|
||
Hide explanations
|
||
button(class="verbose on md-primary md-button md-ink-ripple", type="button", onclick="verbose(true)").
|
||
View explanations
|
||
.l-verbose-section
|
||
:marked
|
||
*Explanations* describe the concepts and reasons behind the instructions.
|
||
Explanations have a thin border on the left like *this* block of text.
|
||
|
||
Click *Hide Explanations* to show only the instructions.
|
||
Click *View Explanations* to see everything again.
|
||
|
||
.l-sub-section
|
||
:marked
|
||
We'll see many code blocks as we build the QuickStart app. They're all easy to copy and paste:
|
||
code-example(format="nocode").
|
||
Click the glyph on the right to copy code snippets to the clipboard ==>
|
||
|
||
.l-main-section
|
||
h2#create-and-configure Step 1: Create and configure the project
|
||
|
||
- var _package_and_config_files = _docsFor == 'dart' ? 'pubspec.yaml' : 'package definition and configuration files'
|
||
|
||
:marked
|
||
In this step we:
|
||
* [(a) Create the project folder](#create-the-project-folder)
|
||
* [(b) Add #{_package_and_config_files}](#add-config-files)
|
||
* [(c) #{_Install} packages](#install-packages)
|
||
|
||
h3 (a) Create the project folder
|
||
|
||
code-example(language="sh").
|
||
mkdir angular2-quickstart
|
||
cd angular2-quickstart
|
||
|
||
h3#add-config-files (b) Add #{_package_and_config_files}
|
||
block package-and-config-files
|
||
- var _tsconfigUri = 'guide/typescript-configuration.html#tsconfig'
|
||
- var _typingsUri = 'guide/typescript-configuration.html#!#typings'
|
||
|
||
p Add the following package definition and configuration files to the project folder:
|
||
ul
|
||
li.
|
||
#[b package.json] lists packages the QuickStart app depends on and
|
||
defines some useful scripts.
|
||
See #[a(href="guide/npm-packages.html") Npm Package Configuration] for details.
|
||
li.
|
||
#[b tsconfig.json] is the TypeScript compiler configuration file.
|
||
See #[a(href="#{_tsconfigUri}") TypeScript Configuration] for details.
|
||
li.
|
||
#[b typings.json] identifies TypeScript definition files.
|
||
See #[a(href="#{_typingsUri}") TypeScript Configuration] for details.
|
||
li.
|
||
#[b systemjs.config.js], the SystemJS configuration file.
|
||
See discussion #[a(href="#systemjs") below].
|
||
|
||
a#config-files
|
||
+makeTabs(`
|
||
quickstart/ts/package.1.json,
|
||
quickstart/ts/tsconfig.1.json,
|
||
quickstart/ts/typings.1.json,
|
||
quickstart/ts/systemjs.config.1.js
|
||
`, '', `
|
||
package.json,
|
||
tsconfig.json,
|
||
typings.json,
|
||
systemjs.config.js
|
||
`)
|
||
|
||
h3#install-packages (c) #{_Install} packages
|
||
block install-packages
|
||
:marked
|
||
We install the packages listed in `package.json` using `npm`. Enter the
|
||
following command in a terminal window (command window in Windows):
|
||
|
||
code-example(language="sh").
|
||
npm install
|
||
|
||
.alert.is-important
|
||
:marked
|
||
Scary <span style="color:red; font-weight: bold">error messages in red</span> may appear **during** install.
|
||
The install typically recovers from these errors and finishes successfully.
|
||
.l-verbose-section(class="l-verbose-inherit")
|
||
:marked
|
||
#### npm errors and warnings
|
||
|
||
All is well if there are no console messages starting with `npm ERR!` *at the end* of **npm install**.
|
||
There might be a few `npm WARN` messages along the way — and that is perfectly fine.
|
||
|
||
We often see an `npm WARN` message after a series of `gyp ERR!` messages.
|
||
Ignore them. A package may try to recompile itself using `node-gyp`.
|
||
If the recompile fails, the package recovers (typically with a pre-built version)
|
||
and everything works.
|
||
|
||
Just make sure there are no `npm ERR!` messages at the end of `npm install`.
|
||
|
||
.l-verbose-section
|
||
:marked
|
||
#### Adding the libraries and packages we need with *npm*
|
||
Angular application developers rely on the _[npm](https://docs.npmjs.com)_
|
||
package manager to install the libraries and packages their apps require.
|
||
The Angular team recommends the starter-set of packages specified in the
|
||
`dependencies` and `devDependencies` sections.
|
||
See the [npm packages](guide/npm-packages.html) chapter for details.
|
||
|
||
#### Helpful scripts
|
||
We've included a number of npm scripts in our suggested `package.json` to handle common development tasks:
|
||
+makeJson('quickstart/ts/package.1.json',{ paths: 'scripts'}, 'package.json (scripts)')(format=".")
|
||
|
||
:marked
|
||
We execute most npm scripts in the following way: `npm run` followed by a *script-name*.
|
||
Some commands (such as `start`) don't require the `run` keyword.
|
||
|
||
Here's what these scripts do:
|
||
|
||
* `npm start` - runs the compiler and a server at the same time, both in "watch mode"
|
||
|
||
* `npm run tsc` - runs the TypeScript compiler once
|
||
|
||
* `npm run tsc:w` - runs the TypeScript compiler in watch mode;
|
||
the process keeps running, awaiting changes to TypeScript files and recompiling when it sees them
|
||
|
||
* `npm run lite` - runs the <a href="https://www.npmjs.com/package/lite-server" target="_blank">lite-server</a>,
|
||
a light-weight, static file server with excellent support for Angular apps that use routing
|
||
|
||
* `npm run typings` - runs the [*typings* tool](#{_typingsUri}) separately
|
||
|
||
* `npm run postinstall` - called by *npm* automatically *after* it successfully completes package installation.
|
||
This script installs the [TypeScript definition files](#{_typingsUri}) defined in `typings.json`
|
||
|
||
:marked
|
||
**We're all set.** Let's write some code.
|
||
|
||
.l-main-section
|
||
h2#root-component Step 2: Our first Angular component
|
||
:marked
|
||
Let's create a folder to hold our application and add a super-simple Angular component.
|
||
|
||
**Create #{_an} #{_appDir} subfolder** off the project root directory:
|
||
|
||
code-example.
|
||
mkdir #{_appDir}
|
||
|
||
a#app-component
|
||
p.
|
||
#[b Create the component file]
|
||
#[code #[+adjExPath('app/app.component.ts')]] (in this newly created directory) with the following content:
|
||
|
||
+makeProjExample('app/app.component.ts')
|
||
|
||
.l-verbose-section
|
||
:marked
|
||
### AppComponent is the root of the application
|
||
|
||
Every Angular app has at least one **root component**, conventionally named `AppComponent`,
|
||
that hosts the client user experience.
|
||
Components are the basic building blocks of Angular applications.
|
||
A component controls a portion of the screen — a *view* — through its associated template.
|
||
|
||
This QuickStart has only one, extremely simple component.
|
||
But it has the essential structure of every component we'll ever write:
|
||
|
||
* One or more [import](#component-import)
|
||
statements to reference the things we need.
|
||
* A [@Component #{_decorator}](#component-decorator)
|
||
that tells Angular what template to use and how to create the component.
|
||
* A [component class](#component-class)
|
||
that controls the appearance and behavior of a view through its template.
|
||
|
||
a#component-import
|
||
:marked
|
||
### Import
|
||
|
||
Angular apps are modular. They consist of many files each dedicated to a purpose.
|
||
Angular itself is modular. It is a collection of library modules
|
||
each made up of several, related features that we'll use to build our application.
|
||
|
||
When we need something from a module or library, we import it.
|
||
Here we import the Angular 2 core so that our component code can have access to
|
||
the `@Component` #{_decorator}.
|
||
|
||
+makeExcerpt('app/app.component.ts', 'import')
|
||
|
||
h3#component-decorator @Component #{_decorator}
|
||
+ifDocsFor('ts')
|
||
:marked
|
||
`Component` is a *decorator function* that takes a *metadata object* as argument.
|
||
We apply this function to the component class by prefixing the function with the
|
||
**@** symbol and invoking it with a metadata object, just above the class.
|
||
:marked
|
||
`@Component` is #{_a} *#{_decorator}* that allows us to associate *metadata* with the
|
||
component class.
|
||
The metadata tells Angular how to create and use this component.
|
||
|
||
+makeExcerpt('app/app.component.ts', 'metadata')
|
||
|
||
block annotation-fields
|
||
:marked
|
||
This particular metadata object has two fields, a `selector` and a `template`.
|
||
:marked
|
||
The **selector** specifies a simple CSS selector for an HTML element that represents the component.
|
||
|
||
>The element for this component is named `my-app`.
|
||
Angular creates and displays an instance of our `AppComponent`
|
||
wherever it encounters a `my-app` element in the host HTML.
|
||
|
||
The **template** specifies the component's companion template,
|
||
written in an enhanced form of HTML that tells Angular how to render this component's view.
|
||
|
||
>Our template is a single line of HTML announcing "*My First Angular 2 App*".
|
||
|
||
>A more advanced template could contain data bindings to component properties
|
||
and might identify other application components which have their own templates.
|
||
These templates might identify yet other components.
|
||
In this way an Angular application becomes a tree of components.
|
||
|
||
:marked
|
||
### Component class
|
||
At the bottom of the file is an empty, do-nothing class named `AppComponent`.
|
||
+makeExcerpt('app/app.component.ts', 'class')
|
||
:marked
|
||
When we're ready to build a substantive application,
|
||
we can expand this class with properties and application logic.
|
||
Our `AppComponent` class is empty because we don't need it to do anything in this QuickStart.
|
||
+ifDocsFor('ts')
|
||
:marked
|
||
We **export** `AppComponent` so that we can **import** it elsewhere in our application,
|
||
as we'll see when we create `main.ts`.
|
||
|
||
.l-main-section
|
||
h2#main Step 3: Add #[code #[+adjExPath('main.ts')]]
|
||
|
||
block create-main
|
||
p.
|
||
Now we need something to tell Angular to load the root component.
|
||
Create the file #[code #[+adjExPath('app/main.ts')]] with the following content:
|
||
|
||
+makeProjExample('app/main.ts')
|
||
|
||
.l-verbose-section
|
||
:marked
|
||
We import the two things we need to launch the application:
|
||
|
||
1. Angular's browser `bootstrap` function
|
||
1. The application root component, `AppComponent`.
|
||
|
||
Then we call `bootstrap` with `AppComponent`.
|
||
|
||
### Bootstrapping is platform-specific
|
||
Notice that we import the `bootstrap` function from `#{_angular_browser_uri}`,
|
||
not `#{_angular_core_uri}`.
|
||
Bootstrapping isn't core because there isn't a single way to bootstrap the app.
|
||
True, most applications that run in a browser call the bootstrap function from
|
||
this library.
|
||
|
||
But it is possible to load a component in a different environment.
|
||
We might load it on a mobile device with [Apache Cordova](https://cordova.apache.org/) or [NativeScript](https://www.nativescript.org/).
|
||
We might wish to render the first page of our application on the server
|
||
to improve launch performance or facilitate
|
||
[SEO](http://www.google.com/webmasters/docs/search-engine-optimization-starter-guide.pdf).
|
||
These targets require a different kind of bootstrap function that we'd import from a different library.
|
||
|
||
### Why create separate *main.#{_docsFor}* and app component files?
|
||
|
||
Both `main.#{_docsFor}` and the app component files are tiny.
|
||
This is just a QuickStart.
|
||
We could have merged these two files into one
|
||
and spared ourselves some complexity.
|
||
|
||
We'd rather demonstrate the proper way to structure an Angular application.
|
||
App bootstrapping is a separate concern from presenting a view.
|
||
Mixing concerns creates difficulties down the road.
|
||
We might launch the `AppComponent` in multiple environments with different bootstrappers.
|
||
Testing the component is much easier if it doesn't also try to run the entire application.
|
||
Let's make the small extra effort to do it *the right way*.
|
||
|
||
.l-main-section
|
||
h2#index Step 4: Add #[code index.html]
|
||
:marked
|
||
In the *#{_indexHtmlDir}* folder
|
||
create an `index.html` file and paste the following lines into it:
|
||
|
||
+makeProjExample('index.html')
|
||
|
||
.l-verbose-section
|
||
:marked
|
||
The `index.html` file defines the web page that hosts the application.
|
||
|
||
block index-html-commentary-for-ts
|
||
:marked
|
||
The noteworthy sections of HTML are:
|
||
|
||
1. The JavaScript [libraries](#libraries)
|
||
2. Configuration file for [SystemJS](#systemjs), and a script
|
||
where we import and run the `app` module which refers to the `main` file that we just wrote.
|
||
3. The [`<my-app>`](#my-app) tag in the `<body>` which is *where our app lives!*
|
||
|
||
:marked
|
||
### Libraries
|
||
We loaded the following scripts
|
||
+makeExcerpt('index.html', 'libraries')
|
||
:marked
|
||
We begin with `core-js`'s ES2015/ES6 shim which monkey patches the global context (window) with essential features of ES2015 (ES6).
|
||
Next are the polyfills for Angular2, `zone.js` and `reflect-metadata`.
|
||
Then the [SystemJS](#systemjs) library for module loading.
|
||
|
||
We'll make different choices as we gain experience and
|
||
become more concerned about production qualities such as
|
||
load times and memory footprint.
|
||
|
||
h3#systemjs SystemJS
|
||
:marked
|
||
QuickStart uses <a href="https://github.com/systemjs/systemjs" target="_blank">SystemJS</a>
|
||
to load application and library modules. [Earlier](#add-config-files) we
|
||
added the `systemjs.config.js` file to the project root.
|
||
There are alternatives that work just fine including the well-regarded
|
||
[webpack](guide/webpack.html).
|
||
SystemJS happens to be a good choice.
|
||
But we want to be clear that it was a *choice* and not a *preference*.
|
||
|
||
All module loaders require configuration and all loader configuration
|
||
becomes complicated rather quickly as soon as the file structure diversifies and
|
||
we start thinking about building for production and performance.
|
||
|
||
We suggest becoming well-versed in the loader of your choice.
|
||
Learn more about SystemJS configuration
|
||
<a href="https://github.com/systemjs/systemjs/blob/master/docs/config-api.md" target="_blank">here</a>.
|
||
|
||
With those cautions in mind, what are we doing in the
|
||
QuickStart [`systemjs.config.js` configuration file we added earlier](#config-files)?
|
||
First, we create a map to tell SystemJS where to look when we import some module.
|
||
Then, we register all our packages to SystemJS:
|
||
all the project dependencies and our application package, `app`.
|
||
|
||
.l-sub-section
|
||
:marked
|
||
Our QuickStart doesn't use all of the listed packages
|
||
but any substantial application will want many of them
|
||
and all of the listed packages are required by at least one of the documentation samples.
|
||
|
||
There is no runtime harm in listing packages that we don't need as they will only be loaded when requested.
|
||
:marked
|
||
The `app` package tells SystemJS what to do when it sees a request for a
|
||
module from the `app/` folder.
|
||
|
||
Our QuickStart makes such requests when one of its
|
||
application TypeScript files has an import statement like this:
|
||
+makeExcerpt('app/main.ts', 'import')
|
||
:marked
|
||
Notice that the module name (after `from`) does not mention a filename extension.
|
||
In the configuration we tell SystemJS to default the extension to `js`, a JavaScript file.
|
||
|
||
That makes sense because we transpile TypeScript to JavaScript
|
||
*before* running the application.
|
||
|
||
.l-sub-section
|
||
:marked
|
||
#### Transpiling in the browser
|
||
In the live example on plunker we transpile (AKA compile) to JavaScript in the browser
|
||
on the fly. _That's fine for a demo_.
|
||
|
||
**Do not transpile in the browser during development or for production**.
|
||
|
||
We strongly recommend transpiling (AKA compiling) to JavaScript during a build phase
|
||
before running the application for several reasons including:
|
||
|
||
* We see compiler warnings and errors that are hidden from us in the browser.
|
||
|
||
* Precompilation simpifies the module loading process and
|
||
it's much easier to diagnose problems when this is a separate, external step.
|
||
|
||
* Precompilation means a faster user experience because the browser doesn't waste time compiling.
|
||
|
||
* We iterate development faster because we only recompile changed files.
|
||
We notice the difference as soon as the app grows beyond a handful of files.
|
||
|
||
* Precompilation fits into a continuous integration process of build, test, deploy.
|
||
|
||
:marked
|
||
The `System.import` call tells SystemJS to import the `main` file
|
||
(`main.js` ... after transpiling `main.ts`, remember?);
|
||
`main` is where we tell Angular to launch the application.
|
||
We also catch and log launch errors to the console.
|
||
|
||
All other modules are loaded upon request
|
||
either by an import statement or by Angular itself.
|
||
|
||
### *<my-app>*
|
||
|
||
a(id="my-app")
|
||
:marked
|
||
When Angular calls the `bootstrap` function in `main.#{_docsFor}`, it reads the `AppComponent`
|
||
metadata, finds the `my-app` selector, locates an element tag named `my-app`,
|
||
and renders our application's view between those tags.
|
||
|
||
:marked
|
||
### Add some style
|
||
Styles aren't essential but they're nice, and `index.html` assumes we have
|
||
a stylesheet called `styles.css`.
|
||
|
||
Create a `styles.css` file in the *#{_indexHtmlDir}* folder and start styling, perhaps with the minimal
|
||
styles shown below. For the full set of master styles used by the documentation samples,
|
||
see [styles.css](https://github.com/angular/angular.io/blob/master/public/docs/_examples/styles.css).
|
||
+makeExcerpt('styles.1.css')
|
||
|
||
.l-main-section
|
||
h2#build-and-run Step 5: Build and run the app!
|
||
block run-app
|
||
:marked
|
||
Open a terminal window and enter this command:
|
||
code-example.
|
||
npm start
|
||
:marked
|
||
That command runs two parallel node processes
|
||
1. The TypeScript compiler in watch mode
|
||
1. A static server called **lite-server** that loads `index.html` in a browser
|
||
and refreshes the browser when application files change
|
||
|
||
In a few moments, a browser tab should open and display
|
||
|
||
figure.image-display
|
||
img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="Output of QuickStart app")
|
||
|
||
:marked
|
||
**Great job!**
|
||
|
||
block build-app
|
||
//- Nothing for ts.
|
||
|
||
:marked
|
||
## Make some changes
|
||
|
||
Try changing the message to "My SECOND Angular 2 app".
|
||
block server-watching
|
||
:marked
|
||
The TypeScript compiler and `lite-server` are watching.
|
||
They should detect the change, recompile the TypeScript into JavaScript,
|
||
refresh the browser, and display the revised message.
|
||
It's a nifty way to develop an application!
|
||
|
||
We close the terminal window when we're done to terminate both the compiler and the server.
|
||
|
||
.l-main-section
|
||
:marked
|
||
# Wrap up
|
||
|
||
Our final project folder structure looks like this:
|
||
block project-file-structure
|
||
.filetree
|
||
.file angular2-quickstart
|
||
.children
|
||
.file app
|
||
.children
|
||
.file app.component.ts
|
||
.file main.ts
|
||
.file node_modules ...
|
||
.file typings ...
|
||
.file index.html
|
||
.file package.json
|
||
.file styles.css
|
||
.file systemjs.config.js
|
||
.file tsconfig.json
|
||
.file typings.json
|
||
:marked
|
||
Here are the file contents:
|
||
|
||
block project-files
|
||
+makeTabs(`
|
||
quickstart/ts/app/app.component.ts,
|
||
quickstart/ts/app/main.ts,
|
||
quickstart/ts/index.html,
|
||
quickstart/ts/package.1.json,
|
||
quickstart/ts/tsconfig.1.json,
|
||
quickstart/ts/typings.1.json,
|
||
quickstart/ts/styles.1.css,
|
||
quickstart/ts/systemjs.config.1.js`
|
||
,null,
|
||
`app/app.component.ts,
|
||
app/main.ts,
|
||
index.html,
|
||
package.json,
|
||
tsconfig.json,
|
||
typings.json,
|
||
styles.css,
|
||
systemjs.config.js`)
|
||
|
||
.l-main-section
|
||
:marked
|
||
## What next?
|
||
Our first application doesn't do much. It's basically "Hello, World" for Angular 2.
|
||
|
||
We kept it simple in our first pass: we wrote a little Angular component,
|
||
created a simple `index.html`, and launched with a
|
||
static file server. That's about all we'd expect to do for a "Hello, World" app.
|
||
|
||
**We have greater ambitions!**
|
||
block what-next-ts-overhead
|
||
:marked
|
||
The good news is that the overhead of setup is (mostly) behind us.
|
||
We'll probably only touch the `package.json` to update libraries.
|
||
We'll likely open `index.html` only if we need to add a library or some css stylesheets.
|
||
:marked
|
||
We're about to take the next step and build a small application that
|
||
demonstrates the great things we can build with Angular 2.
|
||
|
||
Join us on the [Tour of Heroes Tutorial](./tutorial)!
|