MST
星途 面试题库

面试题:Angular服务器部署:复杂场景与故障处理

假设在将Angular应用部署到一个多租户的云服务器环境时,不同租户都有自己独立的子域名且共享部分静态资源。在部署过程中遇到了跨域问题,并且静态资源缓存策略在某些浏览器上出现异常。请详细说明解决跨域问题的思路以及如何调整静态资源缓存策略以适应不同浏览器的方案,并给出完整的解决方案和相关配置代码。
32.4万 热度难度
前端开发Angular

知识考点

AI 面试

面试题答案

一键面试

解决跨域问题的思路

  1. CORS(跨源资源共享)
    • 在服务器端配置允许跨域的请求。对于不同的后端技术栈,有不同的配置方式。例如在Node.js(Express)中,可以使用cors中间件。
    • 配置Access - Control - Allow - Origin等响应头,指定允许跨域请求的源。可以设置为具体的租户子域名,或者*(但*在某些场景下有限制,比如涉及到Credentials时不能使用)。
  2. 代理
    • 在开发环境中,可以使用Angular的proxy.conf.json文件进行代理配置。这样在开发过程中,所有跨域请求都会被代理到目标服务器,绕过浏览器的跨域限制。
    • 在生产环境,可以使用反向代理服务器(如Nginx或Apache)来代理跨域请求,同样通过配置响应头来解决跨域问题。

调整静态资源缓存策略以适应不同浏览器的方案

  1. Cache - Control头
    • 对于不同的静态资源类型(如CSS、JS、图片等)设置合适的Cache - Control头。例如,对于不经常变动的静态资源(如公共的样式库、脚本库),可以设置较长的缓存时间,如Cache - Control: max - age = 31536000(一年)。
    • 对于可能会频繁变动的资源,设置较短的缓存时间,如Cache - Control: max - age = 3600(一小时)。
  2. ETag
    • 服务器为每个静态资源生成唯一的ETag值。当浏览器请求资源时,服务器根据请求头中的If - None - Match字段与当前资源的ETag值进行比较。如果匹配,说明资源未变动,服务器返回304状态码,浏览器使用本地缓存。
  3. Vary头
    • 当静态资源的缓存策略可能因某些请求头(如Accept - Encoding)不同而不同时,设置Vary头。例如,如果服务器根据浏览器是否支持gzip压缩来返回不同压缩格式的资源,可以设置Vary: Accept - Encoding,这样浏览器会根据该头来正确缓存资源。

完整解决方案及相关配置代码

1. 解决跨域问题(以Node.js + Express为例)

const express = require('express');
const cors = require('cors');
const app = express();

// 配置CORS
app.use(cors({
  origin: ['http://tenant1.example.com', 'http://tenant2.example.com'], // 替换为实际租户子域名
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content - Type', 'Authorization']
}));

// 其他路由和中间件配置
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

2. 配置静态资源缓存策略(以Node.js + Express为例)

const express = require('express');
const app = express();

// 设置静态资源中间件并配置缓存
app.use('/static', express.static('public', {
  maxAge: 31536000, // 缓存一年
  setHeaders: (res, path) => {
    if (path.endsWith('.html')) {
      res.set('Cache - Control','no - cache, no - store, must - revalidate');
    } else if (path.endsWith('.js') || path.endsWith('.css')) {
      res.set('Cache - Control','public, max - age = 31536000');
    }
  }
}));

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

3. Angular开发环境代理配置(proxy.conf.json)

{
  "/api": {
    "target": "http://your - backend - server.com",
    "secure": false,
    "changeOrigin": true
  }
}

angular.json中配置代理:

{
  "architect": {
    "serve": {
      "proxyConfig": "./proxy.conf.json",
      // 其他配置
    }
  }
}

4. Nginx反向代理及跨域和缓存配置

server {
  listen 80;
  server_name tenant1.example.com;

  location / {
    proxy_pass http://your - angular - app - server;
    proxy_set_header Host $host;
    proxy_set_header X - Real - IP $remote_addr;
    proxy_set_header X - Forwarded - For $proxy_add_x_forwarded_for;
    proxy_set_header X - Forwarded - Proto $scheme;

    # 解决跨域问题
    add_header Access - Control - Allow - Origin http://tenant1.example.com;
    add_header Access - Control - Allow - Methods 'GET, POST, PUT, DELETE, OPTIONS';
    add_header Access - Control - Allow - Headers 'Content - Type, Authorization';

    # 静态资源缓存配置
    location ~* \.(css|js|png|jpg|gif)$ {
      expires 365d;
      access_log off;
    }
  }
}