RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 938575
Accepted
titaniche
titaniche
Asked:2020-01-30 20:45:06 +0000 UTC2020-01-30 20:45:06 +0000 UTC 2020-01-30 20:45:06 +0000 UTC

Angular 6 + Spring Boot。应用程序加载不正确

  • 772

再会。请告诉我为什么会出现以下问题: 应用程序构建并启动后,浏览器中的窗口显示奇怪的内容。此外,消息来源显示没有编译过的脚本。

页

但是,如果您将其写入地址栏中.../index.html,应用程序将加载并开始工作。

页

然而,如果您刷新浏览器页面 - 在这种情况下,情况将再次重复,如上图(如果 url 是 form url/<application_context>/)或 Whitelabel Error Page 错误(如果 url 是 form url/<application_context>/child/anotherChild...)

我对可能导致这些问题的原因感到有些困惑,所以我什至不知道要包括哪些资源来帮助解决问题。以下是其中一些:

包.json

{
  "name": "asterisk-prime-ui",
  "version": "1.0.0",
  "..": "main.ts",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.conf.json",
    "build-prod": "ng build --prod",
    "build-dev": "ng build --aot --build-optimizer --vendor-chunk",
    "extract": "ngx-translate-extract --input ./src/app --output ./src/assets/i18n/*.json --clean --sort --format namespaced-json --marker _",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^6.1.7",
    "@angular/cdk": "^6.4.7",
    "@angular/common": "^6.1.7",
    "@angular/compiler": "^6.1.7",
    "@angular/core": "^6.1.7",
    "@angular/flex-layout": "^6.0.0-beta.18",
    "@angular/forms": "^6.1.7",
    "@angular/http": "^6.1.7",
    "@angular/material": "^6.4.7",
    "@angular/platform-browser": "^6.1.7",
    "@angular/platform-browser-dynamic": "^6.1.7",
    "@angular/router": "^6.1.7",
    "core-js": "^2.5.4",
    "hammerjs": "^2.0.8",
    "net": "^1.0.2",
    "rxjs": "^6.3.2",
    "rxjs-compat": "^6.3.2",
    "zone.js": "^0.8.29"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.7.0",
    "@angular/cli": "~6.1.5",
    "@angular/compiler-cli": "^6.1.7",
    "@angular/language-service": "^6.1.7",
    "@biesbjerg/ngx-translate-extract": "^2.3.4",
    "@ngx-translate/core": "^10.0.2",
    "@ngx-translate/http-loader": "^3.0.1",
    "@types/jasmine": "~2.8.6",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "~8.9.4",
    "@types/sockjs-client": "^1.1.0",
    "@types/stompjs": "^2.3.4",
    "@types/yargs": "^12.0.5",
    "codelyzer": "^4.4.4",
    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "^3.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "^2.0.3",
    "karma-jasmine": "~1.1.1",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.4.0",
    "sockjs-client": "^1.1.5",
    "stompjs": "^2.3.3",
    "ts-node": "~5.0.1",
    "tslint": "~5.9.1",
    "typescript": "^2.9.2",
    "yargs": "^12.0.5"
  }
}

tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "outDir": "./dist/out-tsc",
    "baseUrl": "/",
    "target": "es5",
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": [
      "es6",
      "es7",
      "dom"
    ],
    "typeRoots": [
      "node_modules/@types"
    ]
  },
  "exclude": [
    "../../node_modules"
  ]
}

角.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "asterisk-prime-ui": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "prefix": "app",
      "schematics": {
        "@schematics/angular:component": {
          "styleext": "less"
        }
      },
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "../../../../asterisk-prime/src/main/resources/static/asterisk-prime-ui",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              {
                "glob": "**/*",
                "input": "src/assets",
                "output": "/assets"
              },
              {
                "glob": "favicon.ico",
                "input": "src",
                "output": "/"
              }
            ],
            "styles": [
              {
                "input": "node_modules/@angular/material/prebuilt-themes/indigo-pink.css"
              },
              {
                "input": "src/styles/global.scss"
              }
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "asterisk-prime-ui:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "asterisk-prime-ui:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "asterisk-prime-ui:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.spec.json",
            "karmaConfig": "src/karma.conf.js",
            "styles": [
              {
                "input": "node_modules/@angular/material/prebuilt-themes/indigo-pink.css"
              },
              {
                "input": "src/styles/global.scss"
              }
            ],
            "scripts": [],
            "assets": [
              {
                "glob": "**/*",
                "input": "src/assets",
                "output": "/assets"
              },
              {
                "glob": "favicon.ico",
                "input": "src",
                "output": "/"
              }
            ]
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "src/tsconfig.app.json",
              "src/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    },
    "asterisk-prime-ui-e2e": {
      "root": "e2e/",
      "projectType": "application",
      "architect": {
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "asterisk-prime-ui:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "asterisk-prime-ui:serve:production"
            }
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": "e2e/tsconfig.e2e.json",
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }
  },
  "defaultProject": "asterisk-prime-ui",
  "schematics": {
    "@schematics/angular:component": {
      "styleext": "scss"
    }
  }
}

索引.html

<!doctype html>
<html lang="en">
<head>
  <base href=".">
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>AsteriskPrimeUI</title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
  <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet" />
</head>
<body>
<app-root>Loading...</app-root>
</body>
</html>

前端部分在 spring-boot 应用程序的静态资源中组装和布局(请参阅 参考资料"outputPath": "../../../../asterisk-prime/src/main/resources/static/asterisk-prime-ui")。此外,所有这些都收集在战争档案中。

WebMvcConfig.java

@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer
{
    @Value("#{'${web.mvc.crossOrigins}'.split(',')}")
    private String[] crossOrigins;

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
            "classpath:/META-INF/resources/",
            "classpath:/resources/",
            "classpath:/static/",
            "classpath:/public/",
            "classpath:/static/asterisk-prime-ui/"
    };

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        if (!registry.hasMappingForPattern("/webjars/**"))
        {
            registry.addResourceHandler("/webjars/**")
                    .addResourceLocations("/webjars/");
        }

        if (!registry.hasMappingForPattern("/**"))
        {
            registry.addResourceHandler("/**")
                    .addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
        }
    }

    @Override
    public void addCorsMappings(CorsRegistry registry)
    {
        registry.addMapping("/api/**")
                .allowedOrigins(crossOrigins)
                .allowCredentials(true)
                .maxAge(3600);
    }

    @Bean
    public ViewResolver urlViewResolver()
    {
        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
        viewResolver.setViewClass(InternalResourceView.class);
        return viewResolver;
    }
}

提前感谢大家的帮助。

spring-mvc
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    titaniche
    2020-02-01T16:10:08Z2020-02-01T16:10:08Z

    该解决方案需要更改后端(Spring Boot)和前端(Angular 6)。

    1.后端

    在 Spring Boot 部分,所有更改都影响了 WebMvc 设置的调整。特别是,我更改了 ViewResolver:

    @Bean
    public ViewResolver internalResourceViewResolver()
    {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(InternalResourceView.class);
        return viewResolver;
    }
    

    index.html并且还在映射时添加了一个“翻转” /(事实证明,这是使用单页应用程序(使用 Angular、React 或类似的)时的标准机制:

    @Override
    public void addViewControllers(ViewControllerRegistry registry)
    {
        registry.addViewController("/").setViewName("index.html");
    }
    

    最终配置:

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages = {"com.prime.asterisk.web.controller"})
    public class WebMvcConfig implements WebMvcConfigurer
    {
        @Value("#{'${web.mvc.crossOrigins}'.split(',')}")
        private String[] crossOrigins;
    
        private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
                "classpath:/META-INF/resources/",
                "classpath:/resources/",
                "classpath:/static/",
                "classpath:/public/",
                "classpath:/static/asterisk-prime-ui/"
        };
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry)
        {
            if (!registry.hasMappingForPattern("/**"))
            {
                registry.addResourceHandler("/**")
                        .addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
            }
        }
    
        @Override
        public void addCorsMappings(CorsRegistry registry)
        {
            registry.addMapping("/api/**")
                    .allowedOrigins(crossOrigins)
                    .allowCredentials(true)
                    .maxAge(3600);
        }
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry)
        {
            registry.addViewController("/").setViewName("index.html");
        }
    
        @Bean
        public ViewResolver internalResourceViewResolver()
        {
            InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
            viewResolver.setViewClass(InternalResourceView.class);
            return viewResolver;
        }
    }
    

    2.前端

    在UI部分,也需要做一些改动。

    В первую очередь, добавить атрибуты base-href и deploy-url для скриптов сборки. В моем случае использован шаблон: /<application-context>/, где <application-context> - asterisk-prime. В целом, в большинстве случаев достаточно было бы поставить атрибут base-href, однако в моем случае этого было мало, т.к. assets проекта не использовали base-href в качестве префикса src-атрибута. Возможно есть другое решение, однако в моем случае достаточно было добавить атрибут deploy-url. Окончательный вид скриптов:

    ...
    "build-prod": "ng build --prod --base-href /asterisk-prime/ --deploy-url /asterisk-prime/",
    ...
    "build-dev": "ng build --aot --build-optimizer --base-href /asterisk-prime/ --deploy-url /asterisk-prime/",
    ...
    

    Далее не менее важным действием было изменить стратегию роутинга приложения. А именно, активировать параметр useHash=true в соответствующем модуле:

    ...
    RouterModule.forRoot(AppConfigRoutesFactory.getRoutes(), {useHash: true})
    ...
    

    P.S.: AppConfigRoutesFactory - класс со статическим методом отдачи Routes (просто передайте туда свои Routes)

    Окончательный вид AppRoutesModule:

    @NgModule({
      imports: [
        RouterModule.forRoot(AppConfigRoutesFactory.getRoutes(),
          {
            useHash: true,
            scrollPositionRestoration: 'enabled'
          })
      ],
      exports: [
        RouterModule
      ]
    })
    
    export class AppRoutingModule {
    }
    

    接下来,您只需要将这个模块导入到您的 AppModule 中。如果在更新页面时出现 Whitelabel Error Page 错误,您应该在路由中使用哈希。

    非常感谢大家提供的所有帮助,评论和尝试至少帮助找到问题的方向。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5