How to set up Angular cli + Angular universal?

前端 未结 3 1986
梦毁少年i
梦毁少年i 2020-12-05 08:41

Anyone have experience with installing angular universal with angular cli projects?

I tried to follow this guide:

https://universal.angular.io/quickstart/

相关标签:
3条回答
  • 2020-12-05 09:15

    Angular Cli now supports this in version 1.3.0-rc.0 and up.

    You can install this version using

    npm install -g @angular/cli


    Setup Instructions from Angular Cli Wiki on Universal Rendering

    I have a demo app which can be found on GitHub

    Source: https://github.com/joejordanbrown/angular-cli-universal

    Live Demo: https://uixd.co.uk/open-source-software/angular-cli-universal/


    Step 1: Create new Angular Cli App

    $ ng new angular-cli-universal
    

    Step 2: Install @angular/platform-server

    Install @angular/platform-server into your project. Make sure you use the same version as the other @angular packages in your project.

    $ npm install --save-dev @angular/platform-server
    

    or

    $ yarn add @angular/platform-server
    

    Step 3: Prepare your app for Universal rendering

    The first thing you need to do is make your AppModule compatible with Universal by adding .withServerTransition() and an application ID to your BrowserModule import:

    src/app/app.module.ts:

    @NgModule({
      bootstrap: [AppComponent],
      imports: [
        // Add .withServerTransition() to support Universal rendering.
        // The application ID can be any identifier which is unique on
        // the page.
        BrowserModule.withServerTransition({appId: 'my-app'}),
        ...
      ],
    
    })
    export class AppModule {}
    

    Next, create a module specifically for your application when running on the server. It's recommended to call this module AppServerModule.

    This example places it alongside app.module.ts in a file named app.server.module.ts:

    src/app/app.server.module.ts:

    import {NgModule} from '@angular/core';
    import {ServerModule} from '@angular/platform-server';
    
    import {AppModule} from './app.module';
    import {AppComponent} from './app.component';
    
    @NgModule({
      imports: [
        // The AppServerModule should import your AppModule followed
        // by the ServerModule from @angular/platform-server.
        AppModule,
        ServerModule,
      ],
      // Since the bootstrapped component is not inherited from your
      // imported AppModule, it needs to be repeated here.
      bootstrap: [AppComponent],
    })
    export class AppServerModule {}
    

    Step 4: Create a server main file and tsconfig to build it

    Create the main file for your Universal bundle. This file only needs to export your AppServerModule. It can go in src. This example calls this file main.server.ts:

    src/main.server.ts:

    export {AppServerModule} from './app/app.server.module';
    

    Copy tsconfig.app.json to tsconfig-server.json and change it to build with a "module" target of "commonjs".

    Add a section for "angularCompilerOptions" and set "entryModule" to your AppServerModule, specified as a path to the import with a hash (#) containing the symbol name. In this example, this would be src/app/app.server.module#AppServerModule.

    src/tsconfig.server.json:

    {
      "extends": "../tsconfig.json",
      "compilerOptions": {
        "outDir": "../out-tsc/app",
        "baseUrl": "./",
        // Set the module format to "commonjs":
        "module": "commonjs",
        "types": []
      },
      "exclude": [
        "test.ts",
        "**/*.spec.ts"
      ],
      // Add "angularCompilerOptions" with the AppServerModule you wrote
      // set as the "entryModule".
      "angularCompilerOptions": {
        "entryModule": "app/app.server.module#AppServerModule"
      }
    }
    

    Step 5: Create a NodeJS server file You need to create a NodeJS server to render and serve the app. This example uses express.

    Install express and compression

    $ npm install --save express compression @nguniversal/express-engine
    

    or

    $ yarn add express compression @nguniversal/express-engine
    

    src/express.server.js:

    const path = require('path');
    const fs = require('fs');
    const express = require('express');
    const compression = require('compression');
    const ngExpressEngine = require('@nguniversal/express-engine').ngExpressEngine;
    
    require('zone.js/dist/zone-node');
    require('rxjs/add/operator/filter');
    require('rxjs/add/operator/map');
    require('rxjs/add/operator/mergeMap');
    
    var hash;
    fs.readdirSync(__dirname).forEach(file => {
      if (file.startsWith('main')) {
        hash = file.split('.')[1];
      }
    });
    
    const AppServerModuleNgFactory = require('./main.' + hash + '.bundle').AppServerModuleNgFactory;
    
    const app = express();
    const port = Number(process.env.PORT || 8080);
    
    app.engine('html', ngExpressEngine({
      baseUrl: 'http://localhost:' + port,
      bootstrap: AppServerModuleNgFactory
    }));
    
    
    app.set('view engine', 'html');
    app.set('views', path.join(__dirname, '/../browser'));
    
    app.use(compression());
    app.use('/', express.static(path.join(__dirname, '/../browser'), {index: false}));
    
    
    app.get('/*', function (req, res) {
      res.render('index', {
        req: req,
        // res: res
      });
    });
    
    app.listen(port, function() {
      console.log(`Listening at ${port}`);
    });
    

    Step 6: Create a new project in .angular-cli.json

    In .angular-cli.json there is an array under the key "apps". Copy the configuration for your client application there, and paste it as a new entry in the array, with an additional key "platform" set to "server".

    Then, remove the "polyfills" key - those aren't needed on the server and adjust "main", and "tsconfig" to point to the files you wrote in step 2. Finally, adjust "outDir" to a new location (this example uses dist/server).

    .angular-cli.json:

    {
      ...
      "apps": [
        {
          // Keep your original application config the same apart from changing outDir to dist/browser.
          // It will be app 0.
          "outDir": "dist/browser",
        },
        {
          // This is your server app. It is app 1.
          "platform": "server",
          "root": "src",
          // Build to dist/server instead of dist. This prevents
          // client and server builds from overwriting each other.
          "outDir": "dist/server",
          "assets": [
            "assets",
            "favicon.ico",
            "express.server.js"
          ],
          "index": "index.html",
          // Change the main file to point to your server main.
          "main": "main.server.ts",
          // Remove polyfills.
          // "polyfills": "polyfills.ts",
          "test": "test.ts",
          // Change the tsconfig to point to your server config.
          "tsconfig": "tsconfig.server.json",
          "testTsconfig": "tsconfig.spec.json",
          "prefix": "app",
          "styles": [
            "styles.css"
          ],
          "scripts": [],
          "environmentSource": "environments/environment.ts",
          "environments": {
            "dev": "environments/environment.ts",
            "prod": "environments/environment.prod.ts"
          }
        }
      ],
      ...
    }
    

    Building the bundle

    With these steps complete, you should be able to build a server bundle for your application, using the --app flag to tell the CLI to build the server bundle, referencing its index of 1 in the "apps" array in .angular-cli.json:

    # This builds the client application in dist/browser/
    $ ng build --prod
    ...
    # This builds the server bundle in dist/server/
    $ ng build --prod --app 1
    Date: 2017-07-24T22:42:09.739Z
    Hash: 9cac7d8e9434007fd8da
    Time: 4933ms
    chunk {0} main.988d7a161bd984b7eb54.bundle.js (main) 9.49 kB [entry] [rendered]
    chunk {1} styles.d41d8cd98f00b204e980.bundle.css (styles) 0 bytes [entry] [rendered]
    

    Starting the express server

    $ node dist/server/express.server.js
    

    View the Angular Cli Wiki for more details https://github.com/angular/angular-cli/wiki/stories-universal-rendering

    0 讨论(0)
  • 2020-12-05 09:34

    You can use universal-cli from https://github.com/devCrossNet/angular-cli

    It is a fork from angular-cli but this work with angular universal.

    After you intalled with npm install -g universal-cli create a new project with

    ung new PROJECT_NAME --universal

    Then the project should be ready to serve with

    cd PROJECT_NAME ung serve

    I have not tested with a existing angular-cli project but maybe ung init --universal could help

    0 讨论(0)
  • 2020-12-05 09:35

    Now Angular-cli 1.3 has been released the documentation has been updated to cover Universal with a guide here. There is a guide and sample for getting it all working with Universal + material 2 and an Express server here.

    0 讨论(0)
提交回复
热议问题