Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(universal): fix issues with inconsistent documentation #3268

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ The official [Angular](https://angular.io/) library for [Firebase](https://fireb

<strong><pre>ng add @angular/fire</pre></strong>

AngularFire smooths over the rough edges an Angular developer might encounter when implementing the framework-agnostic [Firebase JS SDK](https://github.com/firebase/firebase-js-sdk) & aims to provide a more natural developer experience by conforming to Angular conventions.
_Note: If you want to ng add AngularFire and will be using Hosting/Cloud Functions, you need to configure the
Firebase CLI first so that you are logged in for the schematics that are run as part of `ng add @angular/fire`.
Follow [this guide](docs/install-firebase-tools.md) to have the Firebase CLI walk you through the setup._

AngularFire smooths over the rough edges an Angular developer might encounter when implementing the framework-agnostic
[Firebase JS SDK](https://github.com/firebase/firebase-js-sdk) & aims to provide a more natural developer experience
by conforming to Angular conventions.

- **Dependency injection** - Provide and Inject Firebase services in your components
- **Zone.js wrappers** - Stable zones allow proper functionality of service workers, forms, SSR, and pre-rendering
Expand Down
78 changes: 78 additions & 0 deletions docs/install-firebase-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Firebase Tools Install and Setup

### 1. Install package

```bash
npm install -g firebase-tools
```

or with `yarn`

```bash
yarn global add firebase-tools
```

You can also choose to install it as a dependency for your project rather than globally

```bash
npm install --save-dev firebase-tools
```

or with `yarn`

```bash
yarn add -D firebase-tools
```

### 2. Configure Firebase Tools

In your projects root directory run:

```bash
firebase init
```

or if your installed it within your project rather than globally

```bash
npx firebase init
```

or with `yarn`

```bash
yarn firebase init
```

This will ask you to login if you are not logged in already, the process will take you through a browser
redirect to log you into Firebase.

### 3. Choose what Firebase features

`firebase-tools` displays Firebase features you want to configure.

```bash
? Which Firebase features do you want to set up for this directory? Press Space
to select features, then Enter to confirm your choices. (Press <space> to select
, <a> to toggle all, <i> to invert selection, and <enter> to proceed)
◯ Realtime Database: Configure a security rules file for Realtime Database and
(optionally) provision default instance
◯ Firestore: Configure security rules and indexes files for Firestore
◯ Functions: Configure a Cloud Functions directory and its files
◯ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub
Action deploys
◯ Hosting: Set up GitHub Action deploys
(Move up and down to reveal more choices)
```

### 4. Connect your repo to a Firebase project

The CLI will then walk you through making sure your repo is configured with a Firebase project.

```bash
? Please select an option:
◯ Use an existing project
◯ Create a new project
◯ Add Firebase to an existing Google Cloud Platform project
◯ Don't set up a default project
```
33 changes: 27 additions & 6 deletions docs/universal/cloud-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ Let's go ahead and modify your `package.json` to build for Cloud Functions:
```js
"scripts": {
// ... omitted
"build": "ng build && npm run copy:hosting && npm run build:ssr && npm run build:functions",
"copy:hosting": "cp -r ./dist/YOUR_PROJECT_NAME/* ./public && rm ./public/index.html",
"build": "ng build && npm run build:ssr && npm run copy:hosting && npm run build:functions",
"copy:hosting": "cp -r ./dist/YOUR_PROJECT_NAME/* ./public && rm -f ./public/index.html",
"build:functions": "npm run --prefix functions build"
},
```
Expand All @@ -51,21 +51,42 @@ Change the build script in your `functions/package.json` to the following:
```js
"scripts": {
// ... omitted
"build": "rm -r ./dist && cp -r ../dist . && tsc",
"build": "rm -rf ./dist && cp -r ../dist . && tsc",
}
```

You will either need to install the dependencies from the `functions/package.json` or add them to your root `package.json`.

Finally, add the following to your `functions/src/index.ts`:

```ts
export const universal = functions.https.onRequest((request, response) => {
require(`${process.cwd()}/dist/YOUR_PROJECT_NAME-webpack/server`).app(request, response);
require(`${process.cwd()}/dist/YOUR_PROJECT_NAME/server/main`).app()(request, response);
});
```

We you should now be able to run `npm run build` to build your project for Firebase Hosting and Cloud Functions.
In the `server.ts` file generated by the Angular CLI ensure that the `index.html` is being read from the correct place.

As of writing the Angular CLI generates:

```typescript
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index.html';
```

this needs to be changed to:

```typescript
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : join(distFolder, 'index.html');
```

So that the `index.html` is read from the correct `dist` folder.

You should now be able to run `npm run build` to build your project for Firebase Hosting and Cloud Functions.

To test, spin up the emulator with `firebase serve`. Once you've confirmed its working go ahead and `firebase deploy`.

To test, spin up the emulator with `firebase serve`. Once you've confirmed it's working go ahead and `firebase deploy`.
_Note: Universal will now SSR your application and serve it, depending on how you have your deployment setup some assets may fail to
serve because the Cloud Function is at a different route than the `APP_BASE_REF` configured._

### [Next Step: Prerendering your Universal application](prerendering.md)

Expand Down
143 changes: 9 additions & 134 deletions docs/universal/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,147 +7,22 @@ Server-side rendering (SSR) is the process of converting a JavaScript app to pla
- @angular/cli >= v6.0
- @angular/fire >= v5.0.0

## 1. Generate the Angular Universal Server Module
## 1. Add Angular Universal to your project

First, create a server module with the Angular CLI.
Follow the steps from the [Angular Universal Tutorial](https://angular.io/guide/universal) to add Universal to your
project.

```
ng generate universal --client-project <your-project>
ng add @nguniversal/express-engine
```

## 2. Build a Server with ExpressJS
This will create all the files you need and setup all the configurations for Universal rendering for your application.

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

```bash
npm install --save-dev @nguniversal/express-engine @nguniversal/module-map-ngfactory-loader express webpack-cli ts-loader ws xhr2
```

Create a file called `server.ts` in the root of you project.

```ts
// These are important and needed before anything else
import 'zone.js/dist/zone-node';
import 'reflect-metadata';

import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';

// Polyfills required for Firebase
(global as any).WebSocket = require('ws');
(global as any).XMLHttpRequest = require('xhr2');

// Faster renders in prod mode
enableProdMode();

// Export our express server
export const app = express();

const DIST_FOLDER = join(process.cwd(), 'dist');
const APP_NAME = 'YOUR_PROJECT_NAME'; // TODO: replace me!

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

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

app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));

app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, APP_NAME));

// Serve static files
app.get('*.*', express.static(join(DIST_FOLDER, APP_NAME)));

// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render(join(DIST_FOLDER, APP_NAME, 'index.html'), { req });
});

// If we're not in the Cloud Functions environment, spin up a Node server
if (!process.env.FUNCTION_NAME) {
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});
}
```

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

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


```js
const path = require('path');
const webpack = require('webpack');

const APP_NAME = 'YOUR_PROJECT_NAME'; // TODO: replace me!

module.exports = {
entry: { server: './server.ts' },
resolve: { extensions: ['.js', '.ts'] },
mode: 'development',
target: 'node',
externals: [
/* Firebase has some troubles being webpacked when in
in the Node environment, let's skip it.
Note: you may need to exclude other dependencies depending
on your project. */
/^firebase/
],
output: {
// Export a UMD of the webpacked server.ts & deps, for
// rendering in Cloud Functions
path: path.join(__dirname, `dist/${APP_NAME}-webpack`),
library: 'app',
libraryTarget: 'umd',
filename: '[name].js'
},
module: {
rules: [
{ test: /\.ts$/, loader: 'ts-loader' }
]
},
plugins: [
new webpack.ContextReplacementPlugin(
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
}
```

## 4.0 Build Scripts

Update your `package.json` with the following build scripts, replacing `YOUR_PROJECT_NAME` with the name of your project.

```js
"scripts": {
// ... omitted
"build": "ng build && npm run build:ssr",
"build:ssr": "ng run YOUR_PROJECT_NAME:server && npm run webpack:ssr",
"webpack:ssr": "webpack --config webpack.server.config.js",
"serve:ssr": "node dist/YOUR_PROJECT_NAME-webpack/server.js"
},
```
Test your app locally by running `npm run dev:ssr`.

Test your app locally by running `npm run build && npm run serve:ssr`.
_Note: `dev:ssr` is a command that was added to your `package.json` by the `ng add` command that will run the dev server
for your Angular with Universal._

### [Next Step: Deploying your Universal application on Cloud Functions for Firebase](cloud-functions.md)
Loading