简体   繁体   English

Angular SSR 在 docker NGINX 中不起作用

[英]Angular SSR is not working in docker NGINX

I added angualr universal to my app.我在我的应用程序中添加了 angualr Universal。

When I run commands:当我运行命令时:

npm run build:ssr
npm run serve:ssr

SSR rendering works fine. SSR 渲染工作正常。

But when I run my app in docker SSR isn't work I see only my static index.html in page source.但是当我在 docker SSR 中运行我的应用程序时,我在页面源代码中只看到我的 static index.html。

This is my server.ts:这是我的 server.ts:

import 'zone.js/dist/zone-node';

import {APP_BASE_HREF} from '@angular/common';
import {ngExpressEngine} from '@nguniversal/express-engine';
import * as express from 'express';
import {existsSync} from 'fs';
import {join} from 'path';

import {AppServerModule} from './src/main.server';
const compression = require('compression');

// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/my-app-frontend/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  server.use(compression());

  // Our Universal express-engine (found @ https://github.com/angular/universal/tree/main/modules/express-engine)
  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }));

  server.set('view engine', 'html');
  server.set('views', distFolder);

  // Example Express Rest API endpoints
  // server.get('/api/**', (req, res) => { });
  // Serve static files from /browser
  server.get('*.*', express.static(distFolder, {
    maxAge: '1y'
  }));

  // All regular routes use the Universal engine
  server.get('*', (req, res) => {
    res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
  });

  return server;
}

function run(): void {
  const port = process.env['PORT'] || 4200;

  // Start up the Node server
  const server = app();
  server.listen(port, () => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
  run();
}

export * from './src/main.server';

This is my Dockerfile :这是我的Dockerfile

    FROM node:16.17.0-alpine3.16 AS node
    
    WORKDIR /frontend
    
    COPY package*.json ./
    
    RUN npm install
    
    COPY . .
    
    RUN npm run build:ssr

This is my docker-compose.yml :这是我的docker-compose.yml

version: '3'
    
...
    
  frontend:
    container_name: my-app-docker-frontend
    build: ./frontend
    restart: unless-stopped
    command: npm run serve:ssr
    networks:
      - my-app-docker-network

  nginx:
    image: nginx:stable
    container_name: my-app-docker-nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./data/nginx:/etc/nginx/conf.d
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    depends_on:
      - frontend
      - backend
    networks:
      - my-app-docker-network
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"


volumes:
  my-app-docker-db: { }

networks:
  my-app-docker-network:
    driver: bridge

This is my app.conf :这是我的app.conf

server {
  gzip on;
  gzip_static on;
  gzip_types      text/plain application/xml;
  gzip_proxied    no-cache no-store private expired auth;
  gzip_min_length 1000;

  listen 80;
  server_name mysite.com;
  server_tokens off;

    location / {
      proxy_pass  http://frontend:4200;
      proxy_set_header    Host                $http_host;
      proxy_set_header    X-Real-IP           $remote_addr;
      proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    }

    location /api {
      proxy_pass http://backend:8080;
      rewrite ^/api/(.*) /$1 break;
    }
}

I spend two days to solve this problem, any help will usefull.我花了两天时间解决这个问题,任何帮助都会有用。

It looks like your post is mostly code;看起来您的帖子主要是代码; please add some more details.请添加更多细节。

I fixed my problem.我解决了我的问题。

My app worked fine, exept that SSR wasn't work.我的应用程序运行良好,只是 SSR 不起作用。 I aded request intersepter and realized that I was getting error:我添加了 request intersepter 并意识到我遇到了错误:

Http failure response for (unknown url): 0 Unknown Error

But everything work fine.但一切正常。 I started googling and found this post:我开始用谷歌搜索,发现这篇文章:

https://github.com/angular/angular/issues/20738#issuecomment-415740935 https://github.com/angular/angular/issues/20738#issuecomment-415740935

Author had problem with localhost and docker.作者对 localhost 和 docker 有问题。 I am not using localhost in my project so i just replace serverUrl in my environment.prod.ts file.我没有在我的项目中使用 localhost 所以我只是在我的environment.prod.ts文件中替换serverUrl

Before was just api i replase with full url https://myapp.com/api and SSR started working.之前只是api我用完整的 url https://myapp.com/api和 SSR 开始工作。 Also the error: Http failure response for (unknown url): 0 Unknown Error went away.还有错误: Http failure response for (unknown url): 0 Unknown Error消失了。

This was easy fix, but spend 4 days to find it.这很容易解决,但要花 4 天时间才能找到它。 The main couse of error was thay I used relative url instead of absolute.错误的主要原因是我使用相对 url 而不是绝对。

as angular manual said:正如 angular 手册所说:

The tutorial's HeroService and HeroSearchService delegate to the Angular HttpClient module to fetch application data. These services send requests to relative URLs such as api/heroes. In a server-side rendered app, HTTP URLs must be absolute (for example, https://my-server.com/api/heroes). This means that the URLs must be somehow converted to absolute when running on the server and be left relative when running in the browser.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM