Angular8 前后端分离,静态资源处理方式

2,169 阅读3分钟

现在前后端分离

前后端分离已成为一种趋势,前端不再提供专门的机器进行部署,而是采用发布到CDN的方式,同时在启动后端服务的时候,设置一个根路由,通过get方法获取CDN地址的index.html 文件绑定到路由上,即可实现服务的正常运行。

好处就是前端发布非常方便,CND可采用依赖版本号的方式,升级非常容易。

个人遇到的问题

问题一、发布后,本地访问不到静态资源文件(baseUrl 和 deployUrl搞混了)

环境信息

server 端: nodejs, egg工程,启动了个localhost:18081的服务;

client 端: ts angular8工程,启动了个localhost:9991的服务(就是用来放静态资源)

打包:client 使用默认的 ng build 进行打包,打包完之后放在src同级目录dist下。

server端使用的html如下,大家看出来问题没有

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>ConsoleManageClient</title>
  <base href="http://localhost:9991/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>

<body>
  <app-root></app-root>
  <script src="runtime.js" type="module"></script>
  <script src="polyfills.js" type="module"></script>
  <script src="styles.js" type="module"></script>
  <script src="vendor.js" type="module"></script>
  <script src="main.js" type="module"></script>
</body>

</html>

如下是server端使用正确的index.html, 也是client端正常生成的index.html

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>ConsoleManageClient</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></app-root>
  <script src="http://localhost:9991/runtime.js" type="module"></script>
  <script src="http://localhost:9991/polyfills.js" type="module"></script>
  <script src="http://localhost:9991/styles.js" type="module"></script>
  <script src="http://localhost:9991/vendor.js" type="module"></script>
  <script src="http://localhost:9991/main.js" type="module"></script>
</body>

</html>

你会发现有两处不一样:

1、base href="/" 这个是路由的根地址,建议最好默认为 "/";

2、script src="http://localhost:9991/runtime.js" 这个src要指向静态服务器的地址,才能正确取到资源。

问题二、发布后,本地访问不到 assets下的国际化文件或者图片等静态资源文件(代码中)

angular.json 中关于静态资源assets的打包处理是这样的,其实就是直接copy到对应目录

{
 "projects": {
    "ConsoleManageClient": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "less"
        }
      },
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": false,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.less"
            ],
            "scripts": []
          },
}
// 环境变量中设置
export const environment = {
    production: false,
    cdnAddr: 'http://localhost:9991',
};

// app.module.ts中设置
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';

export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(http, environment.cdnAddr + '/assets/i18n/', '.json');
}
@NgModule({
    declarations: [
        AppComponent
    ],
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        HttpClientModule,
        AppRoutingModule,
        xxxModule,

        TranslateModule.forRoot({
            loader: {
                useFactory: HttpLoaderFactory
            },
        }),
    ]
})

仔细看 environment.cdnAddr 使用的地方,使用了http请求的方式,增加了环境变量参数,这样每次就能取到CDN的资源了,如果没有前缀,取到的就是 server:18081/下的东西,拿不到资源。

总结:

本地开发打包使用 ng build --watch --deploy-url http://localhost:9991/

生产环境打包使用 npx ng build --prod --deploy-url http://cdnxxx/

client端代码静态资源地址获取也要配置CND的前缀地址