Skip to content

Commit 74eb871

Browse files
committed
docs(readme): update for 4.0 documentation
1 parent df33e17 commit 74eb871

File tree

7 files changed

+244
-9
lines changed

7 files changed

+244
-9
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
# User-specific files (MonoDevelop/Xamarin Studio)
1313
*.userprefs
14+
15+
# yarn
16+
.yarn.lock
1417

1518
# Build results
1619
[Dd]ebug/

Client/app/browser-app.module.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ export function createConfig(): SignalRConfiguration {
2121
@NgModule({
2222
bootstrap: [AppComponent],
2323
imports: [
24-
BrowserAnimationsModule,
2524
BrowserModule.withServerTransition({
26-
appId: 'my-app-id'
25+
appId: 'my-app-id' // make sure this matches with your Server NgModule
2726
}),
27+
BrowserAnimationsModule,
28+
// Our Common AppModule
2829
AppModule,
30+
2931
SignalRModule.forRoot(() => createConfig())
3032
]
3133
})

Client/app/server-app.module.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ import { AppComponent } from './app.component';
1010
@NgModule({
1111
bootstrap: [ AppComponent ],
1212
imports: [
13-
NoopAnimationsModule,
1413
BrowserModule.withServerTransition({
15-
appId: 'my-app-id'
14+
appId: 'my-app-id' // make sure this matches with your Browser NgModule
1615
}),
1716
ServerModule,
18-
AppModule
17+
NoopAnimationsModule,
18+
19+
// Our Common AppModule
20+
AppModule
1921
]
2022
})
2123
export class AppServerModule {

Client/app/shared/link.service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
/*
2+
* -- LinkService -- [Temporary]
3+
* @MarkPieszak
4+
*
5+
* Similar to Meta service but made to handle <link> creation for SEO purposes
6+
* Soon there will be an overall HeadService within Angular that handles Meta/Link everything
7+
*/
8+
19
import { Injectable, PLATFORM_ID, Optional, RendererFactory2, ViewEncapsulation, Inject } from '@angular/core';
210
import { DOCUMENT } from '@angular/platform-browser';
311
import { isPlatformServer } from '@angular/common';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import 'zone.js/dist/zone';
22
import 'reflect-metadata';
33

4-
import './rx-imports';
4+
import './rx-imports';

Client/polyfills/temporary-aspnetcore-engine.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
/* ********* TEMPORARILY HERE **************
33
* - will be on npm soon -
4-
* import { ngAspnetCoreEngine } from `@universal/ng-aspnetcore-engine`;
4+
* import { ngAspnetCoreEngine } from `@ng-universal/ng-aspnetcore-engine`;
55
*/
66

77
import { Type, NgModuleRef, ApplicationRef, Provider } from '@angular/core';

README.md

Lines changed: 222 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,36 @@
8888

8989
# Getting Started?
9090

91-
**Make sure you have at least Node 4.x or higher installed!**
91+
**Make sure you have at least Node 6.x or higher (w/ npm 3+) installed!**
92+
93+
### Visual Studio 2017
9294

9395
Make sure you have .NET Core 1.0+ installed and/or VS2017.
9496
VS2017 will automatically install all the neccessary npm & .NET dependencies when you open the project.
9597

9698
Simply push F5 to start debugging !
9799

100+
### Visual Studio Code
101+
102+
> Note: Make sure you have the C# extension & .NET Core Debugger installed.
103+
104+
The project comes with the configured Launch.json files to let you just push F5 to start the project.
105+
106+
```bash
107+
# cd into the directory you cloned the project into
108+
npm install && dotnet restore
109+
# or yarn install
110+
```
111+
112+
If you're running the project from command line with `dotnet run` make sure you set your environment variables to Development (otherwise things like HMR won't work).
113+
114+
```bash
115+
# on Windows:
116+
set ASPNETCORE_ENVIRONMENT=Development
117+
# on Mac/Linux
118+
export ASPNETCORE_ENVIRONMENT=Development
119+
```
120+
98121
----
99122

100123
----
@@ -120,7 +143,163 @@ git push --set-upstream azure master
120143

121144
# Application Structure:
122145

123-
> Needs to be updated for 4.0 structure - Coming soon!
146+
> Note: This application has WebAPI (our REST API) setup inside the same project, but of course all of this
147+
could be abstracted out into a completely separate project('s) ideally. .NET Core things are all done in the same project
148+
for simplicity's sake.
149+
150+
**Root level files**
151+
152+
Here we have the *usual suspects* found at the root level.
153+
154+
*Front-end oriented files:*
155+
156+
- `package.json` - NPM project dependencies & scripts
157+
- `.tsconfig` - TypeScript configuration (here we setup PATHs as well)
158+
- `webpack` - configuration files (modular bundling + so much more)
159+
- `karma` - configuration files (unit testing)
160+
- `protractor` - config files (e2e testing)
161+
- `tslint` - TypeScript code linting rules
162+
163+
### /Client/ - Everything Angular
164+
165+
> Let's take a look at how this is structured so we can make some sense of it all!
166+
167+
With Angular Universal, we need to split our applicatoin logic **per platform** so [if we look inside this folder](./Client),
168+
you'll see the 2 root files, that branch the entire logic for browser & server respectively.
169+
170+
- [**Boot-Client.ts**](./Client/boot-client.ts) -
171+
This file starts up the entire Angular application for the Client/browser platform.
172+
173+
Here we setup a few things, client Angular bootstrapping.
174+
175+
You'll barely need to touch this file, but something to note, this is the file where you would import libraries that you **only** want
176+
being used in the Browser. (Just know that you'd have to provide a mock implementation for the Server when doing that).
177+
178+
- [**Boot-Server.ts**](./Client/boot-server.ts) -
179+
This file is where Angular _platform-server_ *serializes* the Angular application itself on the .NET server
180+
within a very quick Node process, and renders it a string. This is what causes that initial fast paint
181+
of the entire application to the Browser, and helps us get all our _SEO_ goodness :sparkles:
182+
183+
---
184+
185+
Notice the folder structure here in `./Client/` :
186+
187+
```diff
188+
+ /Client/
189+
190+
+ /app/
191+
App NgModule - our Root NgModule (you'll insert Components/etc here most often)
192+
AppComponent / App Routes / global css styles
193+
194+
* Notice that we have 2 dividing NgModules:
195+
browser-app.module & server-app.module
196+
You'll almost always be using the common app.module, but these 2 are used to split up platform logic
197+
for situations where you need to use Dependency Injection / etc, between platforms.
198+
199+
Note: You could use whatever folder conventions you'd like, I prefer to split up things in terms of whether they are re-usable
200+
"components" or routeable / page-like components that group together and organize entire sections.
201+
++ > ++ > /components/
202+
Here are all the regular Components that aren't "Pages" or container Components
203+
204+
++ > ++ > /containers/
205+
These are the routeable or "Page / Container" Components, sometimes known as "Dumb" Components
206+
207+
++ > ++ > /shared/
208+
Here we put all shared Services / Directives / Pipes etc
209+
```
210+
211+
When adding new features/components/etc to your application you'll be commonly adding things to the Root **NgModule** (located
212+
in `/Client/app/app.module.ts`), but why are there **two** other NgModules in this folder?
213+
214+
This is because we want to split our logic **per Platform**, but notice they both share the Common NgModule
215+
named `app.module.ts`. When adding most things to your application, this is the only
216+
place you'll have to add in your new Component / Directive / Pipe / etc. You'll only occassional need to manually
217+
add in the Platform specific things to either `browser-app.module || server-app.module`.
218+
219+
To illustrate this point with an example, you can see how we're using Dependency Injection to inject a `StorageService` that is different
220+
for the Browser & Server.
221+
222+
```typescript
223+
// For the Browser (browser-app.module)
224+
{ provide: StorageService, useClass: BrowserStorage }
225+
226+
// For the Server (server-app.module)
227+
{ provide: StorageService, useClass: ServerStorage }
228+
```
229+
230+
> Just remember, you'll usually only need to worry about `app.module.ts`, as that's where you'll be adding most
231+
of your applications new aspects!
232+
233+
234+
### /Server/ - Our REST API (WebApi) - MVC Controller
235+
236+
> As we pointed out, these are here for simplicities sake, and realistically you may want separate projects
237+
for all your microservices / REST API projects / etc.
238+
239+
We're utilizing MVC within this application, but we only need & have ONE Controller, named `HomeController`. This is where our entire
240+
Angular application gets serialized into a String, sent to the Browser, along with all the assets it needs to then bootstrap on the client-side, and become a full-blown SPA afterwards.
241+
242+
---
243+
244+
The short-version is that we invoke that Node process, passing in our Request object & invoke the `boot-server` file, and we get back a nice object that we pass into .NETs `ViewData` object, and sprinkle through out our `Views/Shared/_Layout.cshtml` and `/Views/Home/index.cshtml` files!
245+
246+
A more detailed explanation can be found here: [TODO-add-link * You can read a more detailed explanation here](#)
247+
248+
```csharp
249+
// Prerender / Serialize application (with Universal)
250+
var prerenderResult = await Prerenderer.RenderToString(
251+
/* all of our parameters / options / boot-server file / customData object goes here */
252+
);
253+
254+
ViewData["SpaHtml"] = prerenderResult.Html;
255+
ViewData["Title"] = prerenderResult.Globals["title"];
256+
ViewData["Styles"] = prerenderResult.Globals["styles"];
257+
ViewData["Meta"] = prerenderResult.Globals["meta"];
258+
ViewData["Links"] = prerenderResult.Globals["links"];
259+
260+
return View(); // let's render the MVC View
261+
```
262+
263+
Take a look at the `_Layout.cshtml` file for example, notice how we let .NET handle and inject all our SEO magic (that we extracted from Angular itself) !
264+
265+
```html
266+
<!DOCTYPE html>
267+
<html>
268+
<head>
269+
<base href="/" />
270+
<!-- Title will be the one you set in your Angular application -->
271+
<title>@ViewData["Title"] - AspNET.Core Angular 4.0.0 (+) Universal starter</title>
272+
273+
<meta charset="utf-8" />
274+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
275+
@Html.Raw(ViewData["Meta"]) <!-- <meta /> tags -->
276+
@Html.Raw(ViewData["Links"]) <!-- <link /> tags -->
277+
278+
<link rel="stylesheet" href="~/dist/vendor.css" asp-append-version="true" />
279+
280+
@Html.Raw(ViewData["Styles"]) <!-- <style /> tags -->
281+
282+
</head>
283+
... etc ...
284+
```
285+
286+
Our `Views/Home/index.cshtml` simply renders the application and serves the bundled webpack files in it.
287+
288+
```html
289+
@Html.Raw(ViewData["SpaHtml"])
290+
291+
<script src="~/dist/vendor.js" asp-append-version="true"></script>
292+
@section scripts {
293+
<script src="~/dist/main-client.js" asp-append-version="true"></script>
294+
}
295+
```
296+
297+
### What happens after the App gets server rendered?
298+
299+
Well now, your Client-side Angular will take over, and you'll have a fully functioning SPA. (But we gained all these great SEO benefits of being server-rendered) !
300+
301+
:sparkles:
302+
124303

125304
----
126305

@@ -166,6 +345,42 @@ constructor(element: ElementRef, renderer: Renderer) {
166345
167346
----
168347
348+
----
349+
350+
# FAQ
351+
352+
### How can I disable Universal / SSR (Server-side rendering)?
353+
354+
Simply comment out the logic within HomeController, and replace `@Html.Raw(ViewData["SpaHtml"])` with just your applications root
355+
AppComponent tag ("app" in our case): `<app></app>`.
356+
357+
> You could also remove any `ifPlatformBrowser/etc` logic, and delete the boot-server, browser-app.module & server-app.module files, just make sure your `boot-client` file points to `app.module`.
358+
359+
### How do I have code run only in the Browser?
360+
361+
Check the [Universal Gotchas](#universal-gotchas) on how to use `isPlatformBrowser()`.
362+
363+
### How do I Material2 with this repo?
364+
365+
You'll either want to remove SSR for now, or wait as support should be coming to handle Universal/platform-server rendering.
366+
367+
### How can I use jQuery and/or some jQuery plugins with Angular Universal?
368+
369+
> Note: If at all possible, try to avoid using jQuery or libraries dependent on it, as there are
370+
better, more abstract ways of dealing with the DOM in Angular (2+) such as using the Renderer, etc.
371+
372+
Yes, of course but there are a few things you need to setup before doing this. First, make sure jQuery
373+
is included in webpack vendor file, and that you have a webpack Plugin setup for it. `new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' })`
374+
375+
Now, make sure any "plugins" etc that you have, are only included in your `boot-client.ts` file. (ie: `import 'slick-carousel';`)
376+
In a Component you want to use jQuery, make sure to import it near the top like so:
377+
378+
```typescript
379+
import * as $ from 'jquery';
380+
```
381+
382+
**Always make sure to wrap anything jQuery oriented in Angular's `isPlatformBrowser()` conditional!**
383+
169384
----
170385

171386
# Special Thanks
@@ -174,6 +389,7 @@ Many thanks go out to Steve Sanderson ([@SteveSandersonMS](https://github.com/St
174389

175390
Also thank you to the many Contributors !
176391
- [@AbrarJahin](https://github.com/AbrarJahin)
392+
- [@LiverpoolOwen](https://github.com/LiverpoolOwen)
177393
- [@hakonamatata](https://github.com/hakonamatata)
178394
- [@markwhitfeld](https://github.com/markwhitfeld)
179395
- [@Ketrex](https://github.com/Ketrex)
@@ -194,3 +410,7 @@ Copyright (c) 2016-2017 [Mark Pieszak](https://github.com/MarkPieszak)
194410

195411
Twitter: [@MarkPieszak](http://twitter.com/MarkPieszak) | Medium: [@MarkPieszak](https://medium.com/@MarkPieszak)
196412

413+
# Looking for Angular Consulting / Training / support?
414+
415+
[Contact me]([email protected]), and let's talk about your projects needs!
416+

0 commit comments

Comments
 (0)