【问题标题】:How to deploy an Angular 4 app with server-side rendering on prod server如何在 prod 服务器上部署具有服务器端渲染的 Angular 4 应用程序
【发布时间】:2018-02-15 05:45:30
【问题描述】:

我一直在寻找大约 3 个小时来在启用了“服务器端渲染”的服务器上托管 Angular 4 应用程序。 注意 - 我有一个安装了 Apache (Ubuntu) 的 AWS 服务器。

首先,我已经知道如何托管 Angular 4 应用程序(没有服务器端渲染)。但在这里我主要关心的是我想让我的应用程序启用 - 服务器端渲染。

在我的本地,我使用npm start 命令,它会自动在 - http://localhost:4000 上为应用程序提供服务(启用服务器端渲染)

我的package.json 文件如下所示:

...
"scripts": {
    "serve": "ng serve",
    "prestart": "ng build --prod && ngc && webpack",
    "start": "node dist/server.js",
    "build": "ng build"
},
...

所有这些命令都运行良好。但我很困惑,我应该再次运行

npm start

在生产服务器上,因此它还需要node_modules 才能安装。在我看来,哪种方式不正确?

谁能帮我托管启用“服务器端渲染”的应用程序。

【问题讨论】:

  • 奇怪的是,下面的回答者都没有打扰到你的问题,直到最后。我刚刚通过 Nginx 部署了我的角度 SSR 和代理,并且遇到了一些静态文件未显示的问题
  • @Rexford 是的,你是对的......我很震惊,没有人正确回答我的问题,他们正在回答他们喜欢的......实际上我也在做同样的事情和你一样,但我用的是 apache。
  • 我在下面分享了我如何在生产环境中运行我的 SSR Angular 应用程序。我希望它有所帮助。
  • 我还写了一篇关于如何使用 Angular 4 实现服务器端渲染的文章 - blog.squareboat.com/…
  • @Saumya Rastogi 是否可以在 Sentora 服务上部署 Angular 项目?请告诉我我需要知道。

标签: node.js angular server-side-rendering


【解决方案1】:

其实很简单。

使用 shell 进入 Angular 4 项目的目录。 并这样做:

$ ng build --prod

这将编译应用程序,结果位于 Angular 应用程序根目录的 dist 文件夹中。

现在您只需将 dist 文件夹的内容放入 HTTP 服务器并吃爆米花。

很高兴, 杰里·永布森。

【讨论】:

  • 我想你实际上没有仔细阅读我的问题。正如我的问题中提到的那样,您给出的解决方案已经为我所知。我想要在启用服务器端渲染的情况下托管应用程序的解决方案...
【解决方案2】:

好的,很抱歉我错过了阅读您的问题:)。

首先,Apache 不再需要为您的应用程序提供服务。这是因为 node.js 会为你服务。

因此,如果您的服务器上不需要 apache 服务,您应该出于安全问题将其禁用,并可能避免应用程序之间的端口冲突。

需要服务器渲染来修改您的 Angular 应用程序。让我们开始吧。

1) 转到您的 Angular 项目并安装这些软件包:

npm i -S @angular/platform-server @angular/animations express

2) 打开 src/app/app.module.ts 并用您的应用名称修改下面的注释行。

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'your-angular-app-name' }), // You just have to change this line
    FormsModule,
    HttpModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

3) 现在,我们将在您的应用中设置服务器。为此,请在以下代码中创建文件 app/src/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: [
    ServerModule, // Load the servermodule
    AppModule     // Load the modules of AppModule
],
bootstrap: [AppComponent]
})
export class AppServerModule { }

4) 创建文件 src/server.ts 并添加以下代码。这是节点服务器。

import 'reflect-metadata';
import 'zone.js/dist/zone-node';
import { platformServer, renderModuleFactory } from '@angular/platform-server';
import { enableProdMode } from '@angular/core';
import { AppServerModuleNgFactory } from '../dist/ngfactory/src/app/app.server.module.ngfactory';
import * as express from 'express';
import { readFileSync } from 'fs';
import { join } from 'path';
const PORT = 4000;
enableProdMode();
const app = express();
let template = readFileSync(join(__dirname, '..', 'dist', 'index.html')).toString();
app.engine('html', (_, options, callback) => {
  const opts = { document: template, url: options.req.url };
  renderModuleFactory(AppServerModuleNgFactory, opts)
    .then(html => callback(null, html));
});
app.set('view engine', 'html');
app.set('views', 'src');
app.get('*.*', express.static(join(__dirname, '..', 'dist')));
app.get('*', (req, res) => {
  res.render('index', { req });
});
app.listen(PORT, () => {
  console.log(`Listening on http://localhost:${PORT}...`);
});

