Skip to content

Commit e775eea

Browse files
authored
Merge branch 'master' into feature/schematics_ng-add
2 parents 19b446e + b4eca1b commit e775eea

31 files changed

+440
-59
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ angularfire2-*.tgz
1212
.DS_Store
1313
yarn-error.log
1414
*.bak
15+
package-lock.json

Diff for: README.md

+15-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
- **Observable based** - Use the power of RxJS, Angular, and Firebase.
1111
- **Realtime bindings** - Synchronize data in realtime.
12-
- **Authentication** - Log users in with a variety of providers and monitor authentication state in realtime.
12+
- **Authentication** - Log users in with a variety of providers and monitor authentication state.
1313
- **Offline Data** - Store data offline automatically with AngularFirestore.
1414
- **Server-side Render** - Generate static HTML to boost perceived performance or create static sites.
1515
- **ngrx friendly** - Integrate with ngrx using AngularFire's action based APIs.
@@ -25,7 +25,7 @@
2525

2626
[Upgrading to v5.0? Check out our guide.](docs/version-5-upgrade.md)
2727

28-
**Having troubles?** Get help on the [Firebase Mailing List](https://groups.google.com/forum/#!forum/firebase-talk) (offically supported), the [Firebase Community Slack](https://firebase.community/) (look for the `#angularfire2` room), [Gitter](https://gitter.im/angular/angularfire2), or [Stack Overflow](https://stackoverflow.com/questions/tagged/angularfire2).
28+
**Having troubles?** Get help on the [Firebase Mailing List](https://groups.google.com/forum/#!forum/firebase-talk) (officially supported), the [Firebase Community Slack](https://firebase.community/) (look for the `#angularfire2` room), [Gitter](https://gitter.im/angular/angularfire2), or [Stack Overflow](https://stackoverflow.com/questions/tagged/angularfire2).
2929

3030
## Install
3131

@@ -92,17 +92,25 @@ Firebase offers two cloud-based, client-accessible database solutions that suppo
9292
### Upload files
9393
- [Getting started with Cloud Storage](docs/storage/storage.md)
9494

95-
### Universal
96-
- [Server-side Rendering with Universal](docs/server-side-rendering.md)
97-
9895
### Send push notifications
9996
- [Getting started with Firebase Messaging](docs/messaging/messaging.md)
10097

10198
### Directly call Cloud Functions
10299
- [Getting started with Callable Functions](docs/functions/functions.md)
103100

104-
### Deploy to Firebase Hosting
105-
- [Deploying AngularFire to Firebase Hosting](docs/deploying-angularfire-to-firebase.md)
101+
### Deploying your application
102+
103+
> Firebase Hosting is production-grade web content hosting for developers. With Hosting, you can quickly and easily deploy web apps and static content to a global content delivery network (CDN) with a single command.
104+
105+
- [Deploy your Angular application on Firebase Hosting](docs/deploying-angularfire-to-firebase.md)
106+
107+
#### Server-side rendering
108+
109+
> Angular Universal is a technology that allows you to run your Angular application on a server. This allows you to generate your HTML in a process called server-side rendering (SSR). Angularfire is compatible with server-side rendering; allowing you to take advantage of the Search Engine Optimization, link previews, the performance gains granted by the technology, and more. [Learn more about Angular Universal](https://angular.io/guide/universal).
110+
111+
- [Getting started with Angular Universal](docs/universal/getting-started.md)
112+
- [Deploying your Universal application on Cloud Functions for Firebase](docs/universal/cloud-functions.md)
113+
- [Prerendering your Universal application](docs/universal/prerendering.md)
106114

107115
### Ionic
108116

Diff for: docs/install-and-setup.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ You can optionally provide a custom FirebaseApp name by providing the `--firebas
4646

4747
By providing the `--all` flag you can also add modules for the individual @NgModules that your application needs:
4848

49-
- `AngularFirestoreModule`
5049
- `AngularFireAuthModule`
5150
- `AngularFireDatabaseModule`
51+
- `AngularFireFunctionsModule`
52+
- `AngularFirestoreModule`
5253
- `AngularFireStorageModule`
53-
- `AngularFireMessagingModule` (Future release)
54+
- `AngularFireMessagingModule`
5455

5556
### 4. Edit Firebase configuration
5657

Diff for: docs/ionic/cli.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,10 @@ export class AppModule {}
109109
After adding the AngularFireModule you also need to add modules for the individual @NgModules that your application needs.
110110
- AngularFireAuthModule
111111
- AngularFireDatabaseModule
112-
- AngularFireStorageModule (Future release)
113-
- AngularFireMessagingModule (Future release)
112+
- AngularFireFunctionsModule
113+
- AngularFirestoreModule
114+
- AngularFireStorageModule
115+
- AngularFireMessagingModule
114116

115117
#### Adding the Firebase Database and Auth Modules
116118

Diff for: docs/universal/cloud-functions.md

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Deploying your Universal application on Cloud Functions for Firebase
2+
3+
After [setting up your application with Angular Universal as outlined in Getting Started](getting-started.md), you're now ready to build your application for Firebase Hosting & Cloud Functions.
4+
5+
> Cloud Functions for Firebase lets you automatically run backend code in response to events triggered by Firebase features and HTTPS requests. Your code is stored in Google's cloud and runs in a managed environment. There's no need to manage and scale your own servers. [Learn more about Cloud Functions for Firebase](https://firebase.google.com/docs/functions/).
6+
7+
If you don't already have the Firebase CLI installed, do so:
8+
9+
```bash
10+
npm i -g @firebase-tools
11+
firebase login
12+
```
13+
14+
Then inside your project root, setup your Firebase CLI project:
15+
16+
```bash
17+
firebase init
18+
```
19+
20+
Configure whichever features you'd want to manage but make sure to select at least `functions` and `hosting`. Choose Typescript for Cloud Functions and use the default `public` directory for Hosting.
21+
22+
After you're configured, you should now see a `firebase.json` file in your project root. Let's add the following `rewrites` directive to it:
23+
24+
```js
25+
{
26+
// ...
27+
"hosting": {
28+
// ...
29+
"rewrites": [
30+
{ "source": "**", "function": "universal" }
31+
]
32+
}
33+
}
34+
```
35+
36+
This will inform Firebase Hosting that it should proxy all requests to Cloud Functions, if a file isn't already present in the hosting directory.
37+
38+
Let's go ahead and modify your `package.json` to build for Cloud Functions:
39+
40+
```js
41+
"scripts": {
42+
// ... omitted
43+
"build": "ng build && npm run copy:hosting && npm run build:ssr && npm run build:functions",
44+
"copy:hosting": "cp -r ./dist/YOUR_PROJECT_NAME/* ./public && rm ./public/index.html",
45+
"build:functions": "npm run --prefix functions build"
46+
},
47+
```
48+
49+
Change the build script in your `functions/package.json` to the following:
50+
51+
```js
52+
"scripts": {
53+
// ... omitted
54+
"build": "rm -r ./dist && cp -r ../dist . && tsc",
55+
}
56+
```
57+
58+
Finally, add the following to your `functions/src/index.ts`:
59+
60+
```ts
61+
export const universal = functions.https.onRequest((request, response) => {
62+
require(`${process.cwd()}/dist/YOUR_PROJECT_NAME-webpack/server`).app(request, response);
63+
});
64+
```
65+
66+
We you should now be able to run `npm run build` to build your project for Firebase Hosting and Cloud Functions.
67+
68+
To test, spin up the emulator with `firebase serve`. Once you've confirmed it's working go ahead and `firebase deploy`.
69+
70+
### [Next Step: Prerendering your Universal application](prerendering.md)
71+
72+
## Additional Resources
73+
74+
- [Universal Starter Template](https://github.com/angular/universal-starter)
75+
- [AngularFirebase SSR Videos](https://angularfirebase.com/tag/ssr/)
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# Server-side Rendering with Universal
1+
# Getting started with AngularFire and Universal
22

33
Server-side rendering (SSR) is the process of converting a JavaScript app to plain HTML at request-time, allowing search engine crawlers and linkbots to understand page content reliably.
44

55
## 0. Prerequisites
66

77
- @angular/cli >= v6.0
8-
- angularfire2 >= v5.0.0-rc.7
8+
- @angular/fire >= v5.0.0
99

1010
## 1. Generate the Angular Universal Server Module
1111

@@ -19,8 +19,8 @@ ng generate universal --client-project <your-project>
1919

2020
[ExpressJS](https://expressjs.com/) is a lightweight web framework that can serve http requests in Node. First, install the dev dependencies:
2121

22-
```
23-
npm install --save-dev express webpack-cli ts-loader ws xmlhttprequest
22+
```bash
23+
npm install --save-dev @nguniversal/express-engine @nguniversal/module-map-ngfactory-loader express webpack-cli ts-loader ws xhr2
2424
```
2525

2626
Create a file called `server.ts` in the root of you project.
@@ -30,41 +30,38 @@ Create a file called `server.ts` in the root of you project.
3030
import 'zone.js/dist/zone-node';
3131
import 'reflect-metadata';
3232

33-
import { renderModuleFactory } from '@angular/platform-server';
3433
import { enableProdMode } from '@angular/core';
34+
import { ngExpressEngine } from '@nguniversal/express-engine';
35+
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
3536

3637
import * as express from 'express';
3738
import { join } from 'path';
3839
import { readFileSync } from 'fs';
3940

40-
// Required for Firebase
41+
// Polyfills required for Firebase
4142
(global as any).WebSocket = require('ws');
42-
(global as any).XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
43-
43+
(global as any).XMLHttpRequest = require('xhr2');
4444

4545
// Faster renders in prod mode
4646
enableProdMode();
4747

48-
// Express server
49-
const app = express();
48+
// Export our express server
49+
export const app = express();
5050

51-
const PORT = process.env.PORT || 4000;
5251
const DIST_FOLDER = join(process.cwd(), 'dist');
53-
const APP_NAME = 'YOUR_PROJECT_NAME';
52+
const APP_NAME = 'YOUR_PROJECT_NAME'; // TODO: replace me!
5453

55-
const { AppServerModuleNgFactory } = require(`./dist/${APP_NAME}-server/main`);
54+
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require(`./dist/${APP_NAME}-server/main`);
5655

5756
// index.html template
5857
const template = readFileSync(join(DIST_FOLDER, APP_NAME, 'index.html')).toString();
5958

60-
app.engine('html', (_, options, callback) => {
61-
renderModuleFactory(AppServerModuleNgFactory, {
62-
document: template,
63-
url: options.req.url,
64-
}).then(html => {
65-
callback(null, html);
66-
});
67-
});
59+
app.engine('html', ngExpressEngine({
60+
bootstrap: AppServerModuleNgFactory,
61+
providers: [
62+
provideModuleMap(LAZY_MODULE_MAP)
63+
]
64+
}));
6865

6966
app.set('view engine', 'html');
7067
app.set('views', join(DIST_FOLDER, APP_NAME));
@@ -77,31 +74,44 @@ app.get('*', (req, res) => {
7774
res.render(join(DIST_FOLDER, APP_NAME, 'index.html'), { req });
7875
});
7976

80-
// Start up the Node server
81-
app.listen(PORT, () => {
82-
console.log(`Node server listening on http://localhost:${PORT}`);
83-
});
77+
// If we're not in the Cloud Functions environment, spin up a Node server
78+
if (!process.env.FUNCTION_NAME) {
79+
const PORT = process.env.PORT || 4000;
80+
app.listen(PORT, () => {
81+
console.log(`Node server listening on http://localhost:${PORT}`);
82+
});
83+
}
8484
```
8585

8686
## 3. Add a Webpack Config for the Express Server
8787

88-
Create a new file named `webpack.server.config.js` to bundle the express app from previous step.
88+
Create a new file named `webpack.server.config.js` to bundle the express app from previous step.
8989

9090

9191
```js
9292
const path = require('path');
9393
const webpack = require('webpack');
9494

95-
const APP_NAME = 'YOUR_PROJECT_NAME';
95+
const APP_NAME = 'YOUR_PROJECT_NAME'; // TODO: replace me!
9696

9797
module.exports = {
9898
entry: { server: './server.ts' },
9999
resolve: { extensions: ['.js', '.ts'] },
100100
mode: 'development',
101101
target: 'node',
102-
externals: [/(node_modules|main\..*\.js)/],
102+
externals: [
103+
/* Firebase has some troubles being webpacked when in
104+
in the Node environment, let's skip it.
105+
Note: you may need to exclude other dependencies depending
106+
on your project. */
107+
/^firebase/
108+
],
103109
output: {
104-
path: path.join(__dirname, `dist/${APP_NAME}`),
110+
// Export a UMD of the webpacked server.ts & deps, for
111+
// rendering in Cloud Functions
112+
path: path.join(__dirname, `dist/${APP_NAME}-webpack`),
113+
library: 'app',
114+
libraryTarget: 'umd',
105115
filename: '[name].js'
106116
},
107117
module: {
@@ -126,29 +136,18 @@ module.exports = {
126136

127137
## 4.0 Build Scripts
128138

129-
Update your `package.json` with the following build scripts.
139+
Update your `package.json` with the following build scripts, replacing `YOUR_PROJECT_NAME` with the name of your project.
130140

131141
```js
132142
"scripts": {
133143
// ... omitted
134-
"build:ssr": "ng build --prod && ng run YOUR_PROJECT_NAME:server && npm run webpack:ssr",
135-
"serve:ssr": "node dist/YOUR_PROJECT_NAME/server.js",
136-
"webpack:ssr": "webpack --config webpack.server.config.js"
144+
"build": "ng build && npm run build:ssr",
145+
"build:ssr": "ng run YOUR_PROJECT_NAME:server && npm run webpack:ssr",
146+
"webpack:ssr": "webpack --config webpack.server.config.js",
147+
"serve:ssr": "node dist/YOUR_PROJECT_NAME-webpack/server.js"
137148
},
138149
```
139150

140-
Test your app locally by running `npm run build:ssr && npm run serve:ssr`.
141-
142-
## 5.0 Deployment
143-
144-
With an existing Firebase project, you can easily deploy your ExpressJS server to [App Engine Flex](https://cloud.google.com/appengine/docs/flexible/) (Note: This is a paid service based on resource allocation).
145-
146-
147-
1. Install [gcloud CLI tools](https://cloud.google.com/sdk/gcloud/) and authenticate.
148-
2. Change the start script in package.json to `"start": "npm run serve:ssr"`
149-
2. Run `gcloud app deploy` and you're on the cloud.
150-
151-
## Additional Resources
151+
Test your app locally by running `npm run build && npm run serve:ssr`.
152152

153-
- [Universal Starter Template](https://github.com/angular/universal-starter)
154-
- [AngularFirebase SSR Videos](https://angularfirebase.com/tag/ssr/)
153+
### [Next Step: Deploying your Universal application on Cloud Functions for Firebase](cloud-functions.md)

0 commit comments

Comments
 (0)