Compare commits

...

197 Commits

Author SHA1 Message Date
5775376bcf docs: add changelog for 5.0.0 2017-11-01 10:50:28 -07:00
896b853519 release: cut the 5.0.0 release 2017-11-01 09:44:19 -07:00
5225fdbc0e build(aio): add i18n boilerplate type (#20004)
PR Close #20004
2017-10-31 01:46:06 -04:00
f5b7f2b9a5 docs: add changelog for 5.0.0-rc.9 2017-10-30 21:09:14 -07:00
509f392ab0 release: cut the 5.0.0-rc.9 release 2017-10-30 21:07:37 -07:00
cf5fce8d5e build: update rollup lint rule from bad merge (#20047)
PR Close #20047
2017-10-30 23:45:06 -04:00
f1248b69e6 refactor: make all rollup config ES5 compatible (#20028)
So they can be required by other Node scripts.

PR Close #20028
2017-10-30 23:28:18 -04:00
4498dddbe3 build: add lint rule for global flags in rollup config (#20028)
We now verify that every imports is part of the globals defined in the files rollup.config.js.

PR Close #20028
2017-10-30 23:28:11 -04:00
812786f44e fix: add missing globals from each rollup configuration (#20028)
PR Close #20028
2017-10-30 23:11:42 -04:00
de24d54517 fix(compiler): report errors properly in G3 in certain conditions (#20041)
Condition: static analysis error, given:
- noResolve:true
- generateCodeForLibraries: false
- CompilerHost.getSourceFile throws on non existent files

All of these are true in G3.
PR Close #20041
2017-10-30 23:07:37 -04:00
c295aeeca2 build: add release as a valid commit message subject (#19955)
PR Close #19955
2017-10-30 21:23:48 -04:00
a8add78fe1 build: temporarily increase the commit msg limit to 120
Right now HEAD and 5.0.x have a branch deviation and therefore
all the commits between both branches are being compared. There
exists a problematic commit which has a commit message that is
longer than 100 commits. This patch will temporarily increase
the limit to 120 so that CI passes. Once master is resumed to
being the primary development branch (once 5.0.0 is out) then
the the msg limit will be set back to 100.
2017-10-30 21:23:43 -04:00
e3a16ed02d fix(compiler): reexport less symbols in .ngfactory.ts files (#19884)
* don't reexport symbols that the user already reexported
* never reexport symbols that are part of arguments of non simple function calls

Fixes #19883

PR Close #19884
2017-10-30 21:19:44 -04:00
fd37f3fbab fix(compiler): always use relative paths to refer to generated code
Previously we generated imports like `@angular/material/index.ngfactory`,
which doesn’t make sense as we don’t ship generated code on npm

Closes #20031
2017-10-30 20:00:48 -04:00
85e95cc32b docs: add changelog for 5.0.0-rc.8 2017-10-27 23:31:35 -07:00
de71ba74bb release: cut the 5.0.0-rc.8 release 2017-10-27 23:31:27 -07:00
a01c877534 docs: ensure examples get rxjs ^5.5.0 (#19985)
This change coincidentally updates other packages that were in `package.json`
because it regenerates `yarn.lock`. This too should be fine.

PR Close #19985
2017-10-27 22:28:21 -07:00
2d508a3ef0 fix(compiler-cli): avoid producing source mappings for host views (#19965)
The host view doesn't map back to user code so the template compiler
produces a blank `url` for them.

PR Close #19965
2017-10-27 22:28:14 -07:00
4285b6c3e3 fix(platform-server): add missing packages to the UMD global rollup config
This adds the proper bindings for calling angular packages from platform-server in the UMD.
This was not a problem for universal apps that dont use UMD.

Fixes 19899
2017-10-27 22:27:43 -07:00
5542517b9c docs: add changelog for 5.0.0-rc.7 2017-10-26 19:03:14 -07:00
fef3539608 release: cut the 5.0.0-rc.7 release 2017-10-26 19:01:34 -07:00
f4d5729cb3 fix(compiler): make watch mode work on windows (#19953)
Fixes #19951
PR Close #19953
2017-10-26 21:52:35 -04:00
d343bf7885 fix(compiler): recover from structural errors in watch mode (#19953)
This also changes the compiler so that we throw less often
on structural changes and produce a meaningful state
in the `ng.Program` in case of errors.

Related to #19951

PR Close #19953
2017-10-26 21:52:25 -04:00
9ce7f0e538 fix(compiler): translate emit diagnostics with noEmitOnError: true. (#19953)
This prevents errors reported against `.ngfactory.ts` files show up
as the result of running `ngc`.

Closes #19935
PR Close #19953
2017-10-26 21:52:16 -04:00
4a23df3909 fix(compiler): don’t store invalid state when using listLazyRoutes (#19953)
Previously, `listLazyRoute` would store invalid information in a compiler
internal cache, which lead to incorrect paths that were used during emit.
This commit fixes this.

PR Close #19953
2017-10-26 21:51:43 -04:00
14016c781f fix(service-worker): fix improper call of Observable.merge (#19962)
Observable.merge was called using .call() as if it were an operator
and not an Observable factory. This removes the .call() and uses
the factory properly.

PR Close #19962
2017-10-26 18:16:20 -04:00
47caebfe86 fix(service-worker): don't block initialization on registration (#19936)
Importing ServiceWorkerModule.register() will schedule registration of
the Service Worker inside an APP_INITIALIZER. Previously, the Promise
returned by navigator.serviceWorker.register() was returned from the
initializer function. This has the unwanted side effect of blocking
initialization until the SW is registered. Even worse, if the SW script
fails to load, this can cause the app initialization to fail.

The solution is to not return the registration promise from the
initializer function, essentially decoupling registration from the rest
of the initialization flow.

This change is not unit testable as there are no mocks/adapters yet for
navigator.serviceWorker. A future integration test should cover this case
with better fidelity.

PR Close #19936
2017-10-26 16:10:17 -04:00
5cfd9c6020 fix(service-worker): listen for messages on the right event source (#19954)
Currently, the SwUpdate service doesn't receive messages from the SW.
This is because it attempts to subscribe to the 'message' event on
ServiceWorkerRegistration, when really messages are emitted by the
ServiceWorkerContainer.

This change moves to listening on ServiceWorkerContainer and changes
the mocks to reflect the way the browser actually works.

PR Close #19954
2017-10-26 16:10:07 -04:00
47bc6f105d docs: add changelog for 5.0.0-rc.6 2017-10-25 14:34:42 -07:00
40fa2593a9 release: cut the 5.0.0-rc.6 release 2017-10-25 14:32:11 -07:00
680bcf7b8a build: update to rxjs@5.5.2 (#19931)
PR Close #19931
2017-10-25 15:32:01 -04:00
ef08330341 fix(compiler): automatically set emitDecoratorMetadata when "annotationsAs": "static fields” (#19927)
This is a workaround for https://github.com/angular/tsickle/issues/635.

Fixes #19916
PR Close #19927
2017-10-25 14:26:28 -04:00
6cc042e2ba fix(compiler-cli): produce correct paths for windows output (#19915)
The path mapping was broken for Windows by fc0b1d5b61.
Fixed the path mapping and put code in place to make such a problem
to sneek by again.

PR Close #19915
2017-10-24 19:21:18 -04:00
9b26455740 fix(compiler-cli): only use error collector when needed. (#19912)
The error collector changes behavior of the metadata resolver
in ways that haven't been fully hardened. This changes limits
its use to the lazy route detection and the language service.

Issue: #19906

PR Close #19912
2017-10-24 19:21:13 -04:00
18bce5987c fix(compiler): don’t type check templates with skipTemplateCodegen (#19909)
This change is needed to prevent users’ builds from breaking.

If a user sets `fullTemlateTypeCheck` to true, we will
continue to check the templates even when `skipTemplateCodegen` is true
as well.

Related to #19906

PR Close #19909
2017-10-24 19:21:03 -04:00
f1108fea76 docs: add changelog for 5.0.0-rc.5 2017-10-23 23:28:28 -07:00
64b3e3e41a release: cut the 5.0.0-rc.5 release 2017-10-23 23:27:15 -07:00
a82f863e24 fix(compiler-cli): report all diagnostic error messages (#19886)
This fixes a problem introduced in 8d45fefc31
which modified how diagnostic error messages are reported for structural
metadata errors causing some of the diagnostics to be lost.

PR Close #19886
2017-10-24 00:57:41 -04:00
bde57016c6 docs: add changelog for 5.0.0-rc.4 2017-10-23 17:35:17 -07:00
b16f4bce98 release: cut the 5.0.0-rc.4 release 2017-10-23 17:31:42 -07:00
6bed189e37 build(service-worker): set skipTemplateCodegen for build (#19875)
PR Close #19875
2017-10-23 19:31:42 -04:00
4abacb58f1 fix(aio): add service worker entrypoint to aio build (#19875)
Fixes #19838

PR Close #19875
2017-10-23 19:31:42 -04:00
04200150d5 docs: add service-worker to list of allowed scopes (#19875)
PR Close #19875
2017-10-23 19:31:42 -04:00
fc0b1d5b61 fix(compiler): correctly calculate the outDir if it repeats a parts of the rootDir. (#19836)
Fixes #19718

PR Close #19836
2017-10-23 18:46:04 -04:00
8d45fefc31 refactor(compiler): remove old ngtools api and add listLazyRoutes to new api (#19836)
Usages of `NgTools_InternalApi_NG_2` from `@angular/compiler-cli` will now
throw an error.

Adds `listLazyRoutes` to `@angular/compiler-cli/ngtools2.ts` for getting
the lazy routes of a `ng.Program`.
PR Close #19836
2017-10-23 18:46:04 -04:00
5da96c75a2 fix(bazel): don't console.error from the compile helper (#19879)
This lets other callers of compile() choose different formatting for the diagnostics

PR Close #19879
2017-10-23 16:56:57 -04:00
90d1423fb4 fix(service-worker): include versionedFiles in the manifest hashTable (#19837)
There is no difference in runtime (yet) between versioned and unversioned
files. Theoretically, the SW does not have to cache-bust versioned files,
but the SW doesn't cache bust files on the first request anyway, so in the
common case it doesn't matter. If the hash doesn't match, the SW will cache
bust the file to be sure, which is technically unnecessary, but since the
file itself is versioned, the likelihood of this happening is rare.

This fixes a critical bug where versioned files were erroneously not included
in the hashTable in the generated manifest. This could lead to applications
not updating if only versioned files changed in between versions.

PR Close #19837
2017-10-23 15:11:38 -04:00
910735d732 build: fix yarn install command (--freeze-lockfile --> --frozen-lockfile) 2017-10-20 10:14:30 -07:00
fc86352adf build(aio): use http push for navigation.json 2017-10-20 09:41:02 -07:00
441e01c568 fix(aio): simplify GaService to avoid e2e test failures
The GaService and the E2E specs were unnecessarily complicated and had
arbitrary async timeouts to ensure that the interplay between the GA
library code and the rest of the app worked correctly. This resulted
in potential flaky tests if the timeouts were not adequate; this was
experienced when Travis upgraded to Chrome 62.

The new approach is to block loading of the Analytics library altogether
if there is a `__e2e__` flag set in the `SessionStorage` of the browser.
It doesn't appear to be enough just to set the flag directly on the
window. I think this is because the window gets cleaned when navigation
occurs (but I am not certain).

The downside of this is that we had to add a small piece of extra logic
to the GA snippet in index.html; and we also had to switch from using
`<script async ...>` to a programmatic approach to loading the GA library
which prevents the browser from eagerly fetching the library. This may
be mitigated by adding it to the HTTP/2 push configuration of the Firebase
hosting.

Re-enables the test that was disabled in https://github.com/angular/angular/pull/19784

Closes #19785
2017-10-20 09:40:52 -07:00
14380ff086 build: add warning about changing ngtools_api2 2017-10-20 09:39:30 -07:00
820bb7bd8c revert: ci: use chrome stable (#18307)
This reverts commit 8bcb268140.
2017-10-20 09:38:59 -07:00
230b98d4dd docs: add changelog for 5.0.0-rc.3 2017-10-18 17:23:09 -07:00
065ea926c0 release: cut the 5.0.0-rc.3 release 2017-10-18 17:23:09 -07:00
9b9820858e docs: add changelog for 4.4.6 2017-10-18 17:23:09 -07:00
b922743f6e build: narrow TS version to >=2.4.2 and <2.5 (#19787)
As this is the only version range that we tested against in G3.
We will support newer versions of TypeScript soon 
after the Angular 5 release.

Closes #19750

PR Close #19787
2017-10-18 11:20:23 -07:00
04ab9f1917 fix(common): attempt to JSON.parse errors for JSON responses (#19773)
PR Close #19773
2017-10-18 11:18:58 -07:00
25cbc98979 fix(compiler-cli): do not add references to files outside of rootDir (#19770)
References to resources (such as .css files) that are generated into
the `outDir` directory outside of `rootDir` would cause a spurious
compiler error about not being able to find a files that ends in
'.ngstyle.ts'.

Also fixed a minor issue in compiler error reporting

Fixes: #19765, #19767

PR Close #19770
2017-10-18 11:18:50 -07:00
3861ba2929 docs(changelog): fix typo (#19766)
PR Close #19766
2017-10-18 11:18:42 -07:00
3bcf0cf472 fix(service-worker): PushEvent.data has to be decoded (#19764)
PushEvent.data is not the data object itself, but an instance representing
the data in wire format, with methods to synchronously decode it to JSON,
ArrayBuffer, etc. NGSW assumes all push data is in JSON format.

PR Close #19764
2017-10-18 11:18:34 -07:00
396c2417d9 fix(service-worker): freshness strategy should clone response for cache (#19764)
When Cache.put() is called with a Response, it consumes the response. If
the Response is used for any other purpose (such as satisfying the
original FetchEvent) it must be cloned first.

A bug exists in the mocks used for SW tests, where this condition is not
validated. The bodies of MockResponses can be utilized repeatedly without
erroring in the same way that a real browser would. This bug is fixed by
this commit, which causes tests for the freshness strategy of data caching
to start failing.

The cause of this failure is a second bug in the data caching code, where
the Response is not cloned prior to being passed to Cache.put(). This is
also fixed.

PR Close #19764
2017-10-18 11:18:34 -07:00
fcfb1544e8 docs(aio): changed confusing term (#19762)
Controller should be decorator I believe

PR Close #19762
2017-10-18 11:18:26 -07:00
56774dfb79 fix(compiler-cli): diagnostics file paths relative to cwd, not tsconfig (#19748)
PR Close #19748
2017-10-18 11:18:17 -07:00
c0cc6eeca1 test(animations): ensure :enter callbacks fire on container insertion (#19674)
PR Close #19674
2017-10-18 11:18:08 -07:00
6f2939da62 fix(router): RouterLinkActive should update its state right after checking the children (#19449)
Closes #18983

PR Close #19449
2017-10-18 11:17:55 -07:00
7d1abd9adb build: update to rxjs@5.5.0 (#19345)
PR Close #19345
2017-10-18 11:17:43 -07:00
81173b0d29 fix(aio): make tests less flaky (#19784)
PR Close #19784
2017-10-18 10:19:24 -07:00
b0c7ea8181 Revert "fix(router): RouterLinkActive should update its state right after checking the children (#19449)"
This reverts commit c569b75249.
As it was synched together with 5a9ed2de27
which broke an internal test.
2017-10-18 09:58:41 -07:00
30ecb6e88a Revert "test(animations): ensure :enter callbacks fire on container insertion (#19674)"
This reverts commit 41f57affb6.
As it was synched together with 5a9ed2de27
which broke an internal test.
2017-10-18 09:57:56 -07:00
8d735da5d8 Revert "fix(animations): always fire inner trigger callbacks even if blocked by parent animations (#19753)"
This reverts commit 5a9ed2de27.
As it broke an internal test.
2017-10-18 09:56:59 -07:00
5a9ed2de27 fix(animations): always fire inner trigger callbacks even if blocked by parent animations (#19753)
Closes #19100

PR Close #19753
2017-10-17 20:57:57 -07:00
41f57affb6 test(animations): ensure :enter callbacks fire on container insertion (#19674)
PR Close #19674
2017-10-17 20:57:48 -07:00
c569b75249 fix(router): RouterLinkActive should update its state right after checking the children (#19449)
Closes #18983

PR Close #19449
2017-10-17 20:57:30 -07:00
01e4aa5427 build: remove required BrowserStack run as it fails with “Access denied” (#19769)
See #19768
PR Close #19769
2017-10-17 15:51:40 -07:00
ad130d62d8 fix(compiler): add first bazel test for ng_module (#19703)
We were missing quite a bit of test coverage,
this is the start of recreating it.
PR Close #19703
2017-10-17 15:18:31 -07:00
621f87b2bd fix(service-worker): use posix path resolution for generation of ngsw.json (#19527)
PR Close #19527
2017-10-17 15:18:17 -07:00
64b36190de build: don’t make BrowserStack required as it fails with “Access denied”
See #19768
2017-10-17 14:56:10 -07:00
507290d30d build: fix broken path for animations in .pullapprove (#19453)
PR Close #19453
2017-10-17 10:45:10 -07:00
15a8429b96 fix(service-worker): add missing annotation for SwPush (#19721)
PR Close #19721
2017-10-17 10:38:45 -07:00
9723a362b6 docs(aio): update 2018 events (#19706)
update ac 2017 dates

PR Close #19706
2017-10-17 10:38:37 -07:00
d75a9fabdc ci: validate commit messages correctly when not on master (#19685)
PR Close #19685
2017-10-17 10:38:29 -07:00
9b264c5c78 docs(aio): change in-mem-web-api version for examples (#19668)
PR Close #19668
2017-10-17 10:38:15 -07:00
60bdcd6f5f fix(compiler): generate correct imports for type check blocks (#19582)
Fixes: #19485

PR Close #19582
2017-10-17 10:37:55 -07:00
d035175cdb fix(animations): ensure inner :leave animations do not remove node when skipped (#19532) (#19693)
PR Close #19693
2017-10-16 11:13:58 -07:00
f42d317d2f fix(animations): ensure animateChild() works with all inner leave animations (#19006) (#19532) (#19693)
PR Close #19693
2017-10-16 11:13:58 -07:00
405ccc7195 fix(bazel): fix the output directory for extractor to be genfiles/ instead of bin/ (#19716)
PR Close #19716
2017-10-13 17:31:10 -07:00
836c889baa fix(compiler): prepare for future Bazel semantics of += (#19717)
This is a local mod that was already applied in G3.

PR Close #19717
2017-10-13 16:29:46 -07:00
43f9d917d9 build(aio): fix overwriting with local Angular packages that depend on other local ones (#19655)
PR Close #19655
2017-10-13 09:27:51 -07:00
62c7b7842b test(aio): fix testing of NgPackagesInstaller (#19655)
PR Close #19655
2017-10-13 09:27:51 -07:00
97969a85cd ci(aio): raise payload limit to accommodate the new search feature (#19682)
PR Close #19682
2017-10-13 09:18:42 -07:00
91fcfcb042 feat(aio): add search to 404 page (#19682)
The 404 page will now run a search based on the given URL to offer
suggestions for the page that the user really wanted.

PR Close #19682
2017-10-13 09:18:42 -07:00
88c46feb20 refactor(aio): move SearchResultsComponent into shared module (#19682)
This will allow it to be used by an embedded component.

PR Close #19682
2017-10-13 09:18:42 -07:00
c3f07b329f feat(aio): allow SearchService to have multiple clients (#19682)
PR Close #19682
2017-10-13 09:18:41 -07:00
6121083ba5 test(aio): tidy up e2e tests that used invalid URLs (#19682)
PR Close #19682
2017-10-13 09:18:41 -07:00
717c68089d build(aio): remove unused imports and local variables (#19682)
PR Close #19682
2017-10-13 09:18:41 -07:00
09b4244baf fix(aio): upgrade rxjs dependency to work with TS 2.4 (#19682)
PR Close #19682
2017-10-13 09:18:41 -07:00
2e45267705 ci: add service-worker to pullapprove (#19642)
PR Close #19642
2017-10-13 09:15:59 -07:00
e81d1fc361 docs(animations): add missing bracket to fadeAnimation
Closes #18899
2017-10-13 09:12:36 -07:00
02394d2d80 fix(core): don't refer to hydration in docs anymore.
Closes #18458
2017-10-13 08:53:44 -07:00
653a211743 Revert "Revert "Revert "perf(compiler): skip type check and emit in bazel in some cases. (#19646)"""
This reverts commit 6b7cead0c5.
2017-10-12 16:09:49 -07:00
522ec9a25b docs: add changelog for 5.0.0-rc.2 2017-10-12 13:43:49 -07:00
0fdb7f7181 release: cut the 5.0.0-rc.2 release 2017-10-12 13:38:20 -07:00
443ff33f63 docs: add changelog for 4.4.5 2017-10-12 13:31:41 -07:00
6b7cead0c5 Revert "Revert "perf(compiler): skip type check and emit in bazel in some cases. (#19646)""
This reverts commit 94a925a1b0.
2017-10-12 10:32:21 -07:00
94a925a1b0 Revert "perf(compiler): skip type check and emit in bazel in some cases. (#19646)"
This reverts commit a22121d65d.
2017-10-12 10:26:53 -07:00
055b802713 docs(aio): improve the Angular Connect homepage banner (#19684)
The original logo was too small.
The conference is over two days.

PR Close #19684
2017-10-12 09:31:38 -07:00
41fec319c8 docs(aio): change Material 2 to Material (#19663)
it is just called Angular Material now
PR Close #19663
2017-10-11 16:46:49 -07:00
a22121d65d perf(compiler): skip type check and emit in bazel in some cases. (#19646)
If no user files changed:
- only type check the changed generated files

Never emit non changed generated files
- we still calculate them, but don’t send them through
  TypeScript to emit them but cache the written files instead.
PR Close #19646
2017-10-11 15:54:02 -07:00
3acf9c7063 docs(aio): update banner ad (#19669)
PR Close #19669
2017-10-11 13:14:59 -07:00
566606ef46 ci: freeze yarn lockfile when installing dependencies (#19616)
PR Close #19616
2017-10-11 11:52:36 -07:00
afa2bb246b build(aio): freeze lockfile when setting up examples (#19616)
PR Close #19616
2017-10-11 11:52:35 -07:00
dc038113a5 build(aio): freeze yarn lockfile for aio-builds-setup scripts (#19616)
PR Close #19616
2017-10-11 11:52:35 -07:00
ad7e781a18 build(aio): freeze lockfile when installing example dependencies (#19616)
PR Close #19616
2017-10-11 11:52:35 -07:00
437e803f27 ci(aio): freeze the lockfile for CI builds (#19616)
The CI will now fail if the dependencies in the AIO
package.json have been modified without the
lockfile being updated.

PR Close #19616
2017-10-11 11:52:35 -07:00
dbe6cdad7e build(aio): improve accessor rendering (#19637)
Includes an update to `dgeni-packages@0.22.0` which provides more info
about accessors if required.

PR Close #19637
2017-10-11 11:51:42 -07:00
46992b4bda Revert "fix(animations): ensure animateChild() works with all inner leave animations (#19006) (#19532)"
This reverts commit 9130505b57.
2017-10-11 10:51:52 -07:00
d0af45c31a Revert "fix(animations): ensure inner :leave animations do not remove node when skipped (#19532)"
This reverts commit ac50bd678e.
2017-10-11 10:37:12 -07:00
8b571309ed build(aio): append information about links in and out of docs (#19583)
Closes #19560

PR Close #19583
2017-10-10 17:06:51 -07:00
b0befd7376 fix(compiler): TestBed.overrideProvider should keep imported NgModules eager (#19624)
Before, as soon as a user called `TestBed.overrideProvider` for a provider
of a `NgModule` that was imported via `TestBed.configureTestingModule`,
that `NgModule` became lazy.

This commit changes this behavior to keep the `NgModule` eager,
with or without a call to `TestBed.overrideProvider`.

PR Close #19624
2017-10-10 13:51:25 -07:00
dfa0973563 docs(aio): update animations for CLI (#19551)
PR Close #19551
2017-10-10 13:47:35 -07:00
ac50bd678e fix(animations): ensure inner :leave animations do not remove node when skipped (#19532)
PR Close #19532
2017-10-10 12:41:47 -07:00
9130505b57 fix(animations): ensure animateChild() works with all inner leave animations (#19006) (#19532)
Closes #18305

PR Close #19532
2017-10-10 12:41:47 -07:00
931cf78057 refactor(compiler): introduce TestBed.deprecatedOverrideProvider (#19558)
This allows use to fix `TestBed.overrideProvider` to keep imported `NgModule`s eager,
while allowing our users to still keep the old semantics until they have fixed their
tests.

PR Close #19558
2017-10-10 10:15:46 -07:00
6ade68cff1 fix(compiler): correctly instantiate eager providers that are used via Injector.get (#19558)
Closes #15501

PR Close #19558
2017-10-10 10:15:46 -07:00
d30ce19231 fix(compiler): correctly calculate the out path on windows (#19601)
Fixes #19543
PR Close #19601
2017-10-10 10:15:06 -07:00
d7eac7ee56 Revert "fix(router): navigating to the current location works (#19463)"
This reverts commit 43c5b638b9.
2017-10-09 16:38:12 -07:00
d53b96f2a2 Revert "fix(router): do not call location.go when skipping a navigation (#19463)"
This reverts commit 6651541230.
2017-10-09 16:37:31 -07:00
79deeacbd7 docs(aio): add copy about ngNoForm to NgForm API doc (#19561)
PR Close #19561
2017-10-09 14:53:49 -07:00
32ca6851af build(aio): do not fail on first yarn setup (#19603)
PR Close #19603
2017-10-09 14:47:12 -07:00
cff8c05442 build(aio): ensure yarn lockfile has correct dgeni-packages version (#19617)
PR Close #19617
2017-10-09 14:46:18 -07:00
0ea5f8b5ed docs: add universal guide with production client app - with JK’s edits (#18707)
PR Close #18707
2017-10-09 14:46:04 -07:00
555b1cdf29 docs: add universal guide with production client app (#18707)
Revises both universal and client build to use AOT and webpack for both.
Guide text adjusted accordingly
Dodges CLI client build, expected in near future.

PR Close #18707
2017-10-09 14:46:04 -07:00
0b0d25fa33 docs: add universal guide (#18707)
- based on original effort in PR 17573

PR Close #18707
2017-10-09 14:46:04 -07:00
963a4d0dc8 build(aio): sort API list alphabetically (#19566)
Closes #19559

PR Close #19566
2017-10-09 14:42:52 -07:00
f393d86c96 build: add a Git .mailmap with my new name (#19550)
In this way my past contribution is mapped correctly.

PR Close #19550
2017-10-09 14:35:30 -07:00
6651541230 fix(router): do not call location.go when skipping a navigation (#19463)
Closes #18036

PR Close #19463
2017-10-09 11:45:13 -07:00
43c5b638b9 fix(router): navigating to the current location works (#19463)
Closes #13340

PR Close #19463
2017-10-09 11:45:13 -07:00
c3a52697f5 perf(animations): reduce size of bundle by removing AST classes (#19539)
This CL refactors the animation AST code to make use of interfaces instead of classes. Given that interfaces are not persisted during runtime the removal of classes should nicely cut down on size for the animations-browser bundle.

-- before --
animations-browser.umd.js = 222kb
animations-browser.umd.min.js = 107kb

-- after --
animations-browser.umd.js = 213kb
animations-browser.umd.min.js = 102kb

PR Close #19539
2017-10-09 10:00:48 -07:00
c4704c8abc fix(animations): properly support boolean-based transitions and state changes (#19279)
Closes #9396
Closes #12337

PR Close #19279
2017-10-09 10:00:32 -07:00
b1ca5d4ddf Revert "perf(animations): reduce size of bundle by removing AST classes (#19539)"
This reverts commit d5c9c5f183.
2017-10-06 18:16:30 -07:00
9fecd72f44 Revert "test(animations): test to see if triggers get cancelled on removal (#19532)"
This reverts commit f12e15e682.
2017-10-06 18:15:26 -07:00
f4480d46b4 Revert "fix(animations): ensure animateChild() works with all inner leave animations (#19532)"
This reverts commit 1c77cdadaf.
2017-10-06 18:15:22 -07:00
8e5b582b61 Revert "fix(router): navigating to the current location works (#19463)"
This reverts commit b67d574a95.
2017-10-06 18:15:19 -07:00
0cc87c5ba1 Revert "fix(router): do not call location.go when skipping a navigation (#19463)"
This reverts commit fdfa31798b.
2017-10-06 18:15:16 -07:00
6aa7cc1d96 Revert "fix(animations): properly support boolean-based transitions and state changes (#19279)"
This reverts commit a8920eb774.
2017-10-06 18:15:08 -07:00
a8920eb774 fix(animations): properly support boolean-based transitions and state changes (#19279)
Closes #9396
Closes #12337

PR Close #19279
2017-10-06 15:35:37 -07:00
fdfa31798b fix(router): do not call location.go when skipping a navigation (#19463)
Closes #18036

PR Close #19463
2017-10-06 15:35:25 -07:00
b67d574a95 fix(router): navigating to the current location works (#19463)
Closes #13340

PR Close #19463
2017-10-06 15:35:24 -07:00
1c77cdadaf fix(animations): ensure animateChild() works with all inner leave animations (#19532)
Closes #18305

PR Close #19532
2017-10-06 15:35:13 -07:00
f12e15e682 test(animations): test to see if triggers get cancelled on removal (#19532)
PR Close #19532
2017-10-06 15:35:13 -07:00
d5c9c5f183 perf(animations): reduce size of bundle by removing AST classes (#19539)
This CL refactors the animation AST code to make use of interfaces instead of classes. Given that interfaces are not persisted during runtime the removal of classes should nicely cut down on size for the animations-browser bundle.

-- before --
animations-browser.umd.js = 222kb
animations-browser.umd.min.js = 107kb

-- after --
animations-browser.umd.js = 213kb
animations-browser.umd.min.js = 102kb

PR Close #19539
2017-10-06 15:34:57 -07:00
f83989bb0d fix(compiler-cli): produce smaller source maps for templates (#19578)
Assocating each template node with a the generated TypeScript
generated overly verbose source maps. Changed to creating a
source map entry per unique source span instead of each
unique template ast node.

Fixes: #19537

PR Close #19578
2017-10-06 14:48:25 -07:00
81167d9c4a perf(compiler): speed up loading of summaries for bazel. (#19581)
For hazel, we have a specific way of writing summaries,
which we can leverage to make the deserialization faster.

PR Close #19581
2017-10-06 14:48:02 -07:00
0b06ea177a perf(compiler): only type check input files when using bazel (#19581)
This helps hazel as it does not check libraries (e.g. the default lib) which are
not input files, but still checks `.d.ts` files that are inputs.

PR Close #19581
2017-10-06 14:48:02 -07:00
03227e65cf build(aio): example-boilerplate is no longer responsible for yarn install (#19511)
The tooling for boilerplate was also running `yarn install` on the examples'
shared folder. But since this is handled by `ng-packages-installer` this
commit refactors the tools so that the boilerplate no longer does this
anymore.

PR Close #19511
2017-10-06 11:56:41 -07:00
ca7f2f8c8f docs(aio): fix aot-compiler example to work with Angular v5 (#19511)
PR Close #19511
2017-10-06 11:56:41 -07:00
340d94afb9 build(aio): ignore @angular/mobile-toolkit in dist builds (#19511)
The new v5 version of this toolkit is too incompatible for us to run
AIO against both versions. So for now we will ignore this libary when
running against local Angular distributions and continue to use the
version on npm.

PR Close #19511
2017-10-06 11:56:41 -07:00
9ef8d8b85a build(aio): support ignoring dist packages in "local" mode (#19511)
PR Close #19511
2017-10-06 11:56:41 -07:00
ab8ee4d0d9 build(aio): provide cleaner scripts for local build switching (#19511)
PR Close #19511
2017-10-06 11:56:41 -07:00
d1a00459a8 ci(aio): use custom package.json to run with local distributables (#19511)
Closes #19388

PR Close #19511
2017-10-06 11:56:41 -07:00
9fe6363575 docs(aio): fix aot-compiler example to work with Angular v5 (#19511)
PR Close #19511
2017-10-06 11:56:41 -07:00
142a2b7341 build(aio): ensure webdriver is updated when switching between local and npm deps (#19511)
PR Close #19511
2017-10-06 11:56:41 -07:00
6586265a0c docs(aio): fix pipes example e2e spec to work with Angular v4 (#19511)
There was a breaking change between 4 and 5 for i18n formatting of dates.

PR Close #19511
2017-10-06 11:56:41 -07:00
d3fd088162 docs(aio): fix animations example to work with Angular v5 (#19511)
PR Close #19511
2017-10-06 11:56:40 -07:00
4b3f82a47e build(aio): upgrade ts-node to support newer TypeScript config (#19511)
This was causing `Cannot find type definition file for 'jasmine'. (2688)`
errors when running Protractor.

PR Close #19511
2017-10-06 11:56:40 -07:00
1279d75f7f fix(aio): fix SearchService to work with TypeScript 2.4 (#19511)
The call to `race` required a type parameter to disambiguate the return type.

PR Close #19511
2017-10-06 11:56:40 -07:00
81e9bdc010 docs: add changelog for 5.0.0-rc.1 2017-10-05 18:11:09 -07:00
6fa0929f3f release: cut the 5.0.0-rc.1 release 2017-10-05 18:10:01 -07:00
f10f8db5fb fix(service-worker): several misc fixes for corner cases
This commit fixes several issues discovered through use in real apps.

* The sha1() function operated on text content, causing issues for binary-format files.
  A sha1Binary() function which operates on unparsed data now avoids any encoding issues.
* The characters '?' and '+' were not escaped in Glob-to-regex conversion previously, but
  are now.
* URLs from the browser contain the full origin, but were checked against the table of
  hashes from the manifest which only has the path for URLs from the same origin. Now the
  origin is checked and URLs are relativized to the domain root before comparison if
  appropriate.
* ngsw: prefix was missing from data groups, is now added.
* Occasionally servers will return a redirected response for an asset, and caching it could
  cause errors for navigation requests. The SW now handles this by detecting such responses
  and following the redirect manually, to avoid caching a redirected response.
* The request for known assets is now created from scratch from the URL before fetching from
  the network, in order to sanitize it and avoid carrying any special modes or headers that
  might result in opaque responses.
* Debugging log for troubleshooting.
* Avoid creating errors by returning 504 responses on error.
* Fix bug where idle queue doesn't run in some circumstances.
* Add tests for the above.
2017-10-05 13:27:31 -07:00
b804d4bde5 Revert "fix(platform-browser): support customEqualityTesters when overriding Jasmine toEqual"
This reverts commit f580ffab4f.

Reason: broke a few existing tests.
2017-10-05 13:20:00 -07:00
01f711281c fix(compiler): don’t use ng:// in AOT source maps, and never point to the original source file
This is important to not confuse users nor downstream tools that
consume our source maps. For generated content for which we don’t
have an original source file, we use the generated file now.

Fixes #19538
2017-10-04 16:20:55 -07:00
5b5108363d refactor(compiler): remove stale metadata classes for animations
These are no longer needed as animations are a purely
runtime concept.
2017-10-04 16:20:55 -07:00
c80e02b881 docs(aio): document Custom Async validators
docs(aio): Custom Async validators edits

incorporating suggestions from kapunahelewong
2017-10-04 15:07:46 -07:00
fbc9537952 perf(compiler): fix perf issue in loading aot summaries in jit compiler
The current `flattenSummaries` function re-process the same NgModule
summary even if it has been processed before. Certain modules like
CommonModule are repeated multiple times in the module tree and it is
expanded out every time.

This was making unit tests using AOT summaries really slow. This will
also slow down JIT bootstrap applications that load AOT summaries for
component libraries.

The fix is to remember which summaries were seen before and not to
process them again.
2017-10-04 15:04:23 -07:00
f580ffab4f fix(platform-browser): support customEqualityTesters when overriding Jasmine toEqual 2017-10-04 15:00:58 -07:00
696af79dc7 fix(compiler): properly work on windows
Verified manually on a windows surface tablet.

Fixes #19492
2017-10-04 14:58:08 -07:00
0833b59aab refactor(core): add a checkIndex to the compiler view nodes
Each node now has two index: nodeIndex and checkIndex.

nodeIndex is the index in both the view definition and the view data.
checkIndex is the index in in the update function (update directives and update
renderer).

While nodeIndex and checkIndex have the same value for now, having both of them
will allow changing the structure of view definition after compilation (ie for
runtime translations).
2017-10-04 14:55:54 -07:00
caa51950e8 fix(compiler): only don’t emit already emitted files in incremental compilation 2017-10-04 14:55:21 -07:00
f3f4c3d835 fix(compiler): disallow references for select and index evaluation
Also fixes an issue where enum values of 0 or '``' where not treated
correctly.

Fixes: #18170
2017-10-04 14:54:39 -07:00
9ae3742565 docs(aio): fix typo in preview server config file comment 2017-10-04 12:40:28 -07:00
0f432994b8 docs(aio): document the special treatment of undefined 2017-10-04 12:40:12 -07:00
d4d9009696 docs(aio): fix broken link in toh-pt5 2017-10-04 12:39:41 -07:00
7c5ecb5b5c fix(compiler): also count generated files to determine whether to use single file emit 2017-10-03 09:57:12 -07:00
1058b2a778 fix(compiler): always emit summaries for jit with ng_module bazel rule. 2017-10-03 09:57:12 -07:00
c4129137e7 fix(compiler): set emitSkipped to false for incremental compilation 2017-10-03 09:57:12 -07:00
e3a4ecef35 docs(aio): Fix incorrect wording 2017-10-03 08:15:45 -07:00
9783c92935 build(aio): fix various API rendering issues
Upgrading to dgeni-packages 0.21.4 gives us
access to more properties on the API docs, which
allows us to fix the following issues:

Closes #19450
Closes #19452
Closes #19456
2017-10-03 08:15:02 -07:00
7cecaf2a4f docs(aio): add ngVikings to the events page 2017-10-03 08:07:53 -07:00
eef7d8aa11 fix(upgrade): call ngOnInit() after ngOnChanges() (on components with inputs)
Fixes #18913
2017-10-02 16:01:07 -07:00
617b3d2ba5 fix(upgrade): correctly run change detection when propagateDigest is false 2017-10-02 16:01:07 -07:00
546eb7d851 test(upgrade): ensure AngularJS is bootstraped inside the Angular zone in tests 2017-10-02 16:01:07 -07:00
29dbc3b67c refactor(upgrade): remove redundant call to appRef.detach()
Once  a `ViewRef` is attached to the `ApplicationRef`, destroying the corresponding `ComponentRef` will automatically detach the `ViewRef`.
2017-10-02 16:01:07 -07:00
4e6aa9c2db fix(upgrade): ensure downgraded components are destroyed in the Angular zone 2017-10-02 16:01:07 -07:00
745b59f49c perf(compiler): only emit changed files for incremental compilation
For now, we always create all generated files, but diff them
before we pass them to TypeScript.

For the user files, we compare the programs and only emit changed
TypeScript files.

This also adds more diagnostic messages if the `—diagnostics` flag
is passed to the command line.
2017-10-02 08:24:50 -07:00
b0868915ae perf(compiler): don’t emit summaries for jit by default
This re-adds the flag `enableSummariesForJit` to the compiler options
that already existed in Angular 4.
2017-10-02 08:24:50 -07:00
0038712474 fix(compiler): add typings for COMPILED.
Note: This commit has to be synced into G3 again.
2017-09-29 09:26:38 -07:00
db74f44a97 fix: don’t rely on goog.DEBUG but on COMPILED instead
`good.DEBUG` can also be true when using advanced compilation.

Attention: This change has be applied in G3 already as a local mod!
2017-09-29 09:26:38 -07:00
388 changed files with 11103 additions and 6926 deletions

View File

@ -29,7 +29,7 @@ jobs:
- restore_cache:
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
- run: yarn install
- run: yarn install --frozen-lockfile --non-interactive
- run: ./node_modules/.bin/gulp lint
build:
@ -42,6 +42,7 @@ jobs:
- run: bazel run @yarn//:yarn
- run: bazel build packages/...
- run: bazel test @angular//...
- save_cache:
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:

1
.mailmap Normal file
View File

@ -0,0 +1 @@
Michał Gołębiowski-Owczarek <m.goleb@gmail.com>

View File

@ -7,9 +7,12 @@
#
# alexeagle - Alex Eagle
# alxhub - Alex Rickabaugh
# brocco - Mike Brocchi
# chuckjaz - Chuck Jazdzewski
# filipesilva - Filipe Silva
# Foxandxss - Jesús Rodríguez
# gkalpak - George Kalpakas
# hansl - Hans Larsen
# IgorMinar - Igor Minar
# jasonaden - Jason Aden
# juleskremer - Jules Kremer
@ -101,7 +104,6 @@ groups:
- vicb
- IgorMinar #fallback
core:
conditions:
files:
@ -116,7 +118,7 @@ groups:
animations:
conditions:
files:
- "packages/animation/*"
- "packages/animations/*"
- "packages/platform-browser/animations/*"
users:
- matsko #primary
@ -145,11 +147,23 @@ groups:
- mhevery
- IgorMinar #fallback
compiler-cli/ngtools:
conditions:
files:
- "packages/compiler-cli/src/ngtools*"
users:
- hansl
- filipesilva #fallback
- brocco #fallback
compiler-cli:
conditions:
files:
- "packages/compiler-cli/*"
- "packages/bazel/*"
include:
- "packages/compiler-cli/*"
- "packages/bazel/*"
exclude:
- "packages/compiler-cli/src/ngtools*"
users:
- alexeagle
- chuckjaz
@ -255,7 +269,15 @@ groups:
- IgorMinar #fallback
- mhevery #fallback
service-worker:
conditions:
files:
- "packages/service-worker/*"
users:
- alxhub #primary
- gkalpak
- IgorMinar #fallback
- mhevery #fallback
benchpress:
conditions:

View File

@ -1,12 +1,10 @@
language: node_js
sudo: false
# force trusty as Google Chrome addon is not supported on Precise
dist: trusty
node_js:
- '6.9.5'
addons:
chrome: stable
# firefox: "38.0"
apt:
sources:
@ -50,7 +48,8 @@ env:
- CI_MODE=e2e_2
- CI_MODE=js
- CI_MODE=saucelabs_required
- CI_MODE=browserstack_required
# deactivated, see #19768
# - CI_MODE=browserstack_required
- CI_MODE=saucelabs_optional
- CI_MODE=browserstack_optional
- CI_MODE=aio_tools_test

View File

@ -12,6 +12,7 @@ filegroup(
# This won't scale in the general case.
# TODO(alexeagle): figure out what to do
srcs = glob(["/".join(["node_modules", pkg, "**", ext]) for pkg in [
"jasmine",
"typescript",
"zone.js",
"rxjs",

View File

@ -1,289 +1,109 @@
<a name="5.0.0-rc.0"></a>
# [5.0.0-rc.0](https://github.com/angular/angular/compare/5.0.0-beta.7...5.0.0-rc.0) (2017-09-28)
### Bug Fixes
* **animations:** properly support the query limit option value ([b54368b](https://github.com/angular/angular/commit/b54368b)), closes [#19232](https://github.com/angular/angular/issues/19232)
* **common:** use correct pipe name in error messages ([#19403](https://github.com/angular/angular/issues/19403)) ([f9b0863](https://github.com/angular/angular/commit/f9b0863)), closes [#19373](https://github.com/angular/angular/issues/19373)
* **compiler:** add parens around binary / ternary expressions ([3799f43](https://github.com/angular/angular/commit/3799f43))
* **compiler:** allow to use flat modules and summaries ([ec2be5d](https://github.com/angular/angular/commit/ec2be5d))
* **compiler:** allow to use lowering with `export *`. ([e31a76c](https://github.com/angular/angular/commit/e31a76c))
* **compiler:** also create `.ngfactory.js` files in non obvious cases ([#19301](https://github.com/angular/angular/issues/19301)) ([1a647c3](https://github.com/angular/angular/commit/1a647c3))
* **compiler:** collect non exported symbols in d.ts files ([#19301](https://github.com/angular/angular/issues/19301)) ([62602b9](https://github.com/angular/angular/commit/62602b9))
* **compiler:** correctly derive `fileExists` for generated files ([#19301](https://github.com/angular/angular/issues/19301)) ([f2bad19](https://github.com/angular/angular/commit/f2bad19))
* **compiler:** correctly map error message locations ([#19424](https://github.com/angular/angular/issues/19424)) ([ff5b050](https://github.com/angular/angular/commit/ff5b050))
* **compiler:** do not consider a reference with members as a reference ([#19454](https://github.com/angular/angular/issues/19454)) ([b3db3f8](https://github.com/angular/angular/commit/b3db3f8))
* **compiler:** dont lower property accesses of exported symbols ([#19301](https://github.com/angular/angular/issues/19301)) ([45747ed](https://github.com/angular/angular/commit/45747ed))
* **compiler:** dont type check property access of literal maps ([#19301](https://github.com/angular/angular/issues/19301)) ([04997c8](https://github.com/angular/angular/commit/04997c8))
* **compiler:** implement i18n with new compiler ([627f048](https://github.com/angular/angular/commit/627f048)), closes [#19429](https://github.com/angular/angular/issues/19429)
* **compiler:** make sure our out path calculation is correct ([2f6ae52](https://github.com/angular/angular/commit/2f6ae52))
* **compiler:** make sure to detect paths that start with `rootDir` correctly ([bb1665c](https://github.com/angular/angular/commit/bb1665c)), closes [#19362](https://github.com/angular/angular/issues/19362)
* **compiler:** make watch mode work with `declaration: false` ([7c1d3e0](https://github.com/angular/angular/commit/7c1d3e0)), closes [#19464](https://github.com/angular/angular/issues/19464)
* **compiler:** remove deprecated `Compiler.ngGetContentSelectors()` ([#19347](https://github.com/angular/angular/issues/19347)) ([f57b7df](https://github.com/angular/angular/commit/f57b7df))
* **compiler:** skip &nbsp; when trimming / removing whitespaces ([#19310](https://github.com/angular/angular/issues/19310)) ([13613d4](https://github.com/angular/angular/commit/13613d4)), closes [#19304](https://github.com/angular/angular/issues/19304)
* **compiler:** support `noResolve` ([#19301](https://github.com/angular/angular/issues/19301)) ([c76da27](https://github.com/angular/angular/commit/c76da27))
* **compiler:** various squashed fixes for the new ngc ([a8a9660](https://github.com/angular/angular/commit/a8a9660))
* **compiler:** work well with `forwardRef` with `useValue` / `useFactory` ([1dacae2](https://github.com/angular/angular/commit/1dacae2))
* **compiler-cli:** do not validate metadata from declaration files ([#19324](https://github.com/angular/angular/issues/19324)) ([4767902](https://github.com/angular/angular/commit/4767902)), closes [#18867](https://github.com/angular/angular/issues/18867)
* **compiler-cli:** don't join errors with comma ([#19331](https://github.com/angular/angular/issues/19331)) ([e889c68](https://github.com/angular/angular/commit/e889c68))
* **compiler-cli:** don't rewrite imports when annotating for closure ([#19444](https://github.com/angular/angular/issues/19444)) ([f24ea59](https://github.com/angular/angular/commit/f24ea59))
* create proper externs so that closure does not clobber e.g. `ng` for internal variables ([#19423](https://github.com/angular/angular/issues/19423)) ([b21a1d1](https://github.com/angular/angular/commit/b21a1d1))
* **compiler-cli:** set source file ranges in node emitter ([#19348](https://github.com/angular/angular/issues/19348)) ([27c6638](https://github.com/angular/angular/commit/27c6638))
* **compiler-cli:** update ngtools2 EmitFlags ([#19375](https://github.com/angular/angular/issues/19375)) ([e224e3d](https://github.com/angular/angular/commit/e224e3d))
* **core:** make dynamic & inline code checking behave the same ([#19189](https://github.com/angular/angular/issues/19189)) ([473a577](https://github.com/angular/angular/commit/473a577))
* **http:** introduce named type for HttpParams options ([#19360](https://github.com/angular/angular/issues/19360)) ([8a0e458](https://github.com/angular/angular/commit/8a0e458))
* **language-service:** do not report errors for `OpaqueToken` ([#19427](https://github.com/angular/angular/issues/19427)) ([c1b029a](https://github.com/angular/angular/commit/c1b029a))
* **router:** fix activation events toString and docs ([#19147](https://github.com/angular/angular/issues/19147)) ([2c4107c](https://github.com/angular/angular/commit/2c4107c))
* **router:** resolve and guards should be able to reject with null and undefined ([#19418](https://github.com/angular/angular/issues/19418)) ([a9d32a3](https://github.com/angular/angular/commit/a9d32a3)), closes [#17148](https://github.com/angular/angular/issues/17148)
* **tsc-wrapped:** deduplicate metadata only when the module is the same ([#19249](https://github.com/angular/angular/issues/19249)) ([b6b18c1](https://github.com/angular/angular/commit/b6b18c1)), closes [#19219](https://github.com/angular/angular/issues/19219)
* dont use the global `ng` at all with closure enhanced optimizations ([a7798f2](https://github.com/angular/angular/commit/a7798f2))
### Features
* **animations:** support negative query limit values ([86ffacf](https://github.com/angular/angular/commit/86ffacf)), closes [#19259](https://github.com/angular/angular/issues/19259)
* **compiler:** enabled strict checking of parameters to an `@Injectable` ([#19412](https://github.com/angular/angular/issues/19412)) ([dfb8d21](https://github.com/angular/angular/commit/dfb8d21))
* **compiler:** reuse the TypeScript typecheck for template typechecking. ([#19152](https://github.com/angular/angular/issues/19152)) ([996c7c2](https://github.com/angular/angular/commit/996c7c2))
* **core:** support for bootstrap with custom zone ([#17672](https://github.com/angular/angular/issues/17672)) ([344a5ca](https://github.com/angular/angular/commit/344a5ca))
* **platform-server:** add an API to transfer state from server ([#19134](https://github.com/angular/angular/issues/19134)) ([cfd9ca0](https://github.com/angular/angular/commit/cfd9ca0))
* **service-worker:** introduce the [@angular](https://github.com/angular)/service-worker package ([#19274](https://github.com/angular/angular/issues/19274)) ([d442b68](https://github.com/angular/angular/commit/d442b68))
### Performance Improvements
* **compiler:** make the creation of `ts.Program` faster. ([#19275](https://github.com/angular/angular/issues/19275)) ([edd5f5a](https://github.com/angular/angular/commit/edd5f5a))
* **compiler:** only use tsickle if needed ([#19275](https://github.com/angular/angular/issues/19275)) ([8f95b75](https://github.com/angular/angular/commit/8f95b75))
* **compiler:** speed up watch mode ([#19275](https://github.com/angular/angular/issues/19275)) ([6665d76](https://github.com/angular/angular/commit/6665d76))
### BREAKING CHANGES
* **compiler:** The method `ngGetConentSelectors()`, deprecated in Angular 4.0, has been removed.
Use `ComponentFactory.ngContentSelectors` instead.
<a name="4.4.4"></a>
## [4.4.4](https://github.com/angular/angular/compare/4.4.3...4.4.4) (2017-09-28)
### Bug Fixes
* **animations:** support negative query limit value ([#19419](https://github.com/angular/angular/issues/19419)) ([bc81fbd](https://github.com/angular/angular/commit/bc81fbd)), closes [#19232](https://github.com/angular/angular/issues/19232)
* **compiler:** correctly map error message locations ([#19424](https://github.com/angular/angular/issues/19424)) ([c3b39ba](https://github.com/angular/angular/commit/c3b39ba))
* **compiler:** do not consider a reference with members as a reference ([#19466](https://github.com/angular/angular/issues/19466)) ([7fc2dce](https://github.com/angular/angular/commit/7fc2dce))
* **compiler:** skip &nbsp; when trimming / removing whitespaces ([#19310](https://github.com/angular/angular/issues/19310)) ([c7aa8a1](https://github.com/angular/angular/commit/c7aa8a1)), closes [#19304](https://github.com/angular/angular/issues/19304)
* **tsc-wrapped:** add metadata for `type` declarations ([#19040](https://github.com/angular/angular/issues/19040)) ([ae52851](https://github.com/angular/angular/commit/ae52851))
<a name="4.4.3"></a>
## [4.4.3](https://github.com/angular/angular/compare/4.4.2...4.4.3) (2017-09-19)
### Bug Fixes
* **tsc-wrapped:** deduplicate metadata only when the module is the same ([#19261](https://github.com/angular/angular/issues/19261)) ([0371538](https://github.com/angular/angular/commit/0371538)), closes [#19219](https://github.com/angular/angular/issues/19219)
<a name="4.4.2"></a>
## [4.4.2](https://github.com/angular/angular/compare/4.4.1...4.4.2) (2017-09-18)
### Bug Fixes
* **platform-server**: fix for packaging issues [#19250](https://github.com/angular/angular/issues/19250)
<a name="4.4.1"></a>
## [4.4.1](https://github.com/angular/angular/compare/4.3.6...4.4.1) (2017-09-15)
### Bug Fixes
* **animations:** do not leak DOM nodes/styling for host triggered animations ([#18853](https://github.com/angular/angular/issues/18853)) ([1cc3fe2](https://github.com/angular/angular/commit/1cc3fe2)), closes [#18606](https://github.com/angular/angular/issues/18606)
* **common:** fix improper packaging for [@angular](https://github.com/angular)/common/http ([#18613](https://github.com/angular/angular/issues/18613)) ([a203a95](https://github.com/angular/angular/commit/a203a95))
* **common:** fix XSSI prefix stripping by using JSON.parse always ([#18466](https://github.com/angular/angular/issues/18466)) ([8821723](https://github.com/angular/angular/commit/8821723)), closes [#18396](https://github.com/angular/angular/issues/18396) [#18453](https://github.com/angular/angular/issues/18453)
* **compiler:** normalize the locale name ([#18963](https://github.com/angular/angular/issues/18963)) ([497e017](https://github.com/angular/angular/commit/497e017))
* **core:** complete EventEmitter in QueryList on component destroy ([#18902](https://github.com/angular/angular/issues/18902)) ([7d137d7](https://github.com/angular/angular/commit/7d137d7)), closes [#18741](https://github.com/angular/angular/issues/18741)
* **tsc-wrapped:** deduplicate metadata for re-exported modules ([48ae1a6](https://github.com/angular/angular/commit/48ae1a6))
* **tsc-wrapped:** fix metadata symbol reference ([f6a7183](https://github.com/angular/angular/commit/f6a7183))
* **upgrade:** remove code setting id attribute. ([#19182](https://github.com/angular/angular/issues/19182)) ([b20c5d2](https://github.com/angular/angular/commit/b20c5d2)), closes [#18446](https://github.com/angular/angular/issues/18446)
### Features
* **compiler:** allow multiple exportAs names ([#18723](https://github.com/angular/angular/issues/18723)) ([7ec28fe](https://github.com/angular/angular/commit/7ec28fe))
* **core:** add option to remove blank text nodes from compiled templates ([#18823](https://github.com/angular/angular/issues/18823)) ([b8b551c](https://github.com/angular/angular/commit/b8b551c))
Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1 instead. oops :-)
<a name="5.0.0-beta.7"></a>
## [5.0.0-beta.7](https://github.com/angular/angular/compare/5.0.0-beta.6...5.0.0-beta.7) (2017-09-13)
### Bug Fixes
* **compiler:** emit preamble in generated files. ([b1055a5](https://github.com/angular/angular/commit/b1055a5))
* **compiler:** fix bazel integration and make `perform-compile` more flexible ([a69172f](https://github.com/angular/angular/commit/a69172f))
* **compiler:** lower variables with a closure by exporting the variable. ([5ef6e63](https://github.com/angular/angular/commit/5ef6e63))
* **platform-browser:** run BLACK_LISTED_EVENTS outside of ngZone ([#18993](https://github.com/angular/angular/issues/18993)) ([d52f426](https://github.com/angular/angular/commit/d52f426))
* **platform-browser:** simple version of zone aware addEventListener ([#18993](https://github.com/angular/angular/issues/18993)) ([ed1175f](https://github.com/angular/angular/commit/ed1175f))
* **platform-server:** support setting innerText property ([831613a](https://github.com/angular/angular/commit/831613a))
* **router:** adjust ChildActivation events to only fire when the child is actually changing ([#19043](https://github.com/angular/angular/issues/19043)) ([66f0ab0](https://github.com/angular/angular/commit/66f0ab0)), closes [#18942](https://github.com/angular/angular/issues/18942)
* **tsc-wrapped:** deduplicate metadata for re-exported modules ([c056b8c](https://github.com/angular/angular/commit/c056b8c))
* **tsc-wrapped:** fix metadata symbol reference ([626555c](https://github.com/angular/angular/commit/626555c))
* **upgrade:** add testability hook to downgraded component ([97cc6ca](https://github.com/angular/angular/commit/97cc6ca))
* **upgrade:** remove code setting id attribute. ([b6833d1](https://github.com/angular/angular/commit/b6833d1)), closes [#18446](https://github.com/angular/angular/issues/18446)
### Code Refactoring
* **router:** remove deprecated `RouterOutlet` properties ([a9ef858](https://github.com/angular/angular/commit/a9ef858))
* update angular to support TypeScript 2.4 ([ca5aeba](https://github.com/angular/angular/commit/ca5aeba))
### Features
* **compiler:** deprecate i18n comments in favor of `ng-container` ([#18998](https://github.com/angular/angular/issues/18998)) ([66a5dab](https://github.com/angular/angular/commit/66a5dab))
* **platform-server:** provide a way to hook into renderModule* ([#19023](https://github.com/angular/angular/issues/19023)) ([8dfc3c3](https://github.com/angular/angular/commit/8dfc3c3))
* **router:** add ActivationStart/End events ([8f79150](https://github.com/angular/angular/commit/8f79150))
### BREAKING CHANGES
* - the Angular compiler now requires TypeScript 2.4.x.
* router: `RouterOutlet` properties `locationInjector` and `locationFactoryResolver` have been removed as they were deprecated since v4.
<a name="5.0.0-beta.6"></a>
## [5.0.0-beta.6](https://github.com/angular/angular/compare/5.0.0-beta.5...5.0.0-beta.6) (2017-09-03)
### Bug Fixes
* **animations:** do not leak DOM nodes/styling for host triggered animations ([#18853](https://github.com/angular/angular/issues/18853)) ([fcadeb2](https://github.com/angular/angular/commit/fcadeb2)), closes [#18606](https://github.com/angular/angular/issues/18606)
* **common:** fix a duplicate case in the locale switch ([#18941](https://github.com/angular/angular/issues/18941)) ([fdd5010](https://github.com/angular/angular/commit/fdd5010))
* **common:** fix improper packaging for [@angular](https://github.com/angular)/common/http ([#18613](https://github.com/angular/angular/issues/18613)) ([65e26d7](https://github.com/angular/angular/commit/65e26d7))
* **common:** fix XSSI prefix stripping by using JSON.parse always ([#18466](https://github.com/angular/angular/issues/18466)) ([452a7ae](https://github.com/angular/angular/commit/452a7ae)), closes [#18396](https://github.com/angular/angular/issues/18396) [#18453](https://github.com/angular/angular/issues/18453)
* **common:** update closure-locale generation for tree shaking ([#18938](https://github.com/angular/angular/issues/18938)) ([946e5bd](https://github.com/angular/angular/commit/946e5bd))
* **common:** use correct group separator for currency pipe ([#18932](https://github.com/angular/angular/issues/18932)) ([4ec5e28](https://github.com/angular/angular/commit/4ec5e28))
* **common:** use v4 plurals when importing `DeprecatedI18NPipesModule` ([#18955](https://github.com/angular/angular/issues/18955)) ([30d53a8](https://github.com/angular/angular/commit/30d53a8))
* **compiler:** always check summaries first before falling back to metadata from .d.ts files ([#18788](https://github.com/angular/angular/issues/18788)) ([f83b819](https://github.com/angular/angular/commit/f83b819))
* **compiler:** always emit ngfactories with reexports ([#18788](https://github.com/angular/angular/issues/18788)) ([0262e37](https://github.com/angular/angular/commit/0262e37))
* **compiler:** dont emit stubs when we didnt generate code for a file. ([#18788](https://github.com/angular/angular/issues/18788)) ([506d2e9](https://github.com/angular/angular/commit/506d2e9))
* **compiler:** dont reexport types in `.ngfactory` files ([#18788](https://github.com/angular/angular/issues/18788)) ([8c858d7](https://github.com/angular/angular/commit/8c858d7))
* **compiler:** normalize the locale name ([#18963](https://github.com/angular/angular/issues/18963)) ([043f104](https://github.com/angular/angular/commit/043f104))
* **compiler:** quote non identifiers in map keys. ([#18788](https://github.com/angular/angular/issues/18788)) ([2fbc92f](https://github.com/angular/angular/commit/2fbc92f))
* **compiler:** treat absolute imports as package imports ([#18912](https://github.com/angular/angular/issues/18912)) ([fce7ae1](https://github.com/angular/angular/commit/fce7ae1))
* **compiler:** use either summary or metadata information when reading .d.ts files ([#18912](https://github.com/angular/angular/issues/18912)) ([f1e526f](https://github.com/angular/angular/commit/f1e526f))
* **compiler:** workaround bugs in TS when combining transformers ([#18912](https://github.com/angular/angular/issues/18912)) ([4059a72](https://github.com/angular/angular/commit/4059a72))
* **compiler-cli:** fix memory leaks in watch mode ([#18961](https://github.com/angular/angular/issues/18961)) ([83e5deb](https://github.com/angular/angular/commit/83e5deb))
* **compiler-cli:** use `--locale` parameter for transformers ([#18988](https://github.com/angular/angular/issues/18988)) ([22c4090](https://github.com/angular/angular/commit/22c4090))
* **core:** complete EventEmitter in QueryList on component destroy ([#18902](https://github.com/angular/angular/issues/18902)) ([36d37cc](https://github.com/angular/angular/commit/36d37cc)), closes [#18741](https://github.com/angular/angular/issues/18741)
* **tsc-wrapped:** decouple bundle index host from tsickle dependency ([#18999](https://github.com/angular/angular/issues/18999)) ([d1afadb](https://github.com/angular/angular/commit/d1afadb))
* **upgrade:** deprecate the dynamic version of `ngUpgrade` ([450a13d](https://github.com/angular/angular/commit/450a13d))
### Code Refactoring
* **core:** remove deprecated `OpaqueToken` ([#18971](https://github.com/angular/angular/issues/18971)) ([3c4eef8](https://github.com/angular/angular/commit/3c4eef8))
### Features
* **http**: deprecate @angular/http in favor of @angular/common/http ([#18906](https://github.com/angular/angular/issues/18906)) ([72c7b6e](https://github.com/angular/angular/commit/72c7b6e))
* **common:** accept object map for HttpClient headers & params ([#18490](https://github.com/angular/angular/issues/18490)) ([1b1d5f1](https://github.com/angular/angular/commit/1b1d5f1))
* **common:** generate `closure-locale.ts` to tree shake locale data ([#18907](https://github.com/angular/angular/issues/18907)) ([4878936](https://github.com/angular/angular/commit/4878936))
* **compiler:** set `enableLegacyTemplate` to false by default ([#18756](https://github.com/angular/angular/issues/18756)) ([56238fe](https://github.com/angular/angular/commit/56238fe))
* **compiler-cli:** add watch mode to `ngc` ([#18818](https://github.com/angular/angular/issues/18818)) ([cf7d47d](https://github.com/angular/angular/commit/cf7d47d))
* **compiler-cli:** add watch mode to `ngc` ([#18818](https://github.com/angular/angular/issues/18818)) ([06d01b2](https://github.com/angular/angular/commit/06d01b2))
* **compiler-cli:** lower metadata `useValue` and `data` literal fields ([#18905](https://github.com/angular/angular/issues/18905)) ([0e64261](https://github.com/angular/angular/commit/0e64261))
* **compiler-cli:** lower metadata `useValue` and `data` literal fields ([#18905](https://github.com/angular/angular/issues/18905)) ([c685cc2](https://github.com/angular/angular/commit/c685cc2))
* **platform-server:** provide a DOM implementation on the server ([2f2d5f3](https://github.com/angular/angular/commit/2f2d5f3)), closes [#14638](https://github.com/angular/angular/issues/14638)
### BREAKING CHANGES
* core: `OpaqueToken` has been removed as it was deprecated since v4. Use `InjectionToken` instead.
* compiler: the compiler option `enableLegacyTemplate` is now disabled by default as the `<template>` element has been deprecated since v4. Use `<ng-template>` instead. The option `enableLegacyTemplate` and the `<template>` element will both be removed in Angular v6.
### Features
* **compiler:** allow multiple exportAs names ([#18723](https://github.com/angular/angular/issues/18723)) ([7ec28fe](https://github.com/angular/angular/commit/7ec28fe))
* **core:** add option to remove blank text nodes from compiled templates ([#18823](https://github.com/angular/angular/issues/18823)) ([b8b551c](https://github.com/angular/angular/commit/b8b551c))
<a name="5.0.0-beta.5"></a>
## [5.0.0-beta.5](https://github.com/angular/angular/compare/5.0.0-beta.4...5.0.0-beta.5) (2017-08-29)
### Bug Fixes
* **animations:** ensure animations are disabled on the element containing the @.disabled flag ([#18714](https://github.com/angular/angular/issues/18714)) ([791c7ef](https://github.com/angular/angular/commit/791c7ef))
* **animations:** make sure @.disabled respects disabled parent/sub animation sequences ([#18715](https://github.com/angular/angular/issues/18715)) ([e25f05a](https://github.com/angular/angular/commit/e25f05a))
* **animations:** make sure animation cancellations respect AUTO style values ([#18787](https://github.com/angular/angular/issues/18787)) ([29aa8b3](https://github.com/angular/angular/commit/29aa8b3)), closes [#17450](https://github.com/angular/angular/issues/17450)
* **animations:** resolve error when using AnimationBuilder with platform-server ([#18642](https://github.com/angular/angular/issues/18642)) ([845c68f](https://github.com/angular/angular/commit/845c68f)), closes [#18635](https://github.com/angular/angular/issues/18635)
* **animations:** restore auto-style support for removed DOM nodes ([#18787](https://github.com/angular/angular/issues/18787)) ([7062811](https://github.com/angular/angular/commit/7062811))
* **compiler-cli:** propagate preserveWhitespaces option to codegen ([#18773](https://github.com/angular/angular/issues/18773)) ([8ea6c56](https://github.com/angular/angular/commit/8ea6c56))
* **compiler-cli:** use forward slashes for ts.resolveModuleName ([#18784](https://github.com/angular/angular/issues/18784)) ([e228f2c](https://github.com/angular/angular/commit/e228f2c))
* **core:** correct order in ContentChildren query result ([#18326](https://github.com/angular/angular/issues/18326)) ([f53f724](https://github.com/angular/angular/commit/f53f724)), closes [#16568](https://github.com/angular/angular/issues/16568)
* **core:** make sure onStable runs in the right zone ([#18706](https://github.com/angular/angular/issues/18706)) ([713d7c2](https://github.com/angular/angular/commit/713d7c2))
* **tsc-wrapped:** add metadata for `type` declarations ([#18704](https://github.com/angular/angular/issues/18704)) ([6e3498c](https://github.com/angular/angular/commit/6e3498c)), closes [#18675](https://github.com/angular/angular/issues/18675)
* **tsc-wrapped:** make `test.sh tools` run the tsc-wrapped tests again ([#18683](https://github.com/angular/angular/issues/18683)) ([2da45e6](https://github.com/angular/angular/commit/2da45e6))
### Code Refactoring
* **common:** remove deprecated `NgFor` ([#18758](https://github.com/angular/angular/issues/18758)) ([ec56760](https://github.com/angular/angular/commit/ec56760))
* **common:** remove deprecated `NgTemplateOutlet#ngOutletContext` ([#18780](https://github.com/angular/angular/issues/18780)) ([7522987](https://github.com/angular/angular/commit/7522987))
* **compiler:** remove option `useDebug` ([#18778](https://github.com/angular/angular/issues/18778)) ([499d05d](https://github.com/angular/angular/commit/499d05d))
* **compiler:** split compiler and core ([#18683](https://github.com/angular/angular/issues/18683)) ([0cc77b4](https://github.com/angular/angular/commit/0cc77b4))
* **core:** remove deprecated `ChangeDetectionRef` argument in `DifferFactory#create` ([#18757](https://github.com/angular/angular/issues/18757)) ([be9713c](https://github.com/angular/angular/commit/be9713c))
* **core:** remove deprecated `DebugNode#source` ([#18779](https://github.com/angular/angular/issues/18779)) ([d61b902](https://github.com/angular/angular/commit/d61b902))
* **core:** remove deprecated `Testability#findBindings` ([#18782](https://github.com/angular/angular/issues/18782)) ([f2a2a6b](https://github.com/angular/angular/commit/f2a2a6b))
* **core:** remove deprecated `TrackByFn` ([#18757](https://github.com/angular/angular/issues/18757)) ([596e9f4](https://github.com/angular/angular/commit/596e9f4))
* **core:** remove deprecated parameter for `ErrorHandler` ([#18759](https://github.com/angular/angular/issues/18759)) ([8f41326](https://github.com/angular/angular/commit/8f41326))
* **platform-browser:** remove deprecated `NgProbeToken` ([#18760](https://github.com/angular/angular/issues/18760)) ([d7f42bf](https://github.com/angular/angular/commit/d7f42bf))
* **platform-webworker:** remove deprecated `PRIMITIVE` ([#18761](https://github.com/angular/angular/issues/18761)) ([a56468c](https://github.com/angular/angular/commit/a56468c))
* **router:** remove deprecated `initialNavigation` options ([#18781](https://github.com/angular/angular/issues/18781)) ([d76761b](https://github.com/angular/angular/commit/d76761b))
* **router:** remove deprecated `RouterOutlet` properties ([#18781](https://github.com/angular/angular/issues/18781)) ([d1c4a94](https://github.com/angular/angular/commit/d1c4a94))
<a name="5.0.0"></a>
# [5.0.0](https://github.com/angular/angular/compare/5.0.0-rc.9...5.0.0) pentagonal-donut (2017-11-01)
### Features
* **animations:** allow @.disabled property to work without an expression ([#18713](https://github.com/angular/angular/issues/18713)) ([2159342](https://github.com/angular/angular/commit/2159342))
* **animations:** report errors when invalid CSS properties are detected ([#18718](https://github.com/angular/angular/issues/18718)) ([409688f](https://github.com/angular/angular/commit/409688f)), closes [#18701](https://github.com/angular/angular/issues/18701)
* **animations:** support :increment and :decrement transition aliases ([6f45519](https://github.com/angular/angular/commit/6f45519))
* **animations:** support negative query limit values ([86ffacf](https://github.com/angular/angular/commit/86ffacf)), closes [#19259](https://github.com/angular/angular/issues/19259)
* **common:** accept object map for HttpClient headers & params ([#18490](https://github.com/angular/angular/issues/18490)) ([1b1d5f1](https://github.com/angular/angular/commit/1b1d5f1))
* **common:** add an empty DeprecatedI18NPipesModule module ([#18737](https://github.com/angular/angular/issues/18737)) ([83713dd](https://github.com/angular/angular/commit/83713dd))
* **common:** drop use of the Intl API to improve browser support ([#18284](https://github.com/angular/angular/issues/18284)) ([079d884](https://github.com/angular/angular/commit/079d884)), closes [#10809](https://github.com/angular/angular/issues/10809) [#9524](https://github.com/angular/angular/issues/9524) [#7008](https://github.com/angular/angular/issues/7008) [#9324](https://github.com/angular/angular/issues/9324) [#7590](https://github.com/angular/angular/issues/7590) [#6724](https://github.com/angular/angular/issues/6724) [#3429](https://github.com/angular/angular/issues/3429) [#17576](https://github.com/angular/angular/issues/17576) [#17478](https://github.com/angular/angular/issues/17478) [#17319](https://github.com/angular/angular/issues/17319) [#17200](https://github.com/angular/angular/issues/17200) [#16838](https://github.com/angular/angular/issues/16838) [#16624](https://github.com/angular/angular/issues/16624) [#16625](https://github.com/angular/angular/issues/16625) [#16591](https://github.com/angular/angular/issues/16591) [#14131](https://github.com/angular/angular/issues/14131) [#12632](https://github.com/angular/angular/issues/12632) [#11376](https://github.com/angular/angular/issues/11376) [#11187](https://github.com/angular/angular/issues/11187)
* **compiler:** allow multiple exportAs names ([3a50098](https://github.com/angular/angular/commit/3a50098))
* **common:** generate `closure-locale.ts` to tree shake locale data ([#18907](https://github.com/angular/angular/issues/18907)) ([4878936](https://github.com/angular/angular/commit/4878936))
* **common:** mark NgTemplateOutlet API as stable ([0a73e8d](https://github.com/angular/angular/commit/0a73e8d))
* **compiler-cli:** add watch mode to `ngc` ([#18818](https://github.com/angular/angular/issues/18818)) ([06d01b2](https://github.com/angular/angular/commit/06d01b2))
* **compiler-cli:** lower metadata `useValue` and `data` literal fields ([#18905](https://github.com/angular/angular/issues/18905)) ([0e64261](https://github.com/angular/angular/commit/0e64261))
* **compiler:** add representation of placeholders to xliff & xmb ([b3085e9](https://github.com/angular/angular/commit/b3085e9)), closes [#17345](https://github.com/angular/angular/issues/17345)
* **compiler:** allow multiple exportAs names ([#18723](https://github.com/angular/angular/issues/18723)) ([7ec28fe](https://github.com/angular/angular/commit/7ec28fe))
* **compiler:** deprecate i18n comments in favor of `ng-container` ([#18998](https://github.com/angular/angular/issues/18998)) ([66a5dab](https://github.com/angular/angular/commit/66a5dab))
* **compiler:** enabled strict checking of parameters to an `@Injectable` ([#19412](https://github.com/angular/angular/issues/19412)) ([dfb8d21](https://github.com/angular/angular/commit/dfb8d21))
* **compiler:** make `.ngsummary.json` files portable ([2572bf5](https://github.com/angular/angular/commit/2572bf5))
* **compiler:** reuse the TypeScript typecheck for template typechecking. ([#19152](https://github.com/angular/angular/issues/19152)) ([996c7c2](https://github.com/angular/angular/commit/996c7c2))
* **compiler:** set `enableLegacyTemplate` to false by default ([#18756](https://github.com/angular/angular/issues/18756)) ([56238fe](https://github.com/angular/angular/commit/56238fe))
* **compiler:** use typescript for resolving resource paths ([43226cb](https://github.com/angular/angular/commit/43226cb))
* **core:** Create StaticInjector which does not depend on Reflect polyfill. ([d9d00bd](https://github.com/angular/angular/commit/d9d00bd))
* **core:** add option to remove blank text nodes from compiled templates ([#18823](https://github.com/angular/angular/issues/18823)) ([b8b551c](https://github.com/angular/angular/commit/b8b551c))
* **core:** support for bootstrap with custom zone ([#17672](https://github.com/angular/angular/issues/17672)) ([344a5ca](https://github.com/angular/angular/commit/344a5ca))
* **forms:** add default updateOn values for groups and arrays ([#18536](https://github.com/angular/angular/issues/18536)) ([ff5c58b](https://github.com/angular/angular/commit/ff5c58b))
* **forms:** add options arg to abstract controls ([ebef5e6](https://github.com/angular/angular/commit/ebef5e6))
* **forms:** add status to `AbstractControlDirective` ([233ef93](https://github.com/angular/angular/commit/233ef93))
* **forms:** add updateOn and ngFormOptions to NgForm ([0d45828](https://github.com/angular/angular/commit/0d45828))
* **forms:** add updateOn blur option to FormControls ([#18408](https://github.com/angular/angular/issues/18408)) ([333a708](https://github.com/angular/angular/commit/333a708)), closes [#7113](https://github.com/angular/angular/issues/7113)
* **forms:** add updateOn submit option to FormControls ([#18514](https://github.com/angular/angular/issues/18514)) ([f69561b](https://github.com/angular/angular/commit/f69561b))
* **forms:** add updateOn support to ngModelOptions ([1cfa79c](https://github.com/angular/angular/commit/1cfa79c))
* **http**: deprecate @angular/http in favor of @angular/common/http ([#18906](https://github.com/angular/angular/issues/18906)) ([72c7b6e](https://github.com/angular/angular/commit/72c7b6e))
* **platform-server:** add an API to transfer state from server ([#19134](https://github.com/angular/angular/issues/19134)) ([cfd9ca0](https://github.com/angular/angular/commit/cfd9ca0))
* **platform-server:** provide a DOM implementation on the server ([2f2d5f3](https://github.com/angular/angular/commit/2f2d5f3)), closes [#14638](https://github.com/angular/angular/issues/14638)
* **platform-server:** provide a way to hook into renderModule* ([#19023](https://github.com/angular/angular/issues/19023)) ([8dfc3c3](https://github.com/angular/angular/commit/8dfc3c3))
* **router:** add ActivationStart/End events ([8f79150](https://github.com/angular/angular/commit/8f79150))
* **router:** add events tracking activation of individual routes ([49cd851](https://github.com/angular/angular/commit/49cd851))
* **service-worker:** introduce the [@angular](https://github.com/angular)/service-worker package ([#19274](https://github.com/angular/angular/issues/19274)) ([d442b68](https://github.com/angular/angular/commit/d442b68))
* **upgrade:** propagate touched state of NgModelController ([59c23c7](https://github.com/angular/angular/commit/59c23c7))
* **upgrade:** support lazy-loading Angular module into AngularJS app ([30e76fc](https://github.com/angular/angular/commit/30e76fc))
* update angular to support TypeScript 2.4 ([ca5aeba](https://github.com/angular/angular/commit/ca5aeba))
### Performance Improvements
* **animations:** reduce size of bundle by removing AST classes ([#19539](https://github.com/angular/angular/issues/19539)) ([d5c9c5f](https://github.com/angular/angular/commit/d5c9c5f))
* **compiler:** dont emit summaries for jit by default ([b086891](https://github.com/angular/angular/commit/b086891))
* **compiler:** fix perf issue in loading aot summaries in jit compiler ([fbc9537](https://github.com/angular/angular/commit/fbc9537))
* **compiler:** make the creation of `ts.Program` faster. ([#19275](https://github.com/angular/angular/issues/19275)) ([edd5f5a](https://github.com/angular/angular/commit/edd5f5a))
* **compiler:** only emit changed files for incremental compilation ([745b59f](https://github.com/angular/angular/commit/745b59f))
* **compiler:** only type check input files when using bazel ([#19581](https://github.com/angular/angular/issues/19581)) ([0b06ea1](https://github.com/angular/angular/commit/0b06ea1))
* **compiler:** only use tsickle if needed ([#19275](https://github.com/angular/angular/issues/19275)) ([8f95b75](https://github.com/angular/angular/commit/8f95b75))
* **compiler:** skip type check and emit in bazel in some cases. ([#19646](https://github.com/angular/angular/issues/19646)) ([a22121d](https://github.com/angular/angular/commit/a22121d))
* **compiler:** speed up loading of summaries for bazel. ([#19581](https://github.com/angular/angular/issues/19581)) ([81167d9](https://github.com/angular/angular/commit/81167d9))
* **compiler:** speed up watch mode ([#19275](https://github.com/angular/angular/issues/19275)) ([6665d76](https://github.com/angular/angular/commit/6665d76))
* **core:** Remove decorator DSL which depends on Reflect ([cac130e](https://github.com/angular/angular/commit/cac130e))
* **core:** add option to remove blank text nodes from compiled templates ([d2c0d98](https://github.com/angular/angular/commit/d2c0d98))
* **core:** use native addEventListener for faster rendering. ([#18107](https://github.com/angular/angular/issues/18107)) ([6279e50](https://github.com/angular/angular/commit/6279e50))
* latest tsickle to tree shake: abstract class methods & interfaces ([#18236](https://github.com/angular/angular/issues/18236)) ([b7a6f52](https://github.com/angular/angular/commit/b7a6f52))
* switch angular to use StaticInjector instead of ReflectiveInjector ([fcadbf4](https://github.com/angular/angular/commit/fcadbf4)), closes [#18496](https://github.com/angular/angular/issues/18496)
### BREAKING CHANGES
#### Deprecated code
* compiler: The method `ngGetContentSelectors()`, deprecated in Angular 4.0, has been removed.
Use `ComponentFactory.ngContentSelectors` instead.
* - the Angular compiler now requires TypeScript 2.4.x.
* router: `RouterOutlet` properties `locationInjector` and `locationFactoryResolver` have been removed as they were deprecated since v4.
* common: `NgFor` has been removed as it was deprecated since v4. Use `NgForOf` instead. This does not impact the use of`*ngFor` in your templates.
* common: `NgTemplateOutlet#ngOutletContext` has been removed as it was deprecated since v4. Use `NgTemplateOutlet#ngTemplateOutletContext` instead.
* core: `Testability#findBindings` has been removed as it was deprecated since v4. Use `Testability#findProviders` instead.
* core: `DebugNode#source` has been removed as it was deprecated since v4.
* router: the values `true`, `false`, `legacy_enabled` and `legacy_disabled` for the router parameter `initialNavigation` have been removed as they were deprecated. Use `enabled` or `disabled` instead.
* core: `DifferFactory.create` no longer takes ChangeDetectionRef as a first argument as it was not used and deprecated since v4.
* core: `TrackByFn` has been removed because it was deprecated since v4. Use `TrackByFunction` instead.
* platform-webworker: `PRIMITIVE` has been removed as it was deprecated since v4. Use `SerializerTypes.PRIMITIVE` instead.
* platform-browser: `NgProbeToken` has been removed from `@angular/platform-browser` as it was deprecated since v4. Import it from `@angular/core` instead.
* core: `ErrorHandler` no longer takes a parameter as it was not used and deprecated since v4.
* compiler: the option `useDebug` for the compiler has been removed as it had no effect and was deprecated since v4.
* compiler: the compiler option `enableLegacyTemplate` is now disabled by default as the `<template>` element has been deprecated since v4. Use `<ng-template>` instead. The option `enableLegacyTemplate` and the `<template>` element will both be removed in Angular v6.
* core: `OpaqueToken` has been removed as it was deprecated since v4. Use `InjectionToken` instead.
* `platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Component` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
#### I18n Changes (@angular/common)
Because of multiple bugs and browser inconsistencies, we have dropped the intl api in favor of data exported from the Unicode Common Locale Data Repository (CLDR). Unfortunately we had to change the i18n pipes (date, number, currency, percent) and there are some breaking changes.
#### Other breaking changes
* compiler: - `@angular/platform-server` now additionally depends on
`@angular/platform-browser-dynamic` as a peer dependency.
* common: Because of multiple bugs and browser inconsistencies, we have dropped the intl api in favor of data exported from the Unicode Common Locale Data Repository (CLDR).
Unfortunately we had to change the i18n pipes (date, number, currency, percent) and there are some breaking changes.
##### I18n pipes:
- Breaking change:
- By default Angular now only contains locale data for the language `en-US`, if you set the value of `LOCALE_ID` to another locale, you will have to import new locale data for this language because we don't use the intl API anymore.
@ -357,6 +177,148 @@ Unfortunately we had to change the i18n pipes (date, number, currency, percent)
- if you don't specify the number of digits to round to, the local format will be used (and it usually rounds numbers to 0 digits, instead of not rounding previously), e.g. `{{ 3.141592 | percent }}` will output `314%` for the locale `en-US` instead of `314.1592%` previously.
### Deprecated code
* router: `RouterOutlet` properties `locationInjector` and `locationFactoryResolver` have been removed as they were deprecated since v4.
* common: `NgFor` has been removed as it was deprecated since v4. Use `NgForOf` instead. This does not impact the use of`*ngFor` in your templates.
* common: `NgTemplateOutlet#ngOutletContext` has been removed as it was deprecated since v4. Use `NgTemplateOutlet#ngTemplateOutletContext` instead.
* core: `Testability#findBindings` has been removed as it was deprecated since v4. Use `Testability#findProviders` instead.
* core: `DebugNode#source` has been removed as it was deprecated since v4.
* router: the values `true`, `false`, `legacy_enabled` and `legacy_disabled` for the router parameter `initialNavigation` have been removed as they were deprecated. Use `enabled` or `disabled` instead.
* core: `DifferFactory.create` no longer takes ChangeDetectionRef as a first argument as it was not used and deprecated since v4.
* core: `TrackByFn` has been removed because it was deprecated since v4. Use `TrackByFunction` instead.
* platform-webworker: `PRIMITIVE` has been removed as it was deprecated since v4. Use `SerializerTypes.PRIMITIVE` instead.
* platform-browser: `NgProbeToken` has been removed from `@angular/platform-browser` as it was deprecated since v4. Import it from `@angular/core` instead.
* core: `ErrorHandler` no longer takes a parameter as it was not used and deprecated since v4.
* compiler: the option `useDebug` for the compiler has been removed as it had no effect and was deprecated since v4.
* common: remove deprecated `NgFor` ([#18758](https://github.com/angular/angular/issues/18758)) ([ec56760](https://github.com/angular/angular/commit/ec56760))
* common: remove deprecated `NgTemplateOutlet#ngOutletContext` ([#18780](https://github.com/angular/angular/issues/18780)) ([7522987](https://github.com/angular/angular/commit/7522987))
* compiler: remove option `useDebug` ([#18778](https://github.com/angular/angular/issues/18778)) ([499d05d](https://github.com/angular/angular/commit/499d05d))
* compiler: split compiler and core ([#18683](https://github.com/angular/angular/issues/18683)) ([0cc77b4](https://github.com/angular/angular/commit/0cc77b4))
* compiler: - `@angular/platform-server` now additionally depends on
`@angular/platform-browser-dynamic` as a peer dependency.
* core: remove deprecated `ChangeDetectionRef` argument in `DifferFactory#create` ([#18757](https://github.com/angular/angular/issues/18757)) ([be9713c](https://github.com/angular/angular/commit/be9713c))
* core: remove deprecated `DebugNode#source` ([#18779](https://github.com/angular/angular/issues/18779)) ([d61b902](https://github.com/angular/angular/commit/d61b902))
* core: remove deprecated `OpaqueToken` ([#18971](https://github.com/angular/angular/issues/18971)) ([3c4eef8](https://github.com/angular/angular/commit/3c4eef8))
* core: remove deprecated `Testability#findBindings` ([#18782](https://github.com/angular/angular/issues/18782)) ([f2a2a6b](https://github.com/angular/angular/commit/f2a2a6b))
* core: remove deprecated `TrackByFn` ([#18757](https://github.com/angular/angular/issues/18757)) ([596e9f4](https://github.com/angular/angular/commit/596e9f4))
* core: remove deprecated parameter for `ErrorHandler` ([#18759](https://github.com/angular/angular/issues/18759)) ([8f41326](https://github.com/angular/angular/commit/8f41326))
* platform-browser: remove deprecated `NgProbeToken` ([#18760](https://github.com/angular/angular/issues/18760)) ([d7f42bf](https://github.com/angular/angular/commit/d7f42bf))
* platform-webworker: remove deprecated `PRIMITIVE` ([#18761](https://github.com/angular/angular/issues/18761)) ([a56468c](https://github.com/angular/angular/commit/a56468c))
* router: remove deprecated `RouterOutlet` properties ([#18781](https://github.com/angular/angular/issues/18781)) ([d1c4a94](https://github.com/angular/angular/commit/d1c4a94))
* router: remove deprecated `RouterOutlet` properties ([a9ef858](https://github.com/angular/angular/commit/a9ef858))
* router: remove deprecated `initialNavigation` options ([#18781](https://github.com/angular/angular/issues/18781)) ([d76761b](https://github.com/angular/angular/commit/d76761b))
- `ReflectiveInjector` is now deprecated as it will be remove. Use `Injector.create` as a replacement.
<a name="4.3.1"></a>
## [4.3.1](https://github.com/angular/angular/compare/4.3.0...4.3.1) (2017-07-19)
### Bug Fixes
* **animations:** always camelcase style property names that contain auto styles ([383d896](https://github.com/angular/angular/commit/383d896)), closes [#17938](https://github.com/angular/angular/issues/17938)
* **animations:** capture cancelled animation styles within grouped animations ([333ffd8](https://github.com/angular/angular/commit/333ffd8)), closes [#17170](https://github.com/angular/angular/issues/17170)
* **animations:** do not crash animations if a nested component fires CD during CD ([4c1f32b](https://github.com/angular/angular/commit/4c1f32b)), closes [#18193](https://github.com/angular/angular/issues/18193)
* **animations:** make sure @.disabled works in non-animation components ([a5c4bb5](https://github.com/angular/angular/commit/a5c4bb5))
* **common:** send flushed body as error instead of null ([17b7bc3](https://github.com/angular/angular/commit/17b7bc3)), closes [#18181](https://github.com/angular/angular/issues/18181)
* **compiler:** ensure jit external id arguments names are unique ([4671168](https://github.com/angular/angular/commit/4671168))
* **compiler-cli:** don't generate empty `<target/>` when extracting xliff ([f0476fc](https://github.com/angular/angular/commit/f0476fc)), closes [#15754](https://github.com/angular/angular/issues/15754)
* **platform-server:** provide XhrFactory for HttpClient ([4ce29f3](https://github.com/angular/angular/commit/4ce29f3))
* **router:** canDeactivate guards should run from bottom to top ([1ac78bf](https://github.com/angular/angular/commit/1ac78bf)), closes [#15657](https://github.com/angular/angular/issues/15657)
* **router:** should navigate to the same url when config changes ([4340bea](https://github.com/angular/angular/commit/4340bea)), closes [#15535](https://github.com/angular/angular/issues/15535)
* **router:** should run resolvers for the same route concurrently ([ec89f37](https://github.com/angular/angular/commit/ec89f37)), closes [#14279](https://github.com/angular/angular/issues/14279)
* **router:** terminal route in custom matcher ([5d275e9](https://github.com/angular/angular/commit/5d275e9))
<a name="4.4.6"></a>
## [4.4.6](https://github.com/angular/angular/compare/4.4.5...4.4.6) (2017-10-18)
### Bug Fixes
* **animations:** properly support boolean-based transitions and state changes ([#19672](https://github.com/angular/angular/issues/19672)) ([f983a6c](https://github.com/angular/angular/commit/f983a6c)), closes [#9396](https://github.com/angular/angular/issues/9396) [#12337](https://github.com/angular/angular/issues/12337)
* **common:** attempt to JSON.parse errors for JSON responses ([#19773](https://github.com/angular/angular/issues/19773)) ([269f5ac](https://github.com/angular/angular/commit/269f5ac))
* **router:** RouterLinkActive should update its state right after checking the children ([53a807a](https://github.com/angular/angular/commit/53a807a)), closes [#18983](https://github.com/angular/angular/issues/18983)
### Performance Improvements
* **animations:** reduce size of bundle by removing AST classes ([#19673](https://github.com/angular/angular/issues/19673)) ([76d2496](https://github.com/angular/angular/commit/76d2496))
<a name="4.4.5"></a>
## [4.4.5](https://github.com/angular/angular/compare/4.4.4...4.4.5) (2017-10-12)
### Bug Fixes
* **compiler:** `TestBed.overrideProvider` should keep imported `NgModule`s eager ([#19624](https://github.com/angular/angular/issues/19624)) ([734378c](https://github.com/angular/angular/commit/734378c))
* **compiler:** correctly instantiate eager providers that are used via `Injector.get` ([#19558](https://github.com/angular/angular/issues/19558)) ([e292548](https://github.com/angular/angular/commit/e292548)), closes [#15501](https://github.com/angular/angular/issues/15501)
* **compiler:** disallow references for select and index evaluation ([95f3b1d](https://github.com/angular/angular/commit/95f3b1d))
* **core:** make dynamic & inline code checking behave the same ([#19189](https://github.com/angular/angular/issues/19189)) ([6c66031](https://github.com/angular/angular/commit/6c66031))
* **platform-browser:** support customEqualityTesters when overriding Jasmine toEqual ([cc8ae32](https://github.com/angular/angular/commit/cc8ae32))
* **tsc-wrapped:** don't rewrite imports when annotating for closure ([#19579](https://github.com/angular/angular/issues/19579)) ([c9f8718](https://github.com/angular/angular/commit/c9f8718))
<a name="4.4.4"></a>
## [4.4.4](https://github.com/angular/angular/compare/4.4.3...4.4.4) (2017-09-28)
### Bug Fixes
* **animations:** support negative query limit value ([#19419](https://github.com/angular/angular/issues/19419)) ([bc81fbd](https://github.com/angular/angular/commit/bc81fbd)), closes [#19232](https://github.com/angular/angular/issues/19232)
* **compiler:** correctly map error message locations ([#19424](https://github.com/angular/angular/issues/19424)) ([c3b39ba](https://github.com/angular/angular/commit/c3b39ba))
* **compiler:** do not consider a reference with members as a reference ([#19466](https://github.com/angular/angular/issues/19466)) ([7fc2dce](https://github.com/angular/angular/commit/7fc2dce))
* **compiler:** skip &nbsp; when trimming / removing whitespaces ([#19310](https://github.com/angular/angular/issues/19310)) ([c7aa8a1](https://github.com/angular/angular/commit/c7aa8a1)), closes [#19304](https://github.com/angular/angular/issues/19304)
* **tsc-wrapped:** add metadata for `type` declarations ([#19040](https://github.com/angular/angular/issues/19040)) ([ae52851](https://github.com/angular/angular/commit/ae52851))
<a name="4.4.3"></a>
## [4.4.3](https://github.com/angular/angular/compare/4.4.2...4.4.3) (2017-09-19)
### Bug Fixes
* **tsc-wrapped:** deduplicate metadata only when the module is the same ([#19261](https://github.com/angular/angular/issues/19261)) ([0371538](https://github.com/angular/angular/commit/0371538)), closes [#19219](https://github.com/angular/angular/issues/19219)
<a name="4.4.2"></a>
## [4.4.2](https://github.com/angular/angular/compare/4.4.1...4.4.2) (2017-09-18)
### Bug Fixes
* **platform-server**: fix for packaging issues [#19250](https://github.com/angular/angular/issues/19250)
<a name="4.4.1"></a>
## [4.4.1](https://github.com/angular/angular/compare/4.3.6...4.4.1) (2017-09-15)
### Bug Fixes
* **animations:** do not leak DOM nodes/styling for host triggered animations ([#18853](https://github.com/angular/angular/issues/18853)) ([1cc3fe2](https://github.com/angular/angular/commit/1cc3fe2)), closes [#18606](https://github.com/angular/angular/issues/18606)
* **common:** fix improper packaging for [@angular](https://github.com/angular)/common/http ([#18613](https://github.com/angular/angular/issues/18613)) ([a203a95](https://github.com/angular/angular/commit/a203a95))
* **common:** fix XSSI prefix stripping by using JSON.parse always ([#18466](https://github.com/angular/angular/issues/18466)) ([8821723](https://github.com/angular/angular/commit/8821723)), closes [#18396](https://github.com/angular/angular/issues/18396) [#18453](https://github.com/angular/angular/issues/18453)
* **compiler:** normalize the locale name ([#18963](https://github.com/angular/angular/issues/18963)) ([497e017](https://github.com/angular/angular/commit/497e017))
* **core:** complete EventEmitter in QueryList on component destroy ([#18902](https://github.com/angular/angular/issues/18902)) ([7d137d7](https://github.com/angular/angular/commit/7d137d7)), closes [#18741](https://github.com/angular/angular/issues/18741)
* **tsc-wrapped:** deduplicate metadata for re-exported modules ([48ae1a6](https://github.com/angular/angular/commit/48ae1a6))
* **tsc-wrapped:** fix metadata symbol reference ([f6a7183](https://github.com/angular/angular/commit/f6a7183))
* **upgrade:** remove code setting id attribute. ([#19182](https://github.com/angular/angular/issues/19182)) ([b20c5d2](https://github.com/angular/angular/commit/b20c5d2)), closes [#18446](https://github.com/angular/angular/issues/18446)
### Features
* **compiler:** allow multiple exportAs names ([#18723](https://github.com/angular/angular/issues/18723)) ([7ec28fe](https://github.com/angular/angular/commit/7ec28fe))
* **core:** add option to remove blank text nodes from compiled templates ([#18823](https://github.com/angular/angular/issues/18823)) ([b8b551c](https://github.com/angular/angular/commit/b8b551c))
Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1 instead. oops :-)
<a name="4.3.6"></a>
## [4.3.6](https://github.com/angular/angular/compare/4.3.5...4.3.6) (2017-08-23)
@ -379,31 +341,6 @@ Unfortunately we had to change the i18n pipes (date, number, currency, percent)
<a name="5.0.0-beta.4"></a>
## [5.0.0-beta.4](https://github.com/angular/angular/compare/5.0.0-beta.3...5.0.0-beta.4) (2017-08-16)
### Bug Fixes
* **compiler:** Don't strip CSS source maps ([64b4be9](https://github.com/angular/angular/commit/64b4be9))
* **forms:** re-assigning options should not clear select ([32ff21c](https://github.com/angular/angular/commit/32ff21c)), closes [#18330](https://github.com/angular/angular/issues/18330)
* **language-service:** remove tsickle dependency ([bc22ff1](https://github.com/angular/angular/commit/bc22ff1))
### Features
* **common:** mark NgTemplateOutlet API as stable ([0a73e8d](https://github.com/angular/angular/commit/0a73e8d))
* **forms:** add status to `AbstractControlDirective` ([233ef93](https://github.com/angular/angular/commit/233ef93))
* **forms:** add updateOn support to ngModelOptions ([1cfa79c](https://github.com/angular/angular/commit/1cfa79c))
### Performance Improvements
* **core:** add option to remove blank text nodes from compiled templates ([d2c0d98](https://github.com/angular/angular/commit/d2c0d98))
* **core:** Remove decorator DSL which depends on Reflect ([cac130e](https://github.com/angular/angular/commit/cac130e))
<a name="4.3.5"></a>
## [4.3.5](https://github.com/angular/angular/compare/4.3.4...4.3.5) (2017-08-16)
@ -426,89 +363,6 @@ Unfortunately we had to change the i18n pipes (date, number, currency, percent)
* **compiler:** ignore [@import](https://github.com/import) in multi-line css ([#18452](https://github.com/angular/angular/issues/18452)) ([e7e7622](https://github.com/angular/angular/commit/e7e7622)), closes [#18038](https://github.com/angular/angular/issues/18038)
<a name="5.0.0-beta.3"></a>
## [5.0.0-beta.3](https://github.com/angular/angular/compare/5.0.0-beta.2...5.0.0-beta.3) (2017-08-09)
### Bug Fixes
* **animations:** revert container/queried animations accordingly during cancel ([#18516](https://github.com/angular/angular/issues/18516)) ([c0c03dc](https://github.com/angular/angular/commit/c0c03dc))
* **animations:** support persisting dynamic styles within animation states ([#18468](https://github.com/angular/angular/issues/18468)) ([05472cb](https://github.com/angular/angular/commit/05472cb)), closes [#18423](https://github.com/angular/angular/issues/18423) [#17505](https://github.com/angular/angular/issues/17505)
* **benchpress:** compile cleanly with TS 2.4 ([#18455](https://github.com/angular/angular/issues/18455)) ([e25b3dd](https://github.com/angular/angular/commit/e25b3dd))
* **common:** don't recreate view when context shape doesn't change ([#18277](https://github.com/angular/angular/issues/18277)) ([685cc26](https://github.com/angular/angular/commit/685cc26)), closes [#13407](https://github.com/angular/angular/issues/13407)
* **compiler:** cleanly compile with TypeScript 2.4 ([#18456](https://github.com/angular/angular/issues/18456)) ([7c47b62](https://github.com/angular/angular/commit/7c47b62))
* **compiler:** ignore [@import](https://github.com/import) in multi-line css ([#18452](https://github.com/angular/angular/issues/18452)) ([1dca575](https://github.com/angular/angular/commit/1dca575)), closes [#18038](https://github.com/angular/angular/issues/18038)
* **compiler-cli:** disable buggy expression lowering ([#18513](https://github.com/angular/angular/issues/18513)) ([ca695e0](https://github.com/angular/angular/commit/ca695e0))
* **compiler-cli:** fix and re-enable expression lowering ([#18570](https://github.com/angular/angular/issues/18570)) ([6f2038c](https://github.com/angular/angular/commit/6f2038c)), closes [#18388](https://github.com/angular/angular/issues/18388)
* **compiler-cli:** modified ngc to throw all errors, not just syntax ([#18388](https://github.com/angular/angular/issues/18388)) ([5651e4a](https://github.com/angular/angular/commit/5651e4a))
* **compiler-cli:** remove minimist dependency of compiler-cli/index ([#18532](https://github.com/angular/angular/issues/18532)) ([5b7432b](https://github.com/angular/angular/commit/5b7432b))
* **core:** fix platform-browser-dynamic ([#18576](https://github.com/angular/angular/issues/18576)) ([f0a5501](https://github.com/angular/angular/commit/f0a5501))
* **core:** forbid destroyed views to be inserted or moved in VC ([#18568](https://github.com/angular/angular/issues/18568)) ([e54bd59](https://github.com/angular/angular/commit/e54bd59)), closes [#17780](https://github.com/angular/angular/issues/17780)
### Features
* **core:** Create StaticInjector which does not depend on Reflect polyfill. ([d9d00bd](https://github.com/angular/angular/commit/d9d00bd))
* **forms:** add default updateOn values for groups and arrays ([#18536](https://github.com/angular/angular/issues/18536)) ([ff5c58b](https://github.com/angular/angular/commit/ff5c58b))
* **forms:** add updateOn blur option to FormControls ([#18408](https://github.com/angular/angular/issues/18408)) ([333a708](https://github.com/angular/angular/commit/333a708)), closes [#7113](https://github.com/angular/angular/issues/7113)
* **forms:** add updateOn submit option to FormControls ([#18514](https://github.com/angular/angular/issues/18514)) ([f69561b](https://github.com/angular/angular/commit/f69561b))
### Performance Improvements
* switch angular to use StaticInjector instead of ReflectiveInjector ([fcadbf4](https://github.com/angular/angular/commit/fcadbf4)), closes [#18496](https://github.com/angular/angular/issues/18496)
### BREAKING CHANGES
* `platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Component` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
<a name="5.0.0-beta.2"></a>
## [5.0.0-beta.2](https://github.com/angular/angular/compare/5.0.0-beta.1...5.0.0-beta.2) (2017-08-02)
### Bug Fixes
* **compiler:** do not consider arguments when determining recursion ([e64b54b](https://github.com/angular/angular/commit/e64b54b))
* **compiler:** fix for element needing implicit parent placed in top-level ng-container ([381471d](https://github.com/angular/angular/commit/381471d)), closes [#18314](https://github.com/angular/angular/issues/18314)
### Features
* **forms:** add options arg to abstract controls ([ebef5e6](https://github.com/angular/angular/commit/ebef5e6))
* **router:** add events tracking activation of individual routes ([49cd851](https://github.com/angular/angular/commit/49cd851))
<a name="4.3.3"></a>
## [4.3.3](https://github.com/angular/angular/compare/4.3.2...4.3.3) (2017-08-02)
@ -517,35 +371,6 @@ DEPRECATION:
* **compiler:** fix for element needing implicit parent placed in top-level ng-container ([f5cbc2e](https://github.com/angular/angular/commit/f5cbc2e)), closes [#18314](https://github.com/angular/angular/issues/18314)
<a name="5.0.0-beta.1"></a>
## [5.0.0-beta.1](https://github.com/angular/angular/compare/5.0.0-beta.0...5.0.0-beta.1) (2017-07-27)
### Bug Fixes
* **animations:** export BrowserModule as apart of BrowserAnimationsModule ([#18263](https://github.com/angular/angular/issues/18263)) ([fd0cc01](https://github.com/angular/angular/commit/fd0cc01))
* **compiler:** add equiv & disp attributes to Xliff2 ICU placeholders ([#18283](https://github.com/angular/angular/issues/18283)) ([38ec05f](https://github.com/angular/angular/commit/38ec05f)), closes [#17344](https://github.com/angular/angular/issues/17344)
* **compiler:** allow numbers for ICU message cases in lexer ([#18095](https://github.com/angular/angular/issues/18095)) ([a3a5429](https://github.com/angular/angular/commit/a3a5429)), closes [#17799](https://github.com/angular/angular/issues/17799)
* **core:** invoke error handler outside of the Angular Zone ([#18269](https://github.com/angular/angular/issues/18269)) ([7ae7573](https://github.com/angular/angular/commit/7ae7573)), closes [#17073](https://github.com/angular/angular/issues/17073) [#7774](https://github.com/angular/angular/issues/7774)
* **platform-server:** don't clobber parse5 properties when setting ([#18237](https://github.com/angular/angular/issues/18237)) ([a094769](https://github.com/angular/angular/commit/a094769)), closes [#17050](https://github.com/angular/angular/issues/17050)
* **router:** child CanActivate guard should wait for parent to complete ([#18110](https://github.com/angular/angular/issues/18110)) ([086f4aa](https://github.com/angular/angular/commit/086f4aa)), closes [#15670](https://github.com/angular/angular/issues/15670)
* **router:** should throw when lazy loaded module doesn't define any routes ([#15001](https://github.com/angular/angular/issues/15001)) ([82923a3](https://github.com/angular/angular/commit/82923a3)), closes [#14596](https://github.com/angular/angular/issues/14596)
* **upgrade:** ensure downgraded components are created in the Angular zone ([#18209](https://github.com/angular/angular/issues/18209)) ([43c33d5](https://github.com/angular/angular/commit/43c33d5))
* **upgrade:** throw error if trying to get injector before setting ([#18209](https://github.com/angular/angular/issues/18209)) ([d31dc7b](https://github.com/angular/angular/commit/d31dc7b))
### Features
* **compiler:** add representation of placeholders to xliff & xmb ([b3085e9](https://github.com/angular/angular/commit/b3085e9)), closes [#17345](https://github.com/angular/angular/issues/17345)
### Performance Improvements
* latest tsickle to tree shake: abstract class methods & interfaces ([#18236](https://github.com/angular/angular/issues/18236)) ([b7a6f52](https://github.com/angular/angular/commit/b7a6f52))
* **core:** use native addEventListener for faster rendering. ([#18107](https://github.com/angular/angular/issues/18107)) ([6279e50](https://github.com/angular/angular/commit/6279e50))
<a name="4.3.2"></a>
## [4.3.2](https://github.com/angular/angular/compare/4.3.1...4.3.2) (2017-07-26)
@ -563,35 +388,6 @@ DEPRECATION:
<a name="5.0.0-beta.0"></a>
## [5.0.0-beta.0](https://github.com/angular/angular/compare/4.3.0...5.0.0-beta.0) (2017-07-19)
### Bug Fixes
* **animations:** always camelcase style property names that contain auto styles ([d22f8f5](https://github.com/angular/angular/commit/d22f8f5)), closes [#17938](https://github.com/angular/angular/issues/17938)
* **animations:** capture cancelled animation styles within grouped animations ([23146c9](https://github.com/angular/angular/commit/23146c9)), closes [#17170](https://github.com/angular/angular/issues/17170)
* **animations:** do not crash animations if a nested component fires CD during CD ([5db6f38](https://github.com/angular/angular/commit/5db6f38)), closes [#18193](https://github.com/angular/angular/issues/18193)
* **animations:** make sure @.disabled works in non-animation components ([5344be5](https://github.com/angular/angular/commit/5344be5))
* **common:** send flushed body as error instead of null ([5c62e30](https://github.com/angular/angular/commit/5c62e30)), closes [#18181](https://github.com/angular/angular/issues/18181)
* **compiler:** ensure jit external id arguments names are unique ([95635c1](https://github.com/angular/angular/commit/95635c1))
* **compiler-cli:** don't generate empty <target/> when extracting xliff ([65c9e13](https://github.com/angular/angular/commit/65c9e13)), closes [#15754](https://github.com/angular/angular/issues/15754)
* **platform-server:** provide XhrFactory for HttpClient ([8076482](https://github.com/angular/angular/commit/8076482))
* **router:** canDeactivate guards should run from bottom to top ([e20cfe1](https://github.com/angular/angular/commit/e20cfe1)), closes [#15657](https://github.com/angular/angular/issues/15657)
* **router:** should navigate to the same url when config changes ([eb6fb5f](https://github.com/angular/angular/commit/eb6fb5f)), closes [#15535](https://github.com/angular/angular/issues/15535)
* **router:** should run resolvers for the same route concurrently ([ad3029e](https://github.com/angular/angular/commit/ad3029e)), closes [#14279](https://github.com/angular/angular/issues/14279)
* **router:** terminal route in custom matcher ([b399cb2](https://github.com/angular/angular/commit/b399cb2))
* **upgrade:** allow accessing AngularJS injector from downgraded module ([a5205c6](https://github.com/angular/angular/commit/a5205c6))
### Features
* **animations:** support :increment and :decrement transition aliases ([6f45519](https://github.com/angular/angular/commit/6f45519))
* **upgrade:** propagate touched state of NgModelController ([59c23c7](https://github.com/angular/angular/commit/59c23c7))
* **upgrade:** support lazy-loading Angular module into AngularJS app ([30e76fc](https://github.com/angular/angular/commit/30e76fc))
<a name="4.3.1"></a>
## [4.3.1](https://github.com/angular/angular/compare/4.3.0...4.3.1) (2017-07-19)

View File

@ -220,6 +220,7 @@ The following is the list of supported scopes:
* **platform-webworker**
* **platform-webworker-dynamic**
* **router**
* **service-worker**
* **upgrade**
There are currently a few exceptions to the "use package name" rule:

View File

@ -5,7 +5,8 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
git_repository(
name = "build_bazel_rules_nodejs",
remote = "https://github.com/bazelbuild/rules_nodejs.git",
tag = "0.1.6",
# TODO(alexeagle): use the correct tag here.
commit = "2c6243df53fd33fdab283ebdd01582e4eb815db8",
)
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
@ -20,4 +21,4 @@ local_repository(
local_repository(
name = "angular",
path = "packages/bazel",
)
)

View File

@ -156,7 +156,7 @@ RUN find $AIO_SCRIPTS_SH_DIR -maxdepth 1 -type f -printf "%P\n" \
# Set up the Node.js scripts
COPY scripts-js/ $AIO_SCRIPTS_JS_DIR/
WORKDIR $AIO_SCRIPTS_JS_DIR/
RUN yarn install --production
RUN yarn install --production --frozen-lockfile
# Set up health check

View File

@ -6,7 +6,7 @@ server=8.8.4.4
# Listen for DHCP and DNS requests only on this address.
listen-address=127.0.0.1
# Force an IP addres for these domains.
# Force an IP address for these domains.
address=/{{$AIO_NGINX_HOSTNAME}}/127.0.0.1
address=/{{$AIO_UPLOAD_HOSTNAME}}/127.0.0.1
address=/{{$TEST_AIO_NGINX_HOSTNAME}}/127.0.0.1

View File

@ -9,7 +9,7 @@ VM host to update the preview server based on changes in the source code.
The script will pull the latest changes from the origin's master branch and examine if there have
been any changes in files inside the preview server source code directory (see below). If there are,
it will create a new image and verify that is works as expected. Finally, it will stop and remove
the old docker container and image, create and new container based on the new image and start it.
the old docker container and image, create a new container based on the new image and start it.
The script assumes that the preview server source code is in the repository's
`aio/aio-builds-setup/` directory and expects the following inputs:

View File

@ -9,7 +9,7 @@ readonly defaultImageNameAndTag="aio-builds:latest"
# (Necessary, because only `scripts-js/dist/` is copied to the docker image.)
(
cd "$SCRIPTS_JS_DIR"
yarn install
yarn install --frozen-lockfile --non-interactive
yarn build
)

View File

@ -7,6 +7,6 @@ source "`dirname $0`/_env.sh"
# Test `scripts-js/`
(
cd "$SCRIPTS_JS_DIR"
yarn install
yarn install --frozen-lockfile --non-interactive
yarn test
)

View File

@ -2,6 +2,7 @@
**/src/environments/environment.prod.ts
**/src/environments/environment.ts
**/src/assets/.gitkeep
**/src/favicon.ico
**/src/styles.css
**/src/systemjs-angular-loader.js
**/src/systemjs.config.js
@ -29,11 +30,7 @@
# built files
*.map
_test-output
protractor-helpers.js
*/e2e-spec.js
**/*.js
**/ts/**/*.js
**/js-es6*/**/*.js
dist/
@ -57,10 +54,10 @@ dist/
**/app/**/*.ajs.js
# aot
*/aot/**/*
!*/aot/bs-config.json
!*/aot/index.html
**/*.ngsummary.json
!rollup-config.js
aot-compiler/**/*.d.ts
aot-compiler/**/*.factory.d.ts
# i18n
!i18n/src/systemjs-text-plugin.js
@ -76,6 +73,10 @@ dist/
# styleguide
!styleguide/src/systemjs.custom.js
# universal
!universal/webpack.config.client.js
!universal/webpack.config.universal.js
# plunkers
*plnkr.no-link.html

View File

@ -335,17 +335,17 @@ describe('Animation Tests', () => {
});
}
function getBoundingClientWidth(el: ElementFinder): promise.Promise<number> {
function getBoundingClientWidth(el: ElementFinder) {
return browser.executeScript(
'return arguments[0].getBoundingClientRect().width',
el.getWebElement()
);
) as PromiseLike<number>;
}
function getOffsetWidth(el: ElementFinder): promise.Promise<number> {
function getOffsetWidth(el: ElementFinder) {
return browser.executeScript(
'return arguments[0].offsetWidth',
el.getWebElement()
);
) as PromiseLike<number>;
}
});

View File

@ -5,9 +5,6 @@
<title>Animations</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Polyfill for Web Animations -->
<script src="https://unpkg.com/web-animations-js@2.2.1"></script>
</head>
<body>

View File

@ -7,7 +7,7 @@ import uglify from 'rollup-plugin-uglify';
export default {
entry: 'src/main.js',
dest: 'src/build.js', // output a single application bundle
sourceMap: false,
sourceMap: true,
format: 'iife',
onwarn: function(warning) {
// Skip certain warnings

View File

@ -1,6 +1,6 @@
// #docregion
import { platformBrowser } from '@angular/platform-browser';
import { AppModuleNgFactory } from '../aot/src/app/app.module.ngfactory';
import { AppModuleNgFactory } from './app/app.module.ngfactory';
console.log('Running AOT compiled');
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

View File

@ -20,7 +20,8 @@
],
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}
"annotationsAs": "decorators",
"genDir": ".",
"skipMetadataEmit" : true
}
}

View File

@ -12,8 +12,10 @@ describe('Component Style Tests', function () {
let componentH1 = element(by.css('app-root > h1'));
let externalH1 = element(by.css('body > h1'));
expect(componentH1.getCssValue('fontWeight')).toEqual('normal');
expect(externalH1.getCssValue('fontWeight')).not.toEqual('normal');
// Note: sometimes webdriver returns the fontWeight as "normal",
// othertimes as "400", both of which are equal in CSS terms.
expect(componentH1.getCssValue('fontWeight')).toMatch(/normal|400/);
expect(externalH1.getCssValue('fontWeight')).not.toMatch(/normal|400/);
});

View File

@ -1,6 +1,7 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
const { version: angularVersion } = require('@angular/core/package.json');
describe('Pipes', function () {
@ -28,7 +29,11 @@ describe('Pipes', function () {
it('should be able to toggle birthday formats', function () {
let birthDayEle = element(by.css('app-hero-birthday2 > p'));
expect(birthDayEle.getText()).toEqual(`The hero's birthday is 4/15/88`);
if (angularVersion.indexOf('4.') === 0) { // Breaking change between v4 and v5 (https://github.com/angular/angular/commit/079d884)
expect(birthDayEle.getText()).toEqual(`The hero's birthday is 4/15/1988`);
} else {
expect(birthDayEle.getText()).toEqual(`The hero's birthday is 4/15/88`);
}
let buttonEle = element(by.cssContainingText('app-hero-birthday2 > button', 'Toggle Format'));
expect(buttonEle.isDisplayed()).toBe(true);
buttonEle.click().then(function() {

View File

@ -0,0 +1,3 @@
{
"projectType": "systemjs"
}

View File

@ -1,62 +0,0 @@
{
"name": "toh-universal",
"version": "1.0.0",
"description": "Tour-of-Heroes application with ng-universal server-side rendering",
"scripts": {
"build": "tsc -p src/",
"build:watch": "tsc -w",
"build:aot": "webpack --config webpack.config.aot.js",
"build:uni": "webpack --config webpack.config.uni.js",
"serve": "lite-server -c=bs-config.json",
"serve:aot": "lite-server -c=bs-config.aot.js",
"serve:uni": "node src/dist/server.js",
"serve:uni2": "lite-server -c bs-config.uni.js",
"prestart": "npm run build",
"start": "concurrently \"npm run build:watch\" \"npm run serve\"",
"lint": "tslint ./src/**/*.ts -t verbose",
"ngc": "ngc",
"clean": "rimraf src/dist && rimraf src/app/*.js* && rimraf src/uni/*.js* && rimraf src/main.js*"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@angular/common": "angular/common-builds",
"@angular/compiler": "angular/compiler-builds",
"@angular/compiler-cli": "angular/compiler-cli-builds",
"@angular/core": "angular/core-builds",
"@angular/forms": "angular/forms-builds",
"@angular/http": "angular/http-builds",
"@angular/platform-browser": "angular/platform-browser-builds",
"@angular/platform-browser-dynamic": "angular/platform-browser-dynamic-builds",
"@angular/platform-server": "angular/platform-server-builds",
"@angular/router": "angular/router-builds",
"angular-in-memory-web-api": "^0.3.1",
"systemjs": "0.19.40",
"core-js": "^2.4.1",
"rxjs": "5.1.1",
"zone.js": "^0.7.7"
},
"devDependencies": {
"concurrently": "^3.2.0",
"lite-server": "^2.2.2",
"typescript": "~2.1.6",
"canonical-path": "0.0.2",
"tslint": "^3.15.1",
"lodash": "^4.16.4",
"rimraf": "^2.5.4",
"@types/node": "^6.0.46",
"@ngtools/webpack": "^1.2.11",
"@types/express": "^4.0.35",
"raw-loader": "^0.5.1",
"webpack": "^2.2.1"
},
"repository": {}
}

View File

@ -9,7 +9,8 @@ const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'detail/:id', component: HeroDetailComponent },
{ path: 'heroes', component: HeroesComponent }
{ path: 'heroes', component: HeroesComponent },
{ path: '**', redirectTo: '/dashboard' }
];
@NgModule({

View File

@ -1,4 +1,3 @@
/* #docregion */
h1 {
font-size: 1.2em;
color: #999;

View File

@ -1,5 +1,3 @@
// #docplaster
// #docregion
import { Component } from '@angular/core';
@Component({

View File

@ -1,54 +1,62 @@
// #docplaster
// #docregion
// #docregion v1, v2
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
// #docregion simple
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
// #enddocregion v1
// Imports for loading & configuring the in-memory web api
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './in-memory-data.service';
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './in-memory-data.service';
// #docregion v1
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroService } from './hero.service';
// #enddocregion v1, v2
import { HeroSearchComponent } from './hero-search.component';
// #docregion v1, v2
// #enddocregion simple
// #docregion platform-detection
import { PLATFORM_ID, APP_ID, Inject } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
// #enddocregion platform-detection
// #docregion simple
@NgModule({
imports: [
BrowserModule.withServerTransition({
appId: 'toh-universal'
}),
// #docregion browsermodule
BrowserModule.withServerTransition({ appId: 'uni' }),
// #enddocregion browsermodule
FormsModule,
HttpModule,
// #enddocregion v1
// #docregion in-mem-web-api
InMemoryWebApiModule.forRoot(InMemoryDataService),
// #enddocregion in-mem-web-api
// #docregion v1
HttpClientModule,
HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService),
AppRoutingModule
],
// #docregion search
declarations: [
AppComponent,
DashboardComponent,
HeroDetailComponent,
HeroesComponent,
// #enddocregion v1, v2
HeroSearchComponent
// #docregion v1, v2
],
// #enddocregion search
providers: [ HeroService ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
export class AppModule {
// #enddocregion simple
// #docregion platform-detection
constructor(
@Inject(PLATFORM_ID) private platformId: Object,
@Inject(APP_ID) private appId: string) {
const platform = isPlatformBrowser(platformId) ?
'on the server' : 'in the browser';
console.log(`Running ${platform} with appId=${appId}`);
}
// #enddocregion platform-detection
// #docregion simple
}
// #enddocregion simple

View File

@ -1,4 +1,3 @@
/* #docregion */
[class*='col-'] {
float: left;
padding-right: 20px;

View File

@ -1,7 +1,6 @@
<!-- #docregion -->
<h3>Top Heroes</h3>
<div class="grid grid-pad">
<a *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]" class="col-1-4">
<a *ngFor="let hero of heroes | async" [routerLink]="['/detail', hero.id]" class="col-1-4">
<div class="module hero">
<h4>{{hero.name}}</h4>
</div>

View File

@ -1,22 +1,23 @@
// #docregion , search
import { Component, OnInit } from '@angular/core';
import { Hero } from './hero';
import { HeroService } from './hero.service';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
@Component({
selector: 'my-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: [ './dashboard.component.css' ]
})
// #enddocregion search
export class DashboardComponent implements OnInit {
heroes: Hero[] = [];
heroes: Observable<Hero[]>;
constructor(private heroService: HeroService) { }
ngOnInit(): void {
this.heroService.getHeroes()
.then(heroes => this.heroes = heroes.slice(1, 5));
this.heroes = this.heroService.getHeroes()
.map(heroes => heroes.slice(1, 5));
}
}

View File

@ -1,4 +1,3 @@
/* #docregion */
label {
display: inline-block;
width: 3em;
@ -25,6 +24,6 @@ button:hover {
}
button:disabled {
background-color: #eee;
color: #ccc;
color: #ccc;
cursor: auto;
}

View File

@ -1,4 +1,3 @@
<!-- #docregion -->
<div *ngIf="hero">
<h2>{{hero.name}} details!</h2>
<div>
@ -8,7 +7,5 @@
<input [(ngModel)]="hero.name" placeholder="name" />
</div>
<button (click)="goBack()">Back</button>
<!-- #docregion save -->
<button (click)="save()">Save</button>
<!-- #enddocregion save -->
</div>

View File

@ -1,4 +1,3 @@
// #docregion
import 'rxjs/add/operator/switchMap';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
@ -27,12 +26,11 @@ export class HeroDetailComponent implements OnInit {
.subscribe(hero => this.hero = hero);
}
// #docregion save
save(): void {
this.heroService.update(this.hero)
.then(() => this.goBack());
this.heroService
.update(this.hero)
.subscribe(() => this.goBack());
}
// #enddocregion save
goBack(): void {
this.location.back();

View File

@ -1,4 +1,3 @@
/* #docregion */
.search-result{
border-bottom: 1px solid gray;
border-left: 1px solid gray;

View File

@ -1,4 +1,3 @@
<!-- #docregion -->
<div id="search-component">
<h4>Hero Search</h4>
<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />

View File

@ -1,20 +1,14 @@
// #docplaster
// #docregion
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
// #docregion rxjs-imports
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
// Observable class extensions
import 'rxjs/add/observable/of';
// Observable operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
// #enddocregion rxjs-imports
import { HeroSearchService } from './hero-search.service';
import { Hero } from './hero';
@ -26,27 +20,20 @@ import { Hero } from './hero';
providers: [HeroSearchService]
})
export class HeroSearchComponent implements OnInit {
// #docregion search
heroes: Observable<Hero[]>;
// #enddocregion search
// #docregion searchTerms
private searchTerms = new Subject<string>();
// #enddocregion searchTerms
constructor(
private heroSearchService: HeroSearchService,
private router: Router) {}
// #docregion searchTerms
// Push a search term into the observable stream.
search(term: string): void {
this.searchTerms.next(term);
}
// #enddocregion searchTerms
// #docregion search
ngOnInit(): void {
this.heroes = this.searchTerms
this.heroes = this.searchTerms.asObservable()
.debounceTime(300) // wait 300ms after each keystroke before considering the term
.distinctUntilChanged() // ignore if next search term is same as previous
.switchMap(term => term // switch to new observable each time the term changes
@ -60,7 +47,6 @@ export class HeroSearchComponent implements OnInit {
return Observable.of<Hero[]>([]);
});
}
// #enddocregion search
gotoDetail(hero: Hero): void {
let link = ['/detail', hero.id];

View File

@ -1,20 +1,28 @@
// #docregion
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Inject, Injectable, Optional } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { Hero } from './hero';
import { Hero } from './hero';
// #docregion class
@Injectable()
export class HeroSearchService {
constructor(private http: Http) {}
private searchUrl = 'api/heroes/?name='; // URL to web api
constructor(
private http: HttpClient,
@Optional() @Inject(APP_BASE_HREF) origin: string) {
this.searchUrl = (origin || '') + this.searchUrl;
}
search(term: string): Observable<Hero[]> {
return this.http
.get(`api/heroes/?name=${term}`)
.map(response => response.json().data as Hero[]);
.get(this.searchUrl + term)
.map((data: any) => data.data as Hero[]);
}
}
// #enddocregion class

View File

@ -1,87 +1,64 @@
// #docplaster
// #docregion , imports
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import { Injectable, Inject, Optional } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { HttpHeaders, HttpClient } from '@angular/common/http';
// #docregion rxjs
import 'rxjs/add/operator/toPromise';
// #enddocregion rxjs
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import { Hero } from './hero';
// #enddocregion imports
const headers = new HttpHeaders({'Content-Type': 'application/json'});
@Injectable()
export class HeroService {
// #docregion update
private headers = new Headers({'Content-Type': 'application/json'});
// #enddocregion update
// #docregion getHeroes
private heroesUrl = 'api/heroes'; // URL to web api
constructor(private http: Http) { }
// #docregion ctor
constructor(
private http: HttpClient,
@Optional() @Inject(APP_BASE_HREF) origin: string) {
this.heroesUrl = (origin || '') + this.heroesUrl;
}
// #enddocregion ctor
getHeroes(): Promise<Hero[]> {
getHeroes(): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
// #docregion to-promise
.toPromise()
// #enddocregion to-promise
// #docregion to-data
.then(response => response.json().data as Hero[])
// #enddocregion to-data
// #docregion catch
.map((data: any) => data.data as Hero[])
.catch(this.handleError);
// #enddocregion catch
}
// #enddocregion getHeroes
// #docregion getHero
getHero(id: number): Promise<Hero> {
getHero(id: number): Observable<Hero> {
const url = `${this.heroesUrl}/${id}`;
return this.http.get(url)
.toPromise()
.then(response => response.json().data as Hero)
.map((data: any) => data.data as Hero)
.catch(this.handleError);
}
// #enddocregion getHero
// #docregion delete
delete(id: number): Promise<void> {
delete(id: number): Observable<void> {
const url = `${this.heroesUrl}/${id}`;
return this.http.delete(url, {headers: this.headers})
.toPromise()
.then(() => null)
return this.http.delete(url, { headers })
.catch(this.handleError);
}
// #enddocregion delete
// #docregion create
create(name: string): Promise<Hero> {
create(name: string): Observable<Hero> {
return this.http
.post(this.heroesUrl, JSON.stringify({name: name}), {headers: this.headers})
.toPromise()
.then(res => res.json().data)
.post(this.heroesUrl, { name: name }, { headers })
.map((data: any) => data.data)
.catch(this.handleError);
}
// #enddocregion create
// #docregion update
update(hero: Hero): Promise<Hero> {
update(hero: Hero): Observable<Hero> {
const url = `${this.heroesUrl}/${hero.id}`;
return this.http
.put(url, JSON.stringify(hero), {headers: this.headers})
.toPromise()
.then(() => hero)
.put(url, hero, { headers })
.catch(this.handleError);
}
// #enddocregion update
// #docregion getHeroes, handleError
private handleError(error: any): Promise<any> {
private handleError(error: any): Observable<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
throw error;
}
// #enddocregion getHeroes, handleError
}

View File

@ -21,31 +21,27 @@ export class HeroesComponent implements OnInit {
getHeroes(): void {
this.heroService
.getHeroes()
.then(heroes => this.heroes = heroes);
.subscribe(heroes => this.heroes = heroes);
}
// #docregion add
add(name: string): void {
name = name.trim();
if (!name) { return; }
this.heroService.create(name)
.then(hero => {
.subscribe(hero => {
this.heroes.push(hero);
this.selectedHero = null;
});
}
// #enddocregion add
// #docregion delete
delete(hero: Hero): void {
this.heroService
.delete(hero.id)
.then(() => {
.subscribe(() => {
this.heroes = this.heroes.filter(h => h !== hero);
if (this.selectedHero === hero) { this.selectedHero = null; }
});
}
// #enddocregion delete
ngOnInit(): void {
this.getHeroes();

View File

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>Angular Tour of Heroes</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<my-app>Loading...</my-app>
</body>
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.min.js"></script>
<script src="dist/build.js"></script>
</html>

View File

@ -0,0 +1,22 @@
<!-- #docregion -->
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>Angular Universal Tour of Heroes</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="styles.css">
<script src="shim.min.js"></script>
<script src="zone.min.js"></script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
<!-- #docregion client-app-bundle -->
<script src="client.js"></script>
<!-- #enddocregion client-app-bundle -->
</html>

View File

@ -4,19 +4,20 @@
<head>
<base href="/">
<title>Angular Universal Tour of Heroes</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="styles.css">
<!-- Polyfills -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('main.js').catch(function(err){ console.error(err); });
System.import('main.js')
.catch(function(err){ console.error(err); });
</script>
</head>

View File

@ -1,5 +0,0 @@
// #docregion
import { platformBrowser } from '@angular/platform-browser';
import { AppModuleNgFactory } from '../aot/src/app/app.module.ngfactory';
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

View File

@ -1,40 +0,0 @@
import 'zone.js/dist/zone-node';
import { enableProdMode } from '@angular/core';
// import { AppServerModule } from './app.server';
import { AppServerModuleNgFactory } from '../../aot/src/uni/app.server.ngfactory';
import * as express from 'express';
import { ngUniversalEngine } from './universal-engine';
enableProdMode();
const server = express();
// set our angular engine as the handler for html files, so it will be used to render them.
server.engine('html', ngUniversalEngine({
bootstrap: [AppServerModuleNgFactory]
}));
// set default view directory
server.set('views', 'src');
// handle requests for routes in the app. ngExpressEngine does the rendering.
server.get(['/', '/dashboard', '/heroes', '/detail/:id'], (req, res) => {
res.render('index-aot.html', {req});
});
// handle requests for static files
server.get(['/*.js', '/*.css'], (req, res, next) => {
let fileName: string = req.originalUrl;
console.log(fileName);
let root = fileName.startsWith('/node_modules/') ? '.' : 'src';
res.sendFile(fileName, { root: root }, function (err) {
if (err) {
next(err);
}
});
});
// start the server
server.listen(3200, () => {
console.log('listening on port 3200...');
});

View File

@ -1,38 +0,0 @@
/**
* Express/Connect middleware for rendering pages using Angular Universal
*/
import * as fs from 'fs';
import { renderModuleFactory } from '@angular/platform-server';
const templateCache = {}; // cache for page templates
const outputCache = {}; // cache for rendered pages
export function ngUniversalEngine(setupOptions: any) {
return function (filePath: string, options: { req: Request }, callback: (err: Error, html: string) => void) {
let url: string = options.req.url;
let html: string = outputCache[url];
if (html) {
// return already-built page for this url
console.log('from cache: ' + url);
callback(null, html);
return;
}
console.log('building: ' + url);
if (!templateCache[filePath]) {
let file = fs.readFileSync(filePath);
templateCache[filePath] = file.toString();
}
// render the page via angular platform-server
let appModuleFactory = setupOptions.bootstrap[0];
renderModuleFactory(appModuleFactory, {
document: templateCache[filePath],
url: url
}).then(str => {
outputCache[url] = str;
callback(null, str);
});
};
}

View File

@ -1,21 +1,19 @@
// #docregion
import { NgModule } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { ServerModule } from '@angular/platform-server';
import { AppComponent } from '../app/app.component';
import { AppModule } from '../app/app.module';
@NgModule({
imports: [
AppModule,
ServerModule,
AppModule
],
providers: [
// Add universal-only providers here
],
bootstrap: [
AppComponent
],
providers: [
{provide: APP_BASE_HREF, useValue: '/'}
// { provide: NgModuleFactoryLoader, useClass: ServerRouterLoader }
]
})
export class AppServerModule {
}
export class AppServerModule {}

View File

@ -0,0 +1,68 @@
// Express Server for Angular Universal app
import 'zone.js/dist/zone-node';
import * as express from 'express';
import { enableProdMode } from '@angular/core';
// #docregion import-app-server-factory
// AppServerModuleNgFactory, generated by AOT webpack plug-in,
// exists in-memory during build.
// It is not available in the file system at design time
import { AppServerModuleNgFactory } from '../../aot/src/universal/app-server.module.ngfactory';
// #enddocregion import-app-server-factory
import { universalEngine } from './universal-engine';
enableProdMode();
const port = 3200;
const server = express();
// #docregion universal-engine
// Render HTML files with the universal template engine
server.engine('html', universalEngine({
appModuleFactory: AppServerModuleNgFactory
}));
// engine should find templates in 'dist/' by default
server.set('views', 'dist');
// #enddocregion universal-engine
// CRITICAL TODO: add authentication/authorization middleware
// #docregion data-request
// TODO: implement data requests securely
server.get('/api/*', (req, res) => {
res.status(404).send('data requests are not supported');
});
// #enddocregion data-request
// #docregion navigation-request
// simplistic regex matches any path without a '.'
const pathWithNoExt = /^([^.]*)$/;
// treat any path without an extension as in-app navigation
server.get(pathWithNoExt, (req, res) => {
// render with the universal template engine
res.render('index-universal.html', { req });
});
// #enddocregion navigation-request
// #docregion static
// remaining requests are for static files
server.use((req, res, next) => {
const fileName = req.originalUrl;
console.log(fileName);
// security: only serve files from dist
const root = 'dist';
res.sendFile(fileName, { root }, err => {
if (err) { next(err); }
});
});
// #enddocregion static
// start the server
server.listen(port, () => {
console.log(`listening on port ${port}...`);
});

View File

@ -0,0 +1,49 @@
/**
* Node Express template engine for Universal apps
*/
import * as fs from 'fs';
import { Request } from 'express';
import { renderModuleFactory } from '@angular/platform-server';
import { APP_BASE_HREF } from '@angular/common';
const templateCache: { [key: string]: string } = {}; // page templates
export function universalEngine(setupOptions: any) {
// Express template engine middleware
return function (
filePath: string,
options: { req: Request },
callback: (err: Error, html: string) => void) {
const { req } = options;
const routeUrl = req.url;
let template = templateCache[filePath];
if (!template) {
template = fs.readFileSync(filePath).toString();
templateCache[filePath] = template;
}
const { appModuleFactory } = setupOptions;
const origin = getOrigin(req);
// #docregion render
// render the page
renderModuleFactory(appModuleFactory, {
document: template,
url: routeUrl,
extraProviders: [
{ provide: APP_BASE_HREF, useValue: origin }
]
})
.then(page => callback(null, page));
// #enddocregion render
};
}
function getOrigin(req: Request) {
// e.g., http://localhost:3200/
return `${req.protocol}://${req.hostname}:${req.connection.address().port}/`;
}

View File

@ -1,27 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es2015", "dom"],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
]
},
"files": [
"src/uni/app.server.ts",
"src/uni/server-aot.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"entryModule": "./src/app/app.module#AppModule",
"skipMetadataEmit" : true
}
}

View File

@ -0,0 +1,13 @@
{
"extends": "./tsconfig.universal.json",
"files": [
"src/main.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"entryModule": "./src/app/app.module#AppModule",
"skipMetadataEmit" : true
}
}

View File

@ -15,8 +15,8 @@
},
"files": [
"src/app/app.module.ts",
"src/main-aot.ts"
"src/universal/app-server.module.ts",
"src/universal/server.ts"
],
"angularCompilerOptions": {

View File

@ -0,0 +1,34 @@
// #docregion
const ngtools = require('@ngtools/webpack');
const webpack = require('webpack');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
devtool: 'source-map',
entry: {
main: [ './src/main.ts' ]
},
resolve: {
extensions: ['.ts', '.js']
},
output: {
path: __dirname + '/dist',
filename: 'client.js'
},
plugins: [
// compile with AOT
new ngtools.AotPlugin({
tsConfigPath: './tsconfig.client.json'
}),
// minify
new UglifyJSPlugin()
],
module: {
rules: [
{ test: /\.css$/, loader: 'raw-loader' },
{ test: /\.html$/, loader: 'raw-loader' },
{ test: /\.ts$/, loader: '@ngtools/webpack' }
]
}
}

View File

@ -0,0 +1,43 @@
// #docregion
const ngtools = require('@ngtools/webpack');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
devtool: 'source-map',
entry: {
main: [
'./src/universal/app-server.module.ts',
'./src/universal/server.ts'
]
},
resolve: {
extensions: ['.ts', '.js']
},
target: 'node',
output: {
path: __dirname + '/dist',
filename: 'server.js'
},
plugins: [
// compile with AOT
new ngtools.AotPlugin({
tsConfigPath: './tsconfig.universal.json'
}),
// copy assets to the output (/dist) folder
new CopyWebpackPlugin([
{from: 'src/index-universal.html'},
{from: 'src/styles.css'},
{from: 'node_modules/core-js/client/shim.min.js'},
{from: 'node_modules/zone.js/dist/zone.min.js'},
])
],
module: {
rules: [
{ test: /\.css$/, loader: 'raw-loader' },
{ test: /\.html$/, loader: 'raw-loader' },
{ test: /\.ts$/, loader: '@ngtools/webpack' }
]
}
}

View File

@ -0,0 +1,9 @@
{
"files":[
"!dist/",
"!**/*.d.ts",
"!**/src/**/*.js"
],
"removeSystemJsConfig": false,
"type": "universal"
}

View File

@ -7,3 +7,4 @@
<p>We're sorry. The page you are looking for cannot be found.</p>
</div>
</div>
<aio-file-not-found-search></aio-file-not-found-search>

View File

@ -16,9 +16,7 @@ animation logic with the rest of your application code, for ease of control.
Angular animations are built on top of the standard [Web Animations API](https://w3c.github.io/web-animations/)
and run natively on [browsers that support it](http://caniuse.com/#feat=web-animation).
For other browsers, a polyfill is required. Grab
[`web-animations.min.js` from GitHub](https://github.com/web-animations/web-animations-js) and
add it to your page.
For other browsers, a polyfill is required. Uncomment the `web-animations-js` polyfill from the `polyfills.ts` file.
</div>

View File

@ -139,6 +139,10 @@ null if the control value is valid _or_ a validation error object.
The validation error object typically has a property whose name is the validation key, `'forbiddenName'`,
and whose value is an arbitrary dictionary of values that you could insert into an error message, `{name}`.
Custom async validators are similar to sync validators, but they must instead return a Promise or Observable
that later emits null or a validation error object. In the case of an Observable, the Observable must complete,
at which point the form uses the last value emitted for validation.
### Adding to reactive forms
In reactive forms, custom validators are fairly simple to add. All you have to do is pass the function directly

View File

@ -139,7 +139,7 @@ Now the extractor tool and compiler will generate a translation unit with _your
<code-example path="i18n/src/locale/messages.es.xlf.html" region="custom-id" linenums="false">
</code-example>
Here is the `i18n` attribute with a _definition_, followed by the custom `id`:
Here is the `i18n` attribute with a _description_, followed by the custom `id`:
<code-example path='i18n/src/app/app.component.1.html' region='i18n-attribute-id' title='app/app.component.html' linenums="false">
</code-example>

View File

@ -4502,8 +4502,8 @@ helps instantly identify which members of the component serve which purpose.
**Why?** The property associated with `@HostBinding` or the method associated with `@HostListener`
can be modified only in a single place&mdash;in the directive's class.
If you use the `host` metadata property, you must modify both the property declaration inside the controller,
and the metadata associated with the directive.
If you use the `host` metadata property, you must modify both the property/method declaration in the
directive's class and the metadata in the decorator associated with the directive.
</div>

View File

@ -142,7 +142,7 @@ The `hero` in `{{hero.name}}`
refers to the template input variable, not the component's property.
Template expressions cannot refer to anything in
the global namespace. They can't refer to `window` or `document`. They
the global namespace (except `undefined`). They can't refer to `window` or `document`. They
can't call `console.log` or `Math.max`. They are restricted to referencing
members of the expression context.

View File

@ -0,0 +1,853 @@
# Angular Universal: server-side rendering
This guide describes **Angular Universal**, a technology that runs your Angular application on the server.
<div class="alert is-important">
This is a **preview guide**.
The Angular CLI is adding support for universal apps and
we will realign this guide with the CLI as soon as possible.
</div>
A normal Angular application executes in the _browser_, rendering pages in the DOM in response to user actions.
**Angular Universal** generates _static_ application pages on the _server_
through a process called **server-side rendering (SSR)**.
It can generate and serve those pages in response to requests from browsers.
It can also pre-generate pages as HTML files that you serve later.
This guide describes a Universal sample application that launches quickly as a server-rendered page.
Meanwhile, the browser downloads the full client version and switches to it automatically after the code loads.
<div class="l-sub-section">
[Download the finished sample code](generated/zips/universal/universal.zip),
which runs in a [node express](https://expressjs.com/) server.
</div>
{@a why-do-it}
### Why Universal
There are three main reasons to create a Universal version of your app.
1. Facilitate web crawlers (SEO)
1. Improve performance on mobile and low-powered devices
1. Show the first page quickly
{@a seo}
{@a web-crawlers}
#### Facilitate web crawlers
Google, Bing, Facebook, Twitter and other social media sites rely on web crawlers to index your application content and make that content searchable on the web.
These web crawlers may be unable to navigate and index your highly-interactive, Angular application as a human user could do.
Angular Universal can generate a static version of your app that is easy searchable, linkable, and navigable without JavaScript.
It also makes a site preview available since each URL returns a fully-rendered page.
Enabling web crawlers is often referred to as
[Search Engine Optimization (SEO)](https://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf).
{@a no-javascript}
#### Performance on mobile and low performance devices
Some devices don't support JavaScript or execute JavaScript so poorly that the user experience is unacceptable.
For these cases, you may require a server-rendered, no-JavaScript version of the app.
This version, however limited, may be the only practical alternative for
people who otherwise would not be able to use the app at all.
{@a startup-performance}
#### Show the first page quickly
Displaying the first page quickly can be critical for user engagement.
[53% of mobile site visits are abandoned](https://www.doubleclickbygoogle.com/articles/mobile-speed-matters/) if pages take longer than 3 seconds to load.
Your app may have to launch faster to engage these users before they decide to do something else.
With Angular Universal, you can generate landing pages for the app that look like the complete app.
The pages are pure HTML, and can display even if JavaScript is disabled.
The pages do not handle browser events, but they _do_ support navigation through the site using [routerLink](guide/router.html#router-link).
In practice, you'll serve a static version of the landing page to hold the user's attention.
At the same time, you'll load the full Angular app behind it in the manner [explained below](#transition).
The user perceives near-instant performance from the landing page
and gets the full interactive experience after the full app loads.
{@a how-does-it-work}
### How it works
To make a Universal app, you install the `platform-server` package.
The `platform-server` package has server implementations of the DOM, `XMLHttpRequest`, and other low-level features that do not rely on a browser.
You compile the client application with the `platform-server` module instead of the `platform-browser` module.
and run the resulting Universal app on a web server.
The server (a [Node Express](https://expressjs.com/) server in _this_ guide's example)
passes client requests for application pages to Universal's `renderModuleFactory` function.
The `renderModuleFactory` function takes as inputs a *template* HTML page (usually `index.html`),
an Angular *module* containing components,
and a *route* that determines which components to display.
The route comes from the client's request to the server.
Each request results in the appropriate view for the requested route.
The `renderModuleFactory` renders that view within the `<app>` tag of the template, creating a finished HTML page for the client.
Finally, the server returns the rendered page to the client.
### Working around the browser APIs
Because a Universal `platform-server` app doesn't execute in the browser, you may have to work around some of the browser APIs and capabilities that are missing on the server.
You won't be able reference browser-only native objects such as `window`, `document`, `navigator` or `location`.
If you don't need them on the server-rendered page, side-step them with conditional logic.
Alternatively, look for an injectable Angular abstraction over the object you need such as `Location` or `Document`;
it may substitute adequately for the specific API that you're calling.
If Angular doesn't provide it, you may be able to write your own abstraction that delegates to the browser API while in the browser and to a satisfactory alternative implementation while on the server.
Without mouse or keyboard events, a universal app can't rely on a user clicking a button to show a component.
A universal app should determine what to render based solely on the incoming client request.
This is a good argument for making the app [routeable](guide/router).
Because the user of a server-rendered page can't do much more than click links,
you should [swap in the real client app](#transition) as quickly as possible for a proper interactive experience.
{@a the-example}
## The example
The _Tour of Heroes_ tutorial is the foundation for the Universal sample described in this guide.
The core application files are mostly untouched, with a few exceptions described below.
You'll add more files to support building and serving with Universal.
In this example, Webpack tools compile and bundle the Universal version of the app with the
[AOT (Ahead-of-Time) compiler](guide/aot-compiler).
A node/express web server turns client requests into the HTML pages rendered by Universal.
You will create:
* a server-side app module, `app.server.module.ts`
* a Universal app renderer, `universal-engine.ts`
* an express web server to handle requests, `server.ts`
* a TypeScript config file, `tsconfig.universal.json`
* a Webpack config file, `webpack.config.universal.js`
When you're done, the folder structure will look like this:
<code-example format="." language="none" linenums="false">
src/
index.html <i>app web page</i>
index-universal.html <i>* universal app web page template</i>
main.ts <i>bootstrapper for client app</i>
style.css <i>styles for the app</i>
systemjs.config.js <i>SystemJS client configuration</i>
systemjs-angular-loader.js <i>SystemJS add-in</i>
tsconfig.json <i>TypeScript client configuration</i>
app/ ... <i>application code</i>
dist/ <i>* Post-build files</i>
client.js <i>* AOT-compiled client bundle</i>
server.js <i>* express server & universal app bundle</i>
index-universal.html <i>* copy of the app web page template</i>
... <i>* copies of other asset files</i>
universal/ <i>* folder for universal code</i>
app-server.module.ts <i>* server-side application module</i>
server.ts <i>* express web server</i>
universal-engine.ts <i>* express template engine</i>
bs-config.json <i>config file for lite server</i>
package.json <i>npm configuration</i>
tsconfig.client.json <i>* TypeScript client AOT configuration</i>
tsconfig.universal.json <i>* TypeScript Universal configuration</i>
webpack.config.aot.js <i>* Webpack client AOT configuration</i>
webpack.config.universal.js <i>* Webpack Universal configuration</i>
</code-example>
The files marked with `*` are new and not in the original tutorial sample.
This guide covers them in the sections below.
{@a preparation}
## Preparation
{@a install-the-tools}
### Install the tools
To get started, install these Universal and Webpack packages.
* `@angular/compiler-cli` - contains the AOT compiler.
* `@angular/platform-server` - Universal server-side components.
* `webpack` - Webpack JavaScript bundler.
* `@ngtools/webpack` - Webpack loader and plugin for bundling compiled applications.
* `copy-webpack-plugin` - Webpack plugin to copy asset files to the output folder.
* `raw-loader` - Webpack loader for text files.
* `express` - node web server.
* `@types/express` - TypeScript type definitions for express.
Install them with the following commands:
<code-example format="." language="bash">
npm install @angular/compiler-cli @angular/platform-server express --save
npm install webpack @ngtools/webpack copy-webpack-plugin raw-loader @types/express --save-dev
</code-example>
{@a transition}
### Modify the client app
A Universal app can act as a dynamic, content-rich "splash screen" that engages the user.
It gives the appearance of a near-instant application.
Meanwhile, the browser downloads the client app scripts in background.
Once loaded, Angular transitions from the static server-rendered page to the dynamically rendered views of the interactive client app.
You must make a few changes to your application code to support both server-side rendering and the transition to the client app.
#### The root `AppModule`
Open file `src/app/app.module.ts` and find the `BrowserModule` import in the `NgModule` metadata.
Replace that import with this one:
<code-example path="universal/src/app/app.module.ts" region="browsermodule" title="src/app/app.module.ts (withServerTransition)">
</code-example>
Angular adds the `appId` value (which can be _any_ string) to the style-names of the server-rendered pages,
so that they can be identified and removed when the client app starts.
You can get runtime information about the current platform and the `appId` by injection.
<code-example path="universal/src/app/app.module.ts" region="platform-detection" title="src/app/app.module.ts (platform detection)">
</code-example>
{@a http-urls}
#### Absolute HTTP URLs
The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `Http` module to fetch application data.
These services send requests to _relative_ URLs such as `api/heroes`.
In a Universal app, `Http` URLs must be _absolute_ (e.g., `https://my-server.com/api/heroes`)
even when the Universal web server is capable of handling those requests.
You'll have to change the services to make requests with absolute URLs when running on the server
and with relative URLs when running in the browser.
One solution is to provide the server's runtime origin under the Angular [`APP_BASE_REF` token](api/common/APP_BASE_HREF),
inject it into the service, and prepend the origin to the request URL.
Start by changing the `HeroService` constructor to take a second `origin` parameter that is optionally injected via the `APP_BASE_HREF` token.
<code-example path="universal/src/app/hero.service.ts" region="ctor" title="src/app/hero.service.ts (constructor with optional origin)">
</code-example>
Note how the constructor prepends the origin (if it exists) to the `heroesUrl`.
You don't provide `APP_BASE_HREF` in the browser version, so the `heroesUrl` remains relative.
<div class="l-sub-section">
You can ignore `APP_BASE_HREF` in the browser if you've specified `<base href="/">` in the `index.html`
to satisfy the router's need for a base address, as the tutorial sample does.
</div>
You will provide the `APP_BASE_HREF` in the universal version of the app (see how [below](#provide-origin)),
so the `heroesUrl` becomes absolute.
Do the same thing to the `HttpSearchService` constructor.
You'll have to adjust the `http.get` call in the `search()` method as well.
Here's the revised class.
<code-example path="universal/src/app/hero-search.service.ts" region="class" title="src/app/hero-search.service.ts (with injected origin)" linenums="false">
</code-example>
{@a build-client-app}
#### Try locally first
Open a terminal window and confirm that the client app still works in the browser.
<code-example format="." language="bash">
npm start
</code-example>
When you are done, shut down the server with `ctrl-C`.
<div class="alert is-important">
If you get a "Cannot find module" error, see the explanation and resolution [below](#cannot-find-module)
</div>
<hr>
{@a server-code}
## Server code
To run an Angular Universal application, you'll need a server that accepts client requests and returns rendered pages.
Create a `universal/` folder as a sibling to the `app/` folder.
Add to it the following three universal parts:
1. the [app server module](#app-server-module)
2. the [Universal engine](#universal-engine)
3. the [web server](#web-server)
{@a app-server-module}
### App server module
The app server module class (conventionally named `AppServerModule`) is an Angular module that wraps the application's root module (`AppModule`) so that Universal can mediate between your application and the server.
`AppServerModule` also tells Angular how to bootstrap your application when running as a Universal app.
Create an `app-server.module.ts` file in the `src/universal` directory with the following `AppServerModule` code:
<code-example path="universal/src/universal/app-server.module.ts" title="src/universal/app-server.module.ts">
</code-example>
Notice that it imports first the client app's `AppModule` and then Angular Universal's `ServerModule`.
This is also the place to register providers that are specific to running your app under Universal.
{@a universal-engine}
### Universal template engine
The Universal `renderModuleFactory` function turns a client's requests into server-rendered HTML pages.
You'll call that function within a _template engine_ that's appropriate for your server stack.
This guide's sample is written for [Node Express](https://expressjs.com/)
so the engine takes the form of [Express template engine middleware](https://expressjs.com/en/guide/using-template-engines.html).
Create a `universal-engine.ts` file in the `src/universal` directory with the following code.
<code-example path="universal/src/universal/universal-engine.ts" title="src/universal/universal-engine.ts">
</code-example>
{@a render-module-factory}
#### Rendering the page
The call to Universal's `renderModuleFactory` is where the rendering magic happens.
<code-example path="universal/src/universal/universal-engine.ts" title="src/universal/universal-engine.ts (rendering)" region="render">
</code-example>
The first parameter is the `AppServerModule` that you wrote [earlier](#app-server-module).
It's the bridge between the Universal server-side renderer and your application.
The second parameter is an options object
* `document` is the template for the page to render (typically `index.html`).
* `url` is the application route (e.g., `/dashboard`), extracted from the client's request.
Universal should render the appropriate page for that route.
* `extraProviders` are optional Angular dependency injection providers, applicable when running on this server
{@a provide-origin}
You supply `extraProviders` when your app needs information that can only be determined by the currently running server instance.
The required information in this case is the running server's origin, provided under the `APP_BASE_HREF` token, so that the app can [calculate absolute HTTP URLs](#http-urls).
The `renderModuleFactory` function returns a _promise_ that resolves to the rendered page.
It's up to your engine to decide what to do with that page.
_This engine's_ promise callback returns the rendered page to the [web server](#web-server),
which then forwards it to the client in the HTTP response.
{@a web-server}
### Universal web server
A _Universal_ web server responds to application _page_ requests with static HTML rendered by the [Universal template engine](#universal-engine).
It receives and responds to HTTP requests from clients (usually browsers).
It serves static assets such as scripts, css, and images.
It may respond to data requests, perhaps directly or as a proxy to a separate data server.
The sample web server for _this_ guide is based on the popular [Express](https://expressjs.com/) framework.
<div class="l-sub-section">
_Any_ web server technology can serve a Universal app as long as it can call Universal's `renderModuleFactory`.
The principles and decision points discussed below apply to any web server technology that you chose.
</div>
Create a `server.ts` file in the `src/universal` directory and add the following code:
<code-example path="universal/src/universal/server.ts" title="src/universal/server.ts">
</code-example>
<div class="alert is-critical">
**This sample server is not secure!**
Be sure to add middleware to authenticate and authorize users
just as you would for a normal Angular application server.
</div>
{@a import-app-server-module-factory}
#### Import AppServerModule factory
Most of this server code is re-usable across many applications.
The import of the `AppServerModule` couples it specifically to a single application.
<code-example path="universal/src/universal/server.ts" title="src/universal/server.ts" region="import-app-server-factory">
</code-example>
Your code editor may tell you that this import is incorrect.
It refers to the source file for the `AppServerModule` factory which doesn't exist at design time.
That file _will exist_, briefly, during compilation. But it's never physically in the file system when you're editing `server.ts` and you must tell the compiler to generate this module factory file _before_ it compiles `server.ts`.
[Learn how below](#universal-typescript-configuration).
#### Add the Universal template engine
Express supports template engines such as the [Universal template engine](#universal-engine) you wrote earlier.
You import that engine and register it with Express like this:
<code-example path="universal/src/universal/server.ts" title="src/universal/server.ts (Universal template engine)" region="universal-engine">
</code-example>
#### Filter request URLs
The web server must distinguish _app page requests_ from other kinds of requests.
It's not as simple as intercepting a request to the root address `/`.
The browser could ask for one of the application routes such as `/dashboard`, `/heroes`, or `/detail:12`.
In fact, if the app were _only_ rendered by the server, _every_ app link clicked would arrive at the server
as a navigation URL intended for the router.
Fortunately, application routes have something in common: their URLs lack file extensions.
Data requests also lack extensions but they're easy to recognize because they always begin with `/api`.
All static asset requests have a file extension (e.g., `main.js` or `/node_modules/zone.js/dist/zone.js`).
So we can easily recognize the three types of requests and handle them differently.
1. data request - request URL that begins `/api`
2. app navigation - request URL with no file extension
3. static asset - all other requests.
An Express server is a pipeline of middleware that filters and processes URL requests one after the other.
You configure the Express server pipeline with calls to `server.get()` like this one for data requests.
<code-example path="universal/src/universal/server.ts" title="src/universal/server.ts (data URL)" region="data-request" linenums="false">
</code-example>
<div class="l-sub-section">
This sample server doesn't handle data requests.
The tutorial's "in-memory web api" module, a demo and development tool, intercepts all HTTP calls and
simulates the behavior of a remote data server.
In practice, you would remove that module and register your web api middleware on the server here.
</div>
<div class="alert is-critical">
**Universal HTTP requests have different security requirements**
HTTP requests issued from a browser app are not the same as when issued by the universal app on the server.
When a browser makes an HTTP request, the server can make assumptions about cookies, XSRF headers, etc.
For example, the browser automatically sends auth cookies for the current user.
Angular Universal cannot forward these credentials to a separate data server.
If your server handles HTTP requests, you'll have to add your own security plumbing.
</div>
The following code filters for request URLs with no extensions and treats them as navigation requests.
<code-example path="universal/src/universal/server.ts" title="src/universal/server.ts (navigation)" region="navigation-request" linenums="false">
</code-example>
#### Serve static files safely
A single `server.use()` treats all other URLs as requests for static assets
such as JavaScript, image, and style files.
To ensure that clients can only download the files that they are _permitted_ to see, you will [put all client-facing asset files in the `/dist` folder](#universal-webpack-configuration)
and will only honor requests for files from the `/dist` folder.
The following express code routes all remaining requests to `/dist`; it returns a `404 - NOT FOUND` if the file is not found.
<code-example path="universal/src/universal/server.ts" title="src/universal/server.ts (static files)" region="static" linenums="false">
</code-example>
{@a universal-configuration}
## Configure for Universal
The server application requires its own web page and its own build configuration.
{@a index-universal}
### Universal web page
The universal app renders pages based on a host web page template.
Simple universal apps make do with a slightly modified copy of the original `index.html`.
<div class="alert is-helpful">
If you build a production version of the client app with the CLI's `ng build --prod` command, you do not need a separate universal `index.html`.
The CLI constructs a suitable `index.html` for you. You can skip this subsection and continue to [universal TypeScript configuration](#universal-typescript-configuration).
Read on if you're building the app without the CLI.
</div>
Create an `index-universal.html` as follows, shown next to the development `index.html` for comparison.
<code-tabs>
<code-pane title="src/index-universal.html" path="universal/src/index-universal.html">
</code-pane>
<code-pane title="src/index.html" path="universal/src/index.html">
</code-pane>
</code-tabs>
The differences are few.
* Load the minified versions of the `shim` and `zone` polyfills from the root (which will be `/dist`)
* You won't use SystemJS for universal nor to load the client app.
* Instead you'll load the [production version of the client app](#build-client), `client.js`, which is the result of AOT compilation, minification, and bundling.
That's it for `index-universal.html`.
Next you'll create two universal configuration files, one for TypeScript and one for Webpack.
{@a universal-typescript-configuration}
### Universal TypeScript configuration
Create a `tsconfig.universal.json` file in the project root directory to configure TypeScript and AOT compilation of the universal app.
<code-example path="universal/tsconfig.universal.json" title="tsconfig.universal.json">
</code-example>
Certain settings are noteworthy for their difference from the `tsconfig.json` in the `src/` folder.
* The `module` property must be **es2015** because
the transpiled JavaScript will use `import` statements instead of `require()` calls.
* Point `"typeRoots"` to `"./node_modules/@types/"`
* Set the `files` property (instead of `exclude`) to compile the `app-server.module` before the `universal-engine`,
for the reason [explained above](#import-app-server-module-factory).
* The `angularCompilerOptions` section guides the AOT compiler:
* `genDir` - the temporary output directory for AOT compiled code.
* `entryModule` - the root module of the client application, expressed as `path/to/file#ClassName`.
* `skipMetadataEmit` - set `true` because you don't need metadata in the bundled application.
### Universal Webpack configuration
Create a `webpack.config.universal.js` file in the project root directory with the following code.
<code-example path="universal/webpack.config.universal.js" title="webpack.config.universal.js">
</code-example>
**Webpack configuration** is a rich topic beyond the scope of this guide.
A few observations may clarify some of the choices.
* Webpack walks the dependency graph from the two entry points to find all necessary universal application files.
* The `@ngtools/webpack` loader loads and prepares the TypeScript files for compilation.
* The `AotPlugin` runs the AOT compiler (`ngc`) over the prepared TypeScript, guided by the `tsconfig.universal.json` you created [above](#universal-typescript-configuration).
* The `raw-loader` loads imported CSS and HTML files as strings.
You may need additional loaders or configuration for other file types.
* The compiled output is bundled into `dist/server.js`.
* The `CopyWebpackPlugin` copies specific static files from their source locations into the `/dist` folder.
These files include the universal app's web page template, `index-universal.html`,
and the JavaScript and CSS files mentioned in it
... with the notable exception of `client.js` [to be discussed below](#build-client).
<div class="alert is-helpful">
The `CopyWebpackPlugin` step is unnecessary if you [build the client](#build-client) with the CLI.
</div>
## Build and run with universal
Now that you've created the TypeScript and Webpack config files, you can build and run the Universal application.
First add the _build_ and _serve_ commands to the `scripts` section of the `package.json`:
<code-example format="." language="ts">
"scripts": {
...
"build:uni": "webpack --config webpack.config.universal.js",
"serve:uni": "node dist/server.js",
...
}
</code-example>
{@a build}
#### Build
From the command prompt, type
<code-example format="." language="bash">
npm run build:uni
</code-example>
Webpack compiles and bundles the universal app into a single output file, `dist/server.js`, per the [configuration above](#universal-configuration).
It also generates a [source map](https://webpack.js.org/configuration/devtool/), `dist/server.js.map` that correlates the bundle code to the source code.
Source maps are primarily for the browser's [dev tools](https://developers.google.com/web/tools/chrome-devtools/javascript/source-maps), but on the server they help locate compilation errors in your components.
{@a serve}
#### Serve
After building the server bundle, start the server.
<code-example format="." language="bash">
npm run serve:uni
</code-example>
The console window should say
<code-example format="." language="bash">
listening on port 3200...
</code-example>
## Universal in action
Open a browser to http://localhost:3200/.
You should see the familiar Tour of Heroes dashboard page.
Navigation via `routerLinks` works correctly.
You can go from the Dashboard to the Heroes page and back.
You can click on a hero on the Dashboard page to display its Details page.
But clicks, mouse-moves, and keyboard entries are inert.
* Clicking a hero on the Heroes page does nothing.
* You can't add or delete a hero.
* The search box on the Dashboard page is ignored.
* The _back_ and _save_ buttons on the Details page don't work.
User events other than `routerLink` clicks aren't supported.
The user must wait for the full client app to arrive.
It will never arrive until you compile the client app
and move the output into the `dist/` folder,
a step you'll take in just a moment.
#### Review the console log
Open the browser's development tools.
In the console window you should see output like the following:
<code-example format="." language="bash" linenums="false">
listening on port 3200...
Running in the browser with appId=uni
/styles.css
/shim.min.js
/zone.min.js
/client.js
Error: ENOENT: no such file or directory, stat '... dist/client.js' ...
</code-example>
Most of the console log lines report requests for static files coming from the `<link>` and `<script>` tags in the `index-universal.html`.
The `.js` files in particular are needed to run the client version of the app in the browser.
Once they're loaded, Angular _should_ replace the Universal-rendered page with the full client app.
Except that it didn't!
#### Missing _client.js_ error
Note the error at the bottom of the console log that complains about a missing `client.js` file.
<code-example format="." language="bash">
Error: ENOENT: no such file or directory, stat '... dist/client.js' ...
</code-example>
The full client app doesn't launch because `client.js` doesn't exist.
And `client.js` doesn't exist because you have not yet built the client version of the app.
{@a build-client}
## Build the client app
The express server is sending the universal server-side rendered pages to the client.
But it isn't serving the interactive client app because you haven't built it yet.
A key motivation for universal is to quickly render the first page on the client so of course
you want to transition to the client app as quickly as possible too.
You should build a small, _production_ version of the client app with that AOT compiler that loads and runs fast.
#### Build the client with the CLI
If you're using the CLI to build the client app, you simply run the following command and you're done.
<code-example format="." language="bash">
ng build --prod
</code-example>
The CLI takes care of the rest, including copying all necessary files to the `/dist` folder.
By default the CLI produces two separate client app bundles, one with the vendor packages (`vendor.bundle.js`) and one with your application code (`inline.bundle.js`).
Alternatively, you can build the client using CLI _tools_ but **_without the CLI itself_**.
Read the following sub-sections if that interests you.
If not, skip ahead to the section on [throttling](#throttling).
#### Build the client by hand
You can build the application without the considerable help of the CLI.
You'll still compile with AOT.
You'll still bundle and minify with Webpack.
You'll need two configuration files, just as you did for the universal server: one for TypeScript and one for Webpack.
The client app versions are only slightly different from the corresponding server files.
Here they are, followed by notes that call out the differences:
<code-tabs>
<code-pane title="tsconfig.client.json" path="universal/tsconfig.client.json">
</code-pane>
<code-pane title="webpack.config.client.js" path="universal/webpack.config.client.js">
</code-pane>
</code-tabs>
The **_tsconfig.client.json_** inherits (via `extends`) most settings from the universal `tsconfig`. The _only_ substantive difference is in the `files` section which identifies the client app bootstrapping file, `main.ts`, from which the compiler discovers all other required files.
The **_webpack.config.client.js_** has a few differences,
all of them obvious.
* There is only one `entry.main` file, `main.ts`.
* The output filename is `client.js`.
* The `AotPlugin` references the `./tsconfig.client.json`.
* There's no need to copy asset files because the [universal Webpack config](#universal-webpack-configuration)
took care of them.
* Add the `UglifyJSPlugin` to minify the client app code.
Why minify the client code and not the server code?
You minify client code to reduce the payload transmitted to the browser. The universal server code stays on the server where minification is pointless.
#### Run Webpack for the client
Add an `npm` script to make it easy to build the client from the terminal window.
<code-example format="." language="ts">
"scripts": {
...
"build:uni-client": "webpack --config webpack.config.client.js",
...
}
</code-example>
Now run that command
<code-example format="." language="bash">
npm run build:uni-client
</code-example>
Refresh the browser.
The console log shows that the server can find `client.js`
The Universal app is quickly replaced by the full client app.
Most importantly, the event-based features now work as expected.
<div class="alert is-critical">
When you make application changes, remember to rebuild _both_ the universal server _and_ the client versions of the app.
</div>
## Throttling
The transition from the server-rendered app to the client app happens quickly on a development machine.
You can simulate a slower network to see the transition more clearly and
better appreciate the launch-speed advantage of a universal app running on a low powered, poorly connected device.
Open the Chrome Dev Tools and go to the Network tab.
Find the [Network Throttling](https://developers.google.com/web/tools/chrome-devtools/network-performance/reference#throttling) dropdown on the far right of the menu bar.
Try one of the "3G" speeds.
The server-rendered app still launches quickly but the full client app may take seconds to load.
{@a conclusion}
## Conclusion
This guide showed you how to take an existing Angular application and make it into a Universal app that does server-side rendering.
It also explained some of the key reasons for doing so.
- Facilitate web crawlers (SEO)
- Support low-bandwidth or low-power devices
- Fast first page load
Angular Universal can greatly improve the perceived startup performance of your app.
The slower the network, the more advantageous it becomes to have Universal display the first page to the user.
{@a cannot-find-module}
#### Appendix: _Cannot find module_ error
As you continue to develop the application locally,
running the `npm start` command outside of universal, the compiler may fail with the following error:
<code-example format="." language="bash">
error TS2307: Cannot find module '../../aot/src/universal/app-server.module.ngfactory'.
</code-example>
The likely cause is that you've been through these guide steps before and now have a `/universal` folder.
That folder holds server-side artifacts that are irrelevant to the client app and are confusing the compiler.
You must exclude the _server-side_ `/universal` folder files from _client app_ compilation.
Open `tsconfig.json`, find the `"exclude"` node and add `"universal/*"` to the array.
The result might look something like this:
```
"exclude": [
"node_modules/*",
"universal/*"
]
```
Compile and run again with `npm start`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -13,18 +13,6 @@
</tr>
</thead>
<tbody>
<!-- ngJapan -->
<tr>
<th><a href="http://ngjapan.org/" title="ng-Japan">ng-Japan</a></th>
<td>Tokyo, Japan</td>
<td>June 17, 2017</td>
</tr>
<!-- AngularMix -->
<tr>
<th><a href="https://angularmix.com/" title="AngularMix">AngularMix</a></th>
<td>Universal Studios, Orlando, Florida</td>
<td>October 8, 2017</td>
</tr>
<!-- ReactiveConf -->
<tr>
<th><a href="https://reactiveconf.com/" title="ReactiveConf">ReactiveConf</a></th>
@ -35,7 +23,7 @@
<tr>
<th><a href="http://angularconnect.com" title="AngularConnect">AngularConnect</a></th>
<td>London, United Kingdom</td>
<td>November 07, 2017</td>
<td>November 7-8, 2017</td>
</tr>
<!-- ngAtlanta-->
<tr>
@ -43,6 +31,30 @@
<td>Atlanta, Georgia</td>
<td>January 30, 2018</td>
</tr>
<!-- ngVikings-->
<tr>
<th><a href="https://ngvikings.org/" title="ngVikings">ngVikings</a></th>
<td>Helsinki, Finland</td>
<td>March 1-2, 2018</td>
</tr>
<!-- ngconf 2018-->
<tr>
<th><a href="https://www.ng-conf.org/" title="ng-conf">ng-conf</a></th>
<td>Salt Lake City, UT</td>
<td>April 18-20, 2018</td>
</tr>
<!-- WeRDevs-->
<tr>
<th><a href="https://www.wearedevelopers.com/" title="WeAreDevs">WeAreDevelopers</a></th>
<td>Vienna</td>
<td>May 16-18, 2018</td>
</tr>
<!-- AngularConnect-->
<tr>
<th><a href="http://angularconnect.com" title="AngularConnect">AngularConnect</a></th>
<td>London, United Kingdom</td>
<td>November 5-7, 2018</td>
</tr>
</tbody>
</table>
</article>

View File

@ -32,9 +32,9 @@
<!-- Announcement Bar -->
<div class="homepage-container">
<div class="announcement-bar">
<img src="generated/images/marketing/home/angular-mix.png" height="40" width="151">
<p>Join us at our newest event, October 2017</p>
<a class="button" href="https://angularmix.com/">Learn More</a>
<img src="generated/images/marketing/home/angular-connect.png">
<p>Join us in London for AngularConnect<br>November 7-8, 2017</p>
<a class="button" href="https://angularconnect.com/">Learn More</a>
</div>
</div>

View File

@ -317,7 +317,7 @@
"desc": "Material Design components for Angular",
"logo": "",
"rev": true,
"title": "Angular Material 2",
"title": "Angular Material",
"url": "https://github.com/angular/material2"
},
"aggrid": {

View File

@ -362,7 +362,11 @@
}
]
},
{
"url": "guide/universal",
"title": "Server-side Rendering",
"tooltip": "Render HTML server-side with Angular Universal."
},
{
"url": "guide/visual-studio-2015",
"title": "Visual Studio 2015 QuickStart",

View File

@ -1207,7 +1207,8 @@ Here's an excerpt:
Create the file <code>styles.css</code>.
Ensure that the file contains the [master styles provided here](https://raw.githubusercontent.com/angular/angular/master/aio/tools/examples/shared/boilerplate/src/styles.css).
Ensure that the file contains the [master styles provided here](https://raw.githubusercontent.com/angular/angular/master/aio/tools/examples/shared/boilerplate/common/src/styles.css).

View File

@ -21,4 +21,24 @@ describe('Api pages', function() {
const page = new ApiPage('api/animations/AnimationPlayer');
expect(page.getDescendants('class')).toEqual(['NoopAnimationPlayer', 'MockAnimationPlayer'] as any);
});
it('should show type params of type-aliases', () => {
const page = new ApiPage('api/common/http/HttpEvent');
expect(page.getOverview('type-alias').getText()).toContain('type HttpEvent<T>');
});
it('should show readonly properties as getters', () => {
const page = new ApiPage('api/common/http/HttpRequest');
expect(page.getOverview('class').getText()).toContain('get body: T|null');
});
it('should not show parenthesis for getters', () => {
const page = new ApiPage('api/core/NgModuleRef');
expect(page.getOverview('class').getText()).toContain('get injector: Injector');
});
it('should show both type and initializer if set', () => {
const page = new ApiPage('api/common/HashLocationStrategy');
expect(page.getOverview('class').getText()).toContain('path(includeHash: boolean = false): string');
});
});

View File

@ -27,4 +27,8 @@ export class ApiPage extends SitePage {
const selector = `.descendants.${docType} ${onlyDirect ? '>' : ''} li > :not(ul) code`;
return element.all(by.css(selector)).map<string>(item => item.getText());
}
getOverview(docType) {
return element(by.css(`.${docType}-overview`));
}
}

View File

@ -1,4 +1,4 @@
import { browser, element, by, promise } from 'protractor';
import { element, by } from 'protractor';
import { SitePage } from './app.po';
describe('site App', function() {
@ -41,20 +41,20 @@ describe('site App', function() {
describe('scrolling to the top', () => {
it('should scroll to the top when navigating to another page', () => {
page.navigateTo('guide/docs');
page.navigateTo('guide/security');
page.scrollToBottom();
page.getScrollTop().then(scrollTop => expect(scrollTop).toBeGreaterThan(0));
page.navigateTo('guide/api');
page.navigateTo('api');
page.getScrollTop().then(scrollTop => expect(scrollTop).toBe(0));
});
it('should scroll to the top when navigating to the same page', () => {
page.navigateTo('guide/docs');
page.navigateTo('guide/security');
page.scrollToBottom();
page.getScrollTop().then(scrollTop => expect(scrollTop).toBeGreaterThan(0));
page.navigateTo('guide/docs');
page.navigateTo('guide/security');
page.getScrollTop().then(scrollTop => expect(scrollTop).toBe(0));
});
});
@ -66,30 +66,35 @@ describe('site App', function() {
});
});
// TODO(https://github.com/angular/angular/issues/19785): Activate this again
// once it is no more flaky.
describe('google analytics', () => {
beforeEach(done => page.gaReady.then(done));
it('should call ga', done => {
page.ga()
.then(calls => {
expect(calls.length).toBeGreaterThan(2, 'ga calls');
done();
});
});
it('should call ga with initial URL', done => {
let path: string;
page.navigateTo('api');
page.locationPath()
.then(p => path = p)
.then(() => page.ga().then(calls => {
expect(calls.length).toBeGreaterThan(2, 'ga calls');
expect(calls[1]).toEqual(['set', 'page', path]);
// The last call (length-1) will be the `send` command
// The second to last call (length-2) will be the command to `set` the page url
expect(calls[calls.length - 2]).toEqual(['set', 'page', path]);
done();
}));
});
// Todo: add test to confirm tracking URL when navigate.
it('should call ga with new URL on navigation', done => {
let path: string;
page.getLink('features').click();
page.locationPath()
.then(p => path = p)
.then(() => page.ga().then(calls => {
// The last call (length-1) will be the `send` command
// The second to last call (length-2) will be the command to `set` the page url
expect(calls[calls.length - 2]).toEqual(['set', 'page', path]);
done();
}));
});
});
describe('search', () => {
@ -100,4 +105,12 @@ describe('site App', function() {
expect(page.getSearchResults().map(link => link.getText())).toContain('ControlValueAccessor');
});
});
describe('404 page', () => {
it('should search the index for words found in the url', () => {
page.navigateTo('http/router');
expect(page.getSearchResults().map(link => link.getText())).toContain('Http');
expect(page.getSearchResults().map(link => link.getText())).toContain('Router');
});
});
});

View File

@ -12,7 +12,6 @@ export class SitePage {
.all(by.css('a'))
.filter((a: ElementFinder) => a.getAttribute('href').then(href => githubRegex.test(href)))
.first();
gaReady: promise.Promise<any>;
static setWindowWidth(newWidth: number) {
const win = browser.driver.manage().window();
@ -25,11 +24,14 @@ export class SitePage {
.first();
}
getLink(path) { return element(by.css(`a[href="${path}"]`)); }
ga() { return browser.executeScript('return window["gaCalls"]') as promise.Promise<any[][]>; }
ga() { return browser.executeScript('return window["ga"].q') as promise.Promise<any[][]>; }
locationPath() { return browser.executeScript('return document.location.pathname') as promise.Promise<string>; }
navigateTo(pageUrl = '') {
return browser.get('/' + pageUrl).then(_ => this.replaceGa(_));
return browser.get('/' + pageUrl)
// We need to tell the index.html not to load the real analytics library
// See the GA snippet in index.html
.then(() => browser.driver.executeScript('sessionStorage.setItem("__e2e__", true);'));
}
getDocViewerText() {
@ -61,31 +63,4 @@ export class SitePage {
browser.wait(ExpectedConditions.presenceOf(results.first()), 8000);
return results;
}
/**
* Replace the ambient Google Analytics tracker with homebrew spy
* don't send commands to GA during e2e testing!
* @param _ - forward's anything passed in
*/
private replaceGa(_: any) {
this.gaReady = browser.driver.executeScript(() => {
// Give ga() a "ready" callback:
// https://developers.google.com/analytics/devguides/collection/analyticsjs/command-queue-reference
window['ga'](() => {
window['gaCalls'] = [];
window['ga'] = function() { window['gaCalls'].push(arguments); };
});
})
.then(() => {
// wait for GaService to start using window.ga after analytics lib loads.
const d = promise.defer();
setTimeout(() => d.fulfill(), 1000); // GaService.initializeDelay
return d.promise;
});
return _;
}
}

View File

@ -44,6 +44,17 @@
"source": "**/!(*.*)",
"destination": "/index.html"
}
],
"headers": [
{
"source": "/",
"headers": [
{
"key": "Link",
"value": "</generated/navigation.json>;rel=preload;as=fetch,</generated/docs/index.json>;rel=preload;as=fetch"
}
]
}
]
}
}

View File

@ -6,6 +6,9 @@
"author": "Angular",
"license": "MIT",
"scripts": {
"aio-use-local": "node tools/ng-packages-installer overwrite . --debug --ignore-packages @angular/service-worker",
"aio-use-npm": "node tools/ng-packages-installer restore . && yarn upgrade @angular/cli@1.3.0",
"aio-check-local": "node tools/ng-packages-installer check .",
"ng": "yarn check-env && ng",
"start": "yarn check-env && ng serve",
"prebuild": "yarn setup",
@ -16,29 +19,31 @@
"test": "yarn check-env && ng test",
"pree2e": "yarn check-env && yarn ~~update-webdriver",
"e2e": "ng e2e --no-webdriver-update",
"presetup": "yarn ~~check-env && yarn install && yarn boilerplate:remove",
"setup": "node tools/ng-packages-installer restore . && yarn boilerplate:add",
"postsetup": "yarn build-ie-polyfills && yarn generate-plunkers && yarn generate-zips && yarn docs",
"presetup": "yarn install --frozen-lockfile && yarn ~~check-env && yarn boilerplate:remove",
"setup": "yarn aio-use-npm && yarn example-use-npm",
"postsetup": "yarn boilerplate:add && yarn build-ie-polyfills && yarn generate-plunkers && yarn generate-zips && yarn docs",
"presetup-local": "yarn presetup",
"setup-local": "node tools/ng-packages-installer overwrite . && yarn boilerplate:add --local",
"setup-local": "yarn aio-use-local && yarn upgrade @angular/cli@1.5.0-rc.2 && yarn example-use-local",
"postsetup-local": "yarn postsetup",
"pretest-pwa-score-localhost": "yarn build",
"test-pwa-score-localhost": "concurrently --kill-others --success first \"http-server dist -p 4200 --silent\" \"yarn test-pwa-score http://localhost:4200 90\"",
"test-pwa-score": "node scripts/test-pwa-score",
"example-e2e": "yarn check-ng-packages tools/examples/shared && node ./tools/examples/run-example-e2e",
"example-e2e": "yarn example-check-local && node ./tools/examples/run-example-e2e",
"example-lint": "tslint -c \"content/examples/tslint.json\" \"content/examples/**/*.ts\" -e \"content/examples/styleguide/**/*.avoid.ts\"",
"example-use-local": "node tools/ng-packages-installer overwrite ./tools/examples/shared",
"example-use-npm": "node tools/ng-packages-installer restore ./tools/examples/shared",
"example-check-local": "node tools/ng-packages-installer check ./tools/examples/shared",
"deploy-preview": "scripts/deploy-preview.sh",
"deploy-production": "scripts/deploy-to-firebase.sh",
"check-ng-packages": "node tools/ng-packages-installer check",
"check-env": "yarn ~~check-env",
"postcheck-env": "yarn check-ng-packages .",
"postcheck-env": "yarn aio-check-local",
"payload-size": "scripts/payload.sh",
"predocs": "rimraf src/generated/{docs,*.json}",
"docs": "dgeni ./tools/transforms/angular.io-package",
"docs-watch": "node tools/transforms/authors-package/watchr.js",
"docs-lint": "eslint --ignore-path=\"tools/transforms/.eslintignore\" tools/transforms",
"docs-test": "node tools/transforms/test.js",
"tools-test": "./scripts/deploy-to-firebase.test.sh && yarn docs-test && yarn boilerplate:test && jasmine tools/ng-packages-installer.spec.js",
"tools-test": "./scripts/deploy-to-firebase.test.sh && yarn docs-test && yarn boilerplate:test && jasmine tools/ng-packages-installer/index.spec.js",
"serve-and-sync": "concurrently --kill-others \"yarn docs-watch\" \"yarn start\"",
"boilerplate:add": "node ./tools/examples/example-boilerplate add",
"boilerplate:remove": "node ./tools/examples/example-boilerplate remove",
@ -94,7 +99,7 @@
"concurrently": "^3.4.0",
"cross-spawn": "^5.1.0",
"dgeni": "^0.4.7",
"dgeni-packages": "^0.21.3",
"dgeni-packages": "0.22.0",
"entities": "^1.1.1",
"eslint": "^3.19.0",
"eslint-plugin-jasmine": "^2.2.0",
@ -129,7 +134,7 @@
"semver": "^5.3.0",
"shelljs": "^0.7.7",
"tree-kill": "^1.1.0",
"ts-node": "~2.0.0",
"ts-node": "^3.3.0",
"tslint": "~4.5.0",
"typescript": "2.3.2",
"uglify-js": "^3.0.15",

View File

@ -4,7 +4,7 @@ set -u -e -o pipefail
declare -A payloadLimits
payloadLimits["aio", "uncompressed", "inline"]=1600
payloadLimits["aio", "uncompressed", "main"]=525000
payloadLimits["aio", "uncompressed", "main"]=525500
payloadLimits["aio", "uncompressed", "polyfills"]=38000
payloadLimits["aio", "gzip7", "inline"]=1000
payloadLimits["aio", "gzip7", "main"]=127000

View File

@ -19,6 +19,11 @@ const config = require('lighthouse/lighthouse-core/config/default.js');
// Constants
const VIEWER_URL = 'https://googlechrome.github.io/lighthouse/viewer/';
// Specify the path to Chrome on Travis
if (process.env.TRAVIS) {
process.env.LIGHTHOUSE_CHROMIUM_PATH = process.env.CHROME_BIN;
}
// Run
_main(process.argv.slice(2));

View File

@ -13,7 +13,7 @@
<aio-top-menu *ngIf="isSideBySide" [nodes]="topMenuNodes"></aio-top-menu>
<aio-search-box class="search-container" #searchBox (onSearch)="doSearch($event)" (onFocus)="doSearch($event)"></aio-search-box>
</md-toolbar>
<aio-search-results #searchResults *ngIf="showSearchResults" (resultSelected)="hideSearchResults()"></aio-search-results>
<aio-search-results #searchResultsView *ngIf="showSearchResults" [searchResults]="searchResults | async" (resultSelected)="hideSearchResults()"></aio-search-results>
<md-sidenav-container class="sidenav-container" [class.starting]="isStarting" [class.has-floating-toc]="hasFloatingToc" role="main">

View File

@ -1,12 +1,11 @@
import { NO_ERRORS_SCHEMA, DebugElement } from '@angular/core';
import { async, inject, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { inject, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { Title } from '@angular/platform-browser';
import { APP_BASE_HREF } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { MdProgressBar, MdSidenav } from '@angular/material';
import { By } from '@angular/platform-browser';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { of } from 'rxjs/observable/of';
import { AppComponent } from './app.component';
@ -22,9 +21,9 @@ import { MockSearchService } from 'testing/search.service';
import { NavigationNode } from 'app/navigation/navigation.service';
import { ScrollService } from 'app/shared/scroll.service';
import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
import { SearchResultsComponent } from 'app/search/search-results/search-results.component';
import { SearchResultsComponent } from 'app/shared/search-results/search-results.component';
import { SearchService } from 'app/search/search.service';
import { SelectComponent, Option } from 'app/shared/select/select.component';
import { SelectComponent } from 'app/shared/select/select.component';
import { TocComponent } from 'app/embedded/toc/toc.component';
import { TocItem, TocService } from 'app/shared/toc.service';
@ -1054,11 +1053,6 @@ class TestGaService {
locationChanged = jasmine.createSpy('locationChanged');
}
class TestSearchService {
initWorker = jasmine.createSpy('initWorker');
loadIndex = jasmine.createSpy('loadIndex');
}
class TestHttpClient {
static versionInfo = {

View File

@ -2,18 +2,18 @@ import { Component, ElementRef, HostBinding, HostListener, OnInit,
QueryList, ViewChild, ViewChildren } from '@angular/core';
import { MdSidenav } from '@angular/material';
import { CurrentNodes, NavigationService, NavigationViews, NavigationNode, VersionInfo } from 'app/navigation/navigation.service';
import { CurrentNodes, NavigationService, NavigationNode, VersionInfo } from 'app/navigation/navigation.service';
import { DocumentService, DocumentContents } from 'app/documents/document.service';
import { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component';
import { Deployment } from 'app/shared/deployment.service';
import { LocationService } from 'app/shared/location.service';
import { NavMenuComponent } from 'app/layout/nav-menu/nav-menu.component';
import { ScrollService } from 'app/shared/scroll.service';
import { SearchResultsComponent } from 'app/search/search-results/search-results.component';
import { SearchBoxComponent } from 'app/search/search-box/search-box.component';
import { SearchResults } from 'app/search/interfaces';
import { SearchService } from 'app/search/search.service';
import { TocService } from 'app/shared/toc.service';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { combineLatest } from 'rxjs/observable/combineLatest';
@ -89,10 +89,9 @@ export class AppComponent implements OnInit {
// Search related properties
showSearchResults = false;
@ViewChildren('searchBox, searchResults', { read: ElementRef })
searchResults: Observable<SearchResults>;
@ViewChildren('searchBox, searchResultsView', { read: ElementRef })
searchElements: QueryList<ElementRef>;
@ViewChild(SearchResultsComponent)
searchResults: SearchResultsComponent;
@ViewChild(SearchBoxComponent)
searchBox: SearchBoxComponent;
@ -332,7 +331,7 @@ export class AppComponent implements OnInit {
}
doSearch(query) {
this.searchService.search(query);
this.searchResults = this.searchService.search(query);
this.showSearchResults = !!query;
}

View File

@ -43,9 +43,9 @@ import { NavMenuComponent } from 'app/layout/nav-menu/nav-menu.component';
import { NavItemComponent } from 'app/layout/nav-item/nav-item.component';
import { ScrollService } from 'app/shared/scroll.service';
import { ScrollSpyService } from 'app/shared/scroll-spy.service';
import { SearchResultsComponent } from './search/search-results/search-results.component';
import { SearchBoxComponent } from './search/search-box/search-box.component';
import { TocService } from 'app/shared/toc.service';
import { WindowToken, windowProvider } from 'app/shared/window';
import { SharedModule } from 'app/shared/shared.module';
@ -95,7 +95,6 @@ export const svgIconProviders = [
ModeBannerComponent,
NavMenuComponent,
NavItemComponent,
SearchResultsComponent,
SearchBoxComponent,
TopMenuComponent,
],
@ -115,7 +114,8 @@ export const svgIconProviders = [
ScrollSpyService,
SearchService,
svgIconProviders,
TocService
TocService,
{ provide: WindowToken, useFactory: windowProvider },
],
bootstrap: [AppComponent]
})

View File

@ -1,10 +1,7 @@
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Injector } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { LocationService } from 'app/shared/location.service';
import { MockLocationService } from 'testing/location.service';

View File

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { ApiListComponent } from './api-list.component';

View File

@ -13,7 +13,7 @@ import { ReplaySubject } from 'rxjs/ReplaySubject';
import { combineLatest } from 'rxjs/observable/combineLatest';
import { LocationService } from 'app/shared/location.service';
import { ApiItem, ApiSection, ApiService } from './api.service';
import { ApiSection, ApiService } from './api.service';
import { Option } from 'app/shared/select/select.component';

View File

@ -1,6 +1,6 @@
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Injector } from '@angular/core';
import { TestBed, inject } from '@angular/core/testing';
import { TestBed } from '@angular/core/testing';
import { Logger } from 'app/shared/logger.service';

View File

@ -1,11 +1,9 @@
import { Component, ElementRef, ViewChild, OnChanges, OnDestroy, Input } from '@angular/core';
import { Component, ElementRef, ViewChild, OnChanges, Input } from '@angular/core';
import { Logger } from 'app/shared/logger.service';
import { PrettyPrinter } from './pretty-printer.service';
import { CopierService } from 'app/shared/copier.service';
import { MdSnackBar } from '@angular/material';
const originalLabel = 'Copy Code';
const copiedLabel = 'Copied!';
const defaultLineNumsCount = 10; // by default, show linenums over this number
/**

View File

@ -3,7 +3,7 @@ import { Injector } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { ContributorService } from './contributor.service';
import { Contributor, ContributorGroup } from './contributors.model';
import { ContributorGroup } from './contributors.model';
describe('ContributorService', () => {

View File

@ -1,4 +1,4 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LocationService } from 'app/shared/location.service';
import { MockLocationService } from 'testing/location.service';
import { CurrentLocationComponent } from './current-location.component';

View File

@ -20,6 +20,7 @@ import { CodeTabsComponent } from './code/code-tabs.component';
import { ContributorListComponent } from './contributor/contributor-list.component';
import { ContributorComponent } from './contributor/contributor.component';
import { CurrentLocationComponent } from './current-location.component';
import { FileNotFoundSearchComponent } from './search/file-not-found-search.component';
import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example/live-example.component';
import { ResourceListComponent } from './resource/resource-list.component';
import { ResourceService } from './resource/resource.service';
@ -30,7 +31,8 @@ import { TocComponent } from './toc/toc.component';
*/
export const embeddedComponents: any[] = [
ApiListComponent, CodeExampleComponent, CodeTabsComponent, ContributorListComponent,
CurrentLocationComponent, LiveExampleComponent, ResourceListComponent, TocComponent
CurrentLocationComponent, FileNotFoundSearchComponent, LiveExampleComponent, ResourceListComponent,
TocComponent
];
/** Injectable class w/ property returning components that can be embedded in docs */

View File

@ -1,6 +1,6 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Component, DebugElement, ElementRef } from '@angular/core';
import { Component, DebugElement } from '@angular/core';
import { Location } from '@angular/common';
import { LiveExampleComponent, EmbeddedPlunkerComponent } from './live-example.component';
@ -71,7 +71,6 @@ describe('LiveExampleComponent', () => {
describe('when not embedded', () => {
function getLiveExampleAnchor() { return getAnchors()[0]; }
function getDownloadAnchor() { return getAnchors()[1]; }
it('should create LiveExampleComponent', () => {
testComponent(() => {

View File

@ -1,7 +1,6 @@
import { ReflectiveInjector } from '@angular/core';
import { PlatformLocation } from '@angular/common';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { ResourceListComponent } from './resource-list.component';

View File

@ -3,7 +3,7 @@ import { Injector } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { ResourceService } from './resource.service';
import { Category, SubCategory, Resource } from './resource.model';
import { Category } from './resource.model';
describe('ResourceService', () => {

View File

@ -0,0 +1,49 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Subject } from 'rxjs/Subject';
import { LocationService } from 'app/shared/location.service';
import { MockLocationService } from 'testing/location.service';
import { SearchResults } from 'app/search/interfaces';
import { SearchResultsComponent } from 'app/shared/search-results/search-results.component';
import { SearchService } from 'app/search/search.service';
import { FileNotFoundSearchComponent } from './file-not-found-search.component';
describe('FileNotFoundSearchComponent', () => {
let element: HTMLElement;
let fixture: ComponentFixture<FileNotFoundSearchComponent>;
let searchService: SearchService;
let searchResultSubject: Subject<SearchResults>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ FileNotFoundSearchComponent, SearchResultsComponent ],
providers: [
{ provide: LocationService, useValue: new MockLocationService('base/initial-url?some-query') },
SearchService
]
});
fixture = TestBed.createComponent(FileNotFoundSearchComponent);
searchService = TestBed.get(SearchService);
searchResultSubject = new Subject<SearchResults>();
spyOn(searchService, 'search').and.callFake(() => searchResultSubject.asObservable());
fixture.detectChanges();
element = fixture.nativeElement;
});
it('should run a search with a query built from the current url', () => {
expect(searchService.search).toHaveBeenCalledWith('base initial url');
});
it('should pass through any results to the `aio-search-results` component', () => {
const searchResultsComponent = fixture.debugElement.query(By.directive(SearchResultsComponent)).componentInstance;
expect(searchResultsComponent.searchResults).toBe(null);
const results = { query: 'base initial url', results: []};
searchResultSubject.next(results);
fixture.detectChanges();
expect(searchResultsComponent.searchResults).toEqual(results);
});
});

View File

@ -0,0 +1,23 @@
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { LocationService } from 'app/shared/location.service';
import { SearchResults } from 'app/search/interfaces';
import { SearchService } from 'app/search/search.service';
@Component({
selector: 'aio-file-not-found-search',
template:
`<p>Let's see if any of these search results help...</p>
<aio-search-results class="embedded" [searchResults]="searchResults | async"></aio-search-results>`
})
export class FileNotFoundSearchComponent implements OnInit {
searchResults: Observable<SearchResults>;
constructor(private location: LocationService, private search: SearchService) {}
ngOnInit() {
this.searchResults = this.location.currentPath.switchMap(path => {
const query = path.split(/\W+/).join(' ');
return this.search.search(query);
});
}
}

View File

@ -1,6 +1,6 @@
import { Component, CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By, DOCUMENT } from '@angular/platform-browser';
import { By } from '@angular/platform-browser';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { asap } from 'rxjs/scheduler/asap';

View File

@ -1,11 +1,8 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {
Component, ComponentFactoryResolver, DebugElement,
ElementRef, Injector, NgModule, OnInit, ViewChild } from '@angular/core';
import { By } from '@angular/platform-browser';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, DebugElement, ElementRef, NgModule, OnInit, ViewChild } from '@angular/core';
import { DocViewerComponent } from './doc-viewer.component';
import { DocumentContents } from 'app/documents/document.service';
import { EmbeddedModule, embeddedComponents, EmbeddedComponents } from 'app/embedded/embedded.module';
import { EmbeddedModule, EmbeddedComponents } from 'app/embedded/embedded.module';
import { Title } from '@angular/platform-browser';
import { TocService } from 'app/shared/toc.service';

View File

@ -1,7 +1,7 @@
import {
Component, ComponentFactory, ComponentFactoryResolver, ComponentRef,
DoCheck, ElementRef, EventEmitter, Injector, Input, OnDestroy,
Output, ViewEncapsulation
Output
} from '@angular/core';
import { EmbeddedComponents } from 'app/embedded/embedded.module';

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { SimpleChange, SimpleChanges, NO_ERRORS_SCHEMA } from '@angular/core';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NavItemComponent } from './nav-item.component';
import { NavigationNode } from 'app/navigation/navigation.model';

View File

@ -1,9 +1,9 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { TopMenuComponent } from './top-menu.component';
import { NavigationService, NavigationViews, NavigationNode } from 'app/navigation/navigation.service';
import { NavigationService, NavigationViews } from 'app/navigation/navigation.service';
describe('TopMenuComponent', () => {
let component: TopMenuComponent;

View File

@ -2,7 +2,6 @@ import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AsyncSubject } from 'rxjs/AsyncSubject';
import { combineLatest } from 'rxjs/observable/combineLatest';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/publishLast';

View File

@ -0,0 +1,19 @@
export interface SearchResults {
query: string;
results: SearchResult[];
}
export interface SearchResult {
path: string;
title: string;
type: string;
titleWords: string;
keywords: string;
}
export interface SearchArea {
name: string;
pages: SearchResult[];
priorityPages: SearchResult[];
}

View File

@ -2,7 +2,6 @@ import { Component } from '@angular/core';
import { ComponentFixture, fakeAsync, inject, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { SearchBoxComponent } from './search-box.component';
import { MockSearchService } from 'testing/search.service';
import { LocationService } from 'app/shared/location.service';
import { MockLocationService } from 'testing/location.service';

Some files were not shown because too many files have changed in this diff Show More