5) 打开 src/tsconfig.app.json 并将文件 server.ts 添加到 exclude json 变量中。

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "module": "es2015",
    "baseUrl": "",
    "types": []
  },
  "exclude": [
    "server.ts", # Just here !
    "test.ts",
    "**/*.spec.ts"
  ]
}

6) 打开 tsconfig.json 定位到您的项目的根目录并添加 angularCompilerOptions,如下所示:

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "baseUrl": "src",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2016",
      "dom"
    ]
  },
  "angularCompilerOptions": { 
    "genDir": "./dist/ngfactory",
    "entryModule": "./src/app/app.module#AppModule"
  }  
}

7) 现在,修改您的 package.json,让您的生活更轻松。

{
  "scripts": {
    "prestart": "ng build --prod && ngc",
    "start": "ts-node src/server.ts", 
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
}

8) 现在您可以使用以下方法测试您的应用:

npm start

希望对你有帮助。

注意: 如果您的项目已经存在,您可能会遇到一些模块(如 Angular Material)的问题,因为 node.js 不知道窗口对象、文档对象。

所以,你必须:

  • 创建app.common.module.ts,其他模块加载文件将继承。并收集通用模块(客户端+服务器)。

  • 最后把困扰我们的模块放到app.module.ts中。

Cdly。

【讨论】:

  • 抱歉,我认为这不能回答我的问题。我不是要求构建项目。您在上面谈到的方式与我正在实施的方式相同,但我的问题是 - 如何在服务器上提供该特定应用程序?我想要实现它!
【解决方案3】:

no 7 package.jsno 脚本有重复的启动脚本。

我们还需要共享主机帐户中不包含的服务器支持。

【讨论】:

    【解决方案4】:

    谁能帮我托管启用“服务器端渲染”的应用程序。

    是的。不幸的是,我使用 Nginx。但是,这种方法在 Apache 等中应该没有什么不同。

    这就是我在生产中托管我的服务器端渲染 Angular 应用程序的方式(我正在做)。我写了一篇关于它的文章on my blog

    构建你的 SSR 后,你应该有这样的东西:

    在您设法将 dist/ 文件夹中的所有内容发送到远程服务器后,您使用 pm2 运行它(这是我用来运行我的节点应用程序的)

    运行pm2 start path/to/dist/server.js --name name_of_process

    它应该在localhost:4000上运行

    下面的 Nginx 虚拟服务器块应该将所有请求通过 Nginx 代理到服务器端渲染 Angular 应用程序。

    下面的 nginx 配置实际上为您的角度 SSR 提供​​静态服务,并在请求不是针对静态文件时回退到代理。

    upstream ssr_khophi_nodejs {
        server 127.0.0.1:4000;
    }
    
    server {
        listen 443 ssl http2;
    
        server_name staging.khophi.com; # <--- Change this part
    
        include /etc/nginx/ssl/ssl-params.conf;# <--- Ignore this part if not using SSL
        include /etc/nginx/ssl/khophi.com.ssl;# <--- Ignore this part if not using SSL
    
        root /home/khophi/khophi.com/ssr/dist/browser; # <-- Notice where we're point to
    
       location / {
            try_files $uri $uri @backend; # <--- This looks for requests (statics i.e js/css/fonts)
                                          # in /ssr/dist/browser folder. If nothing found, calls @backend
        }
    
        location @backend {
            # NOTE THERE IS NO TRAILING SLASH AT THE END. NO TRAILING SLASH. NO SLASH. NO!
            proxy_pass http://ssr_khophi_nodejs; # <--- THIS DOES NOT HAVE A TRAILING '/'
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_http_version 1.1;
            proxy_set_header X-NginX-Proxy true;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_cache_bypass $http_upgrade;
            proxy_redirect off;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
    
    server {
        listen 80;
        server_name staging.khophi.com;
        return 301 https://$server_name$request_uri?;
    }
    

    希望对你有帮助。

    【讨论】:

    • 感谢您的回答,但我必须在 apache 上实现它。我已经弄清楚如何为服务器端渲染做准备。我还在 Medium 上写了一篇文章 - blog.squareboat.com/…
    • @SaumyaRastogi 你的博客只是关于服务器端渲染的实现。没找到你是怎么在服务器上部署的?
    • 客户端/最终用户不会将“pm2 start path/to/dist/server.js --name name_of_process”放在服务器端。客户端只输入一个url如何加载应用页面?
    • @SunilKumar 如果我理解,您想在不使用终端的情况下运行pm2 start path/to/dist/server.js --name name_of_process?如果是这样,我不知道有任何其他方法可以让您的应用通过 URL 运行。
    • @KhoPhi 是否可以在 Sentora 服务器上部署 Angular 项目?请告诉我我需要知道。
    猜你喜欢
    • 2018-03-21
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 2018-07-05
    相关资源
    最近更新 更多