如何将 Angular 4+(前端)部署到 CDN?

15
我想将我的 Angular 应用程序(使用 AOT)部署到 CDN 上,同时使用自己的 REST 服务器。
我希望第一个请求始终发送到我的 REST 服务器(假设为https://example.com)。然后,第一个响应将指示浏览器从 CDN 加载 Angular 的第一个模块。
所有资源请求 (API 请求) 当然都将发送到我的 REST 服务器(假设为https://example.com/api/XXXX)。
现在我的问题是: 代码如何知道从何处加载下一个 Angular 模块? 请问有人可以解释一下其中的机制吗?
3个回答

25

简短回答:在执行“ng build”命令时使用选项“--deploy-url”。

“--deploy-url”选项的作用是强制<script>标签使用您指定的域名来使用绝对URL。这样,浏览器始终知道从哪里加载静态资源文件(JavaScript、图像等)。

=========================

用例:

REST服务器正在我们的数据中心运行。它不仅提供REST API,还提供初始的index.html文件(即浏览器的第一个请求总是发送到此REST服务器)。

我们所有的Angular静态文件(它们只是JavaScript文件)都部署到CDN(例如AWS、AZURE、GOOGLE等)上。

=========================

如果没有使用“--deploy-url”,则“ng build”将生成以下index.html文件:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root>Loading...</app-root>
  <script type="text/javascript" src="/inline.bundle.js"></script>
  <script type="text/javascript" src="/polyfills.bundle.js"></script>
  <script type="text/javascript" src="/styles.bundle.js"></script>
  <script type="text/javascript" src="/vendor.bundle.js"></script>
  <script type="text/javascript" src="/main.bundle.js"></script>
 </body>
</html>

使用"--deploy-url"参数,执行命令"ng build"会生成以下index.html文件:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root>Loading...</app-root>
  <script type="text/javascript" src="https://any.cdn.com/inline.bundle.js"></script>
  <script type="text/javascript" src="https://any.cdn.com/polyfills.bundle.js"></script>   
  <script type="text/javascript" src="https://any.cdn.com/styles.bundle.js"></script>    
  <script type="text/javascript" src="https://any.cdn.com/vendor.bundle.js"></script>  
  <script type="text/javascript" src="https://any.cdn.com/main.bundle.js">
  </script>
</body>
</html>

=========================

部署是什么:

例如,

ng build --deploy-url YOUR-CDN-SERVER-DOMAIN --prod --aot

这应该会生成一个 /dist 文件夹,其中包括所有文件(包括index.html)。接下来只需将index.html移至REST服务器,将其余文件部署到CDN中。

现在您可以让用户首先访问您自己的域名www.example.com。 您可以将所有Angular生成的JS文件放在任何CDN上,而不必担心CORS。

=======================

注:

此解决方案可能从高层次的角度解释问题。 它在我的情况下完美地工作。 如果您有疑问,请随时留言。


2

不确定这是否有帮助,但这是我在将前端托管在S3上并在我们的数据中心使用REST服务器时的解决方案:我们将www.example.com的CNAME指向S3存储桶,其中包含前端,api.example.com指向我们的REST服务器。

在您的 environment.prod.ts 中指定 apiUrl

export const environment = {
    production: true,
    apiUrl: 'https://api.example.com'
};

您可以用它来进行API调用,例如:

import {environment} from '../environments/environment';

getHttp(url: string, params?: RequestOptions): Observable<any> {
    // prefix API URL if not already given
    if (url.indexOf(environment.apiUrl) === -1) {
        url = environment.apiUrl + url;
    }
    return this.http.get(url, params).map().catch();
}

确保在构建时传递环境而不仅仅是目标:

ng build --env=prod

最重要的是,通过从您的REST服务器发送这些标头,允许来自www到api的请求(CORS):

Access-Control-Allow-Origin: https://www.example.com
Vary: Origin

注意:这也使得在本地开发中使用代理变得过时了,因为您可以在environment.ts中简单地指定带端口的本地apiUrl。

首先感谢您的回复。您的解决方案始终将第一个请求发送到提供前端静态文件的任何服务器。但是我希望第一个请求首先发送到我的REST服务器,以便我可以避免所有资源API调用的CORS相关问题,因为它们在同一域下。 我已经想出了一个“解决方案”,稍后会发布(仍需要一些重新措辞)。 - gye

1
你需要使用Cdnify。尝试使用像gulpCDN这样的库。
对于我们的问题,我所做的是在prod构建后将所有Dist文件上传到S3,然后运行

gulp cdnify,它将替换主和供应商捆绑文件的本地主机链接为来自s3存储桶的链接(您需要直接指定根目录以使gulp自动执行此操作)在index.html中

文件将由我的节点服务器提供,然后使用它。
我们采用这种方法的原因是Node在提供静态文件时速度较慢,因此使用这种机制可以获得更快的性能。一旦加载了index.html,您就不必担心其他模块,因为所有供应商和主js文件都将从cdn链接中加载,该链接已在index.html中更改。
供参考,我使用了这些库Gulp S3gulp cdinfy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接