在没有 http 调用的情况下将数据从服务器端传递到客户端
Pass data from server side to client without http call
我开发 angular 通用 & node.js 作为服务器应用程序。我按照每个人的建议做所有事情,包括官方文档。
正常情况下,当加载客户端应用程序时,它会执行 ajax 对 API 的查询。 API 放在我的服务器上。
我的目标是避免此 ajax 调用并从已包含此数据的服务器呈现页面。
我像典型的例子一样尝试:
ngOnInit() {
let myTransferStateKey = makeStateKey<any>("myDatas");
if(this.transferState.hasKey(myTransferStateKey)) {
this.result = this.transferState.get(myTransferStateKey, {});
this.transferState.remove(myTransferStateKey);
} else {
this.http.get("link-to-api").subscribe(response => {
this.result = response;
this.transferState.set(myTransferStateKey, this.result);
});
}
}
据我了解,以下代码将在服务器端执行:
this.http.get("link-to-api").subscribe(response => {
this.result = response;
this.transferState.set(myTransferStateKey, this.result);
});
所以服务器端会对自己的服务器执行真正的http查询?真丑!理想情况下,我应该只在我的服务器上使用服务并将数据传递给查看,然后服务器将使用此数据将 html 呈现给客户端。我希望你明白我的意思..
这也是我的 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';
import { AppServerModule } from './src/main.server';
import {ngExpressEngine} from '@nguniversal/express-engine';
// 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', 'calendar');
// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
const domino = require('domino');
const window = domino.createWindow(template);
global['window'] = window;
global['document'] = window.document;
global['requestAnimationFrame'] = cb => cb();
app.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser')));
// All regular routes use the Universal engine
app.get('/', (req, res) => {
res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req });
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});
那么如何优雅的解决呢?我喜欢这种通用的方法和服务器端渲染,但我觉得它现在还很潮湿。
我用的是angular9版,node.js12版...
让我澄清并阐明想法和问题:如何为客户端和服务器使用单一服务(相同的 class/file 等)?唯一的区别应该是服务器将直接使用服务,但客户端在需要获取数据时 - 将使用 ajax 请求 API,而在服务器端 - 此服务 class 将是used ) 我必须让它与 server.ts 或类似的东西一起工作...
所以我认为您混淆了 Angular 通用与 NodeJS 应用程序。
Angular Universal 呈现服务器上请求的 first 页面,从那时起,当您在站点周围单击时,它就像常规 Angular 应用。这实际上只是给人一种错觉,即第一个 "paint" 真的很快,因为一旦您访问该网站,您几乎可以完全呈现整个页面,而不是常规的 Angular 应用程序空白页然后作为您的订阅 return 您填写页面等
如果您希望事情始终在服务器端呈现,那么您可能正在考虑做一个标准的 Express NodeJS 应用程序,该应用程序 returns HTML 视图,而不是 Angular 通用。
如果你真的想继续使用Universal。然后你可以使用调用 "isPlatformBrowser" 和 "isPlatformServer" 的 angular 方法来检查你是否在服务器或浏览器上 运行,然后你可以有逻辑调用API 或直接获取数据。
例如:
export class PostfeedComponent implements OnInit {
constructor(@Inject(PLATFORM_ID) private platform: Object) { }
ngOnInit() {
if (isPlatformBrowser(this.platform)) {
// here you can run any browser specific code
} else {
// Runs only on server
}
}
}
更多信息:
我开发 angular 通用 & node.js 作为服务器应用程序。我按照每个人的建议做所有事情,包括官方文档。
正常情况下,当加载客户端应用程序时,它会执行 ajax 对 API 的查询。 API 放在我的服务器上。 我的目标是避免此 ajax 调用并从已包含此数据的服务器呈现页面。
我像典型的例子一样尝试:
ngOnInit() {
let myTransferStateKey = makeStateKey<any>("myDatas");
if(this.transferState.hasKey(myTransferStateKey)) {
this.result = this.transferState.get(myTransferStateKey, {});
this.transferState.remove(myTransferStateKey);
} else {
this.http.get("link-to-api").subscribe(response => {
this.result = response;
this.transferState.set(myTransferStateKey, this.result);
});
}
}
据我了解,以下代码将在服务器端执行:
this.http.get("link-to-api").subscribe(response => {
this.result = response;
this.transferState.set(myTransferStateKey, this.result);
});
所以服务器端会对自己的服务器执行真正的http查询?真丑!理想情况下,我应该只在我的服务器上使用服务并将数据传递给查看,然后服务器将使用此数据将 html 呈现给客户端。我希望你明白我的意思..
这也是我的 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';
import { AppServerModule } from './src/main.server';
import {ngExpressEngine} from '@nguniversal/express-engine';
// 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', 'calendar');
// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
const domino = require('domino');
const window = domino.createWindow(template);
global['window'] = window;
global['document'] = window.document;
global['requestAnimationFrame'] = cb => cb();
app.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser')));
// All regular routes use the Universal engine
app.get('/', (req, res) => {
res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req });
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});
那么如何优雅的解决呢?我喜欢这种通用的方法和服务器端渲染,但我觉得它现在还很潮湿。
我用的是angular9版,node.js12版...
让我澄清并阐明想法和问题:如何为客户端和服务器使用单一服务(相同的 class/file 等)?唯一的区别应该是服务器将直接使用服务,但客户端在需要获取数据时 - 将使用 ajax 请求 API,而在服务器端 - 此服务 class 将是used ) 我必须让它与 server.ts 或类似的东西一起工作...
所以我认为您混淆了 Angular 通用与 NodeJS 应用程序。
Angular Universal 呈现服务器上请求的 first 页面,从那时起,当您在站点周围单击时,它就像常规 Angular 应用。这实际上只是给人一种错觉,即第一个 "paint" 真的很快,因为一旦您访问该网站,您几乎可以完全呈现整个页面,而不是常规的 Angular 应用程序空白页然后作为您的订阅 return 您填写页面等
如果您希望事情始终在服务器端呈现,那么您可能正在考虑做一个标准的 Express NodeJS 应用程序,该应用程序 returns HTML 视图,而不是 Angular 通用。
如果你真的想继续使用Universal。然后你可以使用调用 "isPlatformBrowser" 和 "isPlatformServer" 的 angular 方法来检查你是否在服务器或浏览器上 运行,然后你可以有逻辑调用API 或直接获取数据。
例如:
export class PostfeedComponent implements OnInit {
constructor(@Inject(PLATFORM_ID) private platform: Object) { }
ngOnInit() {
if (isPlatformBrowser(this.platform)) {
// here you can run any browser specific code
} else {
// Runs only on server
}
}
}
更多信息: