角度通用未达到 api

Posted

技术标签:

【中文标题】角度通用未达到 api【英文标题】:angular universal not reaching api 【发布时间】:2018-08-05 20:38:24 【问题描述】:

我目前正在尝试构建一个有角度的通用应用程序(https://github.com/angular/universal-starter),但我遇到了一个问题。 当我尝试访问我的 API 时,我的应用程序似乎找不到它。

这是我开始写的基本代码:

server.ts

import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import  enableProdMode  from '@angular/core';

import * as express from 'express';
import  join  from 'path';
import  readFileSync  from 'fs';

var apiRoute = require("./routes/api");

// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();

// Express server
const app = express();

const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist');

// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const  AppServerModuleNgFactory, LAZY_MODULE_MAP  = require('./dist/server/main.bundle');

// Express Engine
import  ngExpressEngine  from '@nguniversal/express-engine';
// Import module map for lazy loading
import  provideModuleMap  from '@nguniversal/module-map-ngfactory-loader';

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine(
  bootstrap: AppServerModuleNgFactory,
  providers: [
    provideModuleMap(LAZY_MODULE_MAP)
  ]
));

app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));

/* - Example Express Rest API endpoints -
  app.get('/api/**', (req, res) =>  );
*/

app.use("/api/", apiRoute);




// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser'), 
  maxAge: '1y'
));

// ALl regular routes use the Universal engine
app.get('*', (req, res) => 
  res.render('index',  req );
);

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

api.js

var express = require('express');
var router = express.Router();

router.get("/", function (req, res, next) 
    console.log("ok test");
    res.status(200).json(
        title: "Success",
        obj: "okSuccess"
    );
);

module.exports = router;

app.module.ts

import BrowserModule from '@angular/platform-browser';
import NgModule from '@angular/core';
import RouterModule from '@angular/router';

import  AppComponent  from './app.component';
import  HomeComponent  from './home/home.component';
import TransferHttpCacheModule from '@nguniversal/common';
import  HttpClientModule  from '@angular/common/http';
import  HomeService  from './home/home.service';

@NgModule(
  declarations: [
    AppComponent,
    HomeComponent,
  ],
  imports: [
    HttpClientModule,
    BrowserModule.withServerTransition(appId: 'my-app'),
    RouterModule.forRoot([
       path: '', component: HomeComponent, pathMatch: 'full',
       path: 'lazy', loadChildren: './lazy/lazy.module#LazyModule',
       path: 'lazy/nested', loadChildren: './lazy/lazy.module#LazyModule'
    ]),
    TransferHttpCacheModule,
  ],
  providers: [
    HomeService
  ],
  bootstrap: [AppComponent]
)
export class AppModule  

home.component.ts

import  Component, OnInit  from '@angular/core';
import  HomeService  from './home.service';

@Component(
  selector: 'app-home',
  template: `<h3> message </h3>`
)
export class HomeComponent implements OnInit 
  public message: string;

  constructor(private homeService: HomeService)  

  ngOnInit() 
    this.message = 'Hello';
    console.log(this.homeService.apiCall());
   

home.service.ts

import  Injectable  from "@angular/core";
import  Headers, Http, Response  from "@angular/http";
import  HttpClient, HttpHeaders, HttpParams, HttpRequest  from '@angular/common/http';
import 'rxjs/Rx';
import  Observable  from "rxjs/Observable";


@Injectable()
export class HomeService 

    constructor(private httpClient: HttpClient)  

    apiCall() 
        return this.httpClient.get<any>("/api")
        .map((response) => 
                console.log(response);
                return response;
            )
            .subscribe((response) => 
                console.log(response);
                return response;
            );
    

我通过输入npm run start 开始在开发模式下构建,但随后出现以下错误

我不太明白为什么会出现这个错误,好像 express 没有添加我的路线。

【问题讨论】:

【参考方案1】:

注意:如果你查看 package.json 文件,你会注意到 npm run start 只调用 ng serve,所以它没有使用 angular Universal。所以下面的方法不起作用,因为前面没有定义'/api'路由/处理程序。

this.httpClient.get<any>("/api")

启动角度通用渲染模式的说明在这里 https://github.com/angular/universal-starter#production-also-for-testing-s-s-rpre-rendering-locally

此外,当使用 Angular Universal 时,您在执行 ajax 调用时不能使用相对 URL。您必须指定完整的 url(协议/域/端口,如果不是 80 或 https 的 443)

所以现在,你应该使用

this.httpClient.get<any>("http://localhost:4000/api")

如果你的 Angular Universal 在 localhost 的 4000 端口上运行

【讨论】:

所以,据我所知,每次我在我的 api(和我的前面)上更改某些内容时,我都必须使用 npm run build:s-s-r &amp;&amp; npm run serve:s-s-r 进行完整的构建? 如果不改接口就不确定API部分,但肯定是前端。但这只是在为生产而构建时才要做的事情。在开发模式下,您只需使用ng serve,并在需要时重新启动 api 服务器(例如,如果您想在文件更改时自动执行,请使用 nodemon 或 pm2) 好的,谢谢,我现在明白了,我只是专注于npm run start,不明白为什么它不使用自己的服务器。但现在我明白了 :)

以上是关于角度通用未达到 api的主要内容,如果未能解决你的问题,请参考以下文章

通用构建请求方法响应未定义

GPU通用计算API的变迁和趋势

如何运行角度通用 HTTPS

仅适用于某些路线的角度通用渲染

角度通用安装会引发错误

在角度通用应用程序(nodejs)上集成newrelic