- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我第一次对 Angular 或我自己感到非常失望,因为我不知道这是 Angular 的问题还是我自己的问题。我有 Angular 6.0.0 项目,它不是很大,但也不小。我在我的项目中实现了 Angular Universal ssr 。
没有 ssr 的结果: *提示我有惰性模块。主要只是我的第一页。
heroku 免费服务器上 ssr 的结果(但本地主机上的 main.js 大小相同,只是本地主机上的加载时间为 40 毫秒):
我认为这些数字太大了? SSR
工作正常,但加载时间
很糟糕 - 从 184 毫秒到 2.50 秒。
详细项目信息:
Package.json(提示:我正在使用heroku将我的网络部署到nodejs服务器):
{
....
"engines": {
"node": "8.11.1",
"npm": "6.5.0"
},
"scripts": {
"ng": "ng",
"start:heroku": "node dist/server",
"start": "ng serve --aot",
"build": "ng build",
"lint": "ng lint Deals",
"build:client-and-server-bundles": "ng build --prod --aot && ng run Deals:server:production",
"build:prerender": "npm run build:client-and-server-bundles && npm run compile:server && npm run generate:prerender",
"build:ssr": "npm run build:client-and-server-bundles && npm run compile:server",
"compile:server": "tsc -p server.tsconfig.json",
"generate:prerender": "cd dist && node prerender",
"serve:prerender": "cd dist/browser && http-server",
"serve:ssr": "node dist/server ",
"postinstall": "npm run build:ssr"
},
"pre-commit": [],
"private": true,
"dependencies": {
"@angular-devkit/build-angular": "0.6.0",
"@angular/animations": "^6.1.10",
"@angular/cdk": "^7.1.0",
"@angular/cli": "6.0.0",
"@angular/common": "^6.0.0",
"@angular/compiler": "^6.0.0",
"@angular/compiler-cli": "^6.0.0",
"@angular/core": "^6.0.0",
"@angular/fire": "^5.1.1",
"@angular/forms": "^6.0.0",
"@angular/http": "^6.0.0",
"@angular/language-service": "^6.0.0",
"@angular/material": "^7.1.0",
"@angular/platform-browser": "^6.0.0",
"@angular/platform-browser-dynamic": "^6.0.0",
"@angular/platform-server": "^6.0.0",
"@angular/pwa": "^0.11.4",
"@angular/router": "^6.0.0",
"@angular/service-worker": "^6.0.0",
"@ngrx/core": "^1.2.0",
"@ngrx/store-devtools": "^6.1.2",
"@nguniversal/common": "^6.0.0",
"@nguniversal/express-engine": "^6.0.0",
"@nguniversal/module-map-ngfactory-loader": "^6.0.0",
"@ngx-translate/core": "^10.0.2",
"@ngx-translate/http-loader": "^4.0.0",
"@types/node": "^8.0.30",
"angular2-cookie": "^1.2.6",
"angularfire2": "^5.1.1",
"angulartics-clicky": "^1.0.0",
"angulartics2": "^6.3.1",
"codelyzer": "^4.0.2",
"core-js": "^2.4.1",
"express": "^4.15.2",
"firebase": "^5.6.0",
"hammerjs": "^2.0.8",
"http-server": "^0.10.0",
"ngx-page-scroll": "^5.0.1",
"nodemailer": "^4.7.0",
"npm": "^6.4.1",
"pre-commit": "^1.2.2",
"reflect-metadata": "^0.1.10",
"rxjs": "^6.2.2",
"ts-loader": "^4.2.0",
"tslint": "^5.7.0",
"typescript": "~2.7.2",
"zone.js": "^0.8.26"
},
渲染 ssr 的 Server.ts :
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { enableProdMode } from '@angular/core';
// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine';
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
import * as express from 'express';
import { join } from 'path';
// 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');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./server/main');
// 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),
// In case you want to use an AppShell with SSR and Lazy loading
// you'd need to uncomment the below. (see: https://github.com/angular/angular-cli/issues/9202)
// {
// provide: NgModuleFactoryLoader,
// useClass: ModuleMapNgFactoryLoader,
// deps: [
// Compiler,
// MODULE_MAP
// ],
// },
]
}));
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// 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, () => {});
server.tsconfig.json:
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
},
"include": ["server.ts", "prerender.ts"]
}
最佳答案
服务器.ts
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
const test = process.env['TEST'] === 'true';
const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString();
const win = domino.createWindow(template);
const files = fs.readdirSync(`${process.cwd()}/dist-server`);
global['window'] = win;
Object.defineProperty(win.document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true,
};
},
});
global['document'] = win.document;
global['CSS'] = null;
// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['Prism'] = null;
import { enableProdMode } from '@angular/core';
import * as express from 'express';
import * as compression from 'compression';
import * as cookieparser from 'cookie-parser';
const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader');
const mainFiles = files.filter((file) => file.startsWith('main'));
const hash = mainFiles[0].split('.')[1];
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require(`./dist-server/main.${hash}`);
import { ngExpressEngine } from '@nguniversal/express-engine';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
const PORT = process.env.PORT || 4000;
import { ROUTES } from './static.paths';
import { exit } from 'process';
enableProdMode();
const app = express();
app.use(compression());
app.use(cookieparser());
const redirectowww = false;
const redirectohttps = true;
const wwwredirecto = true;
app.use((req, res, next) => {
// for domain/index.html
if (req.url === '/index.html') {
res.redirect(301, 'https://' + req.hostname);
}
// check if it is a secure (https) request
// if not redirect to the equivalent https url
if (
redirectohttps &&
req.headers['x-forwarded-proto'] !== 'https' &&
req.hostname !== 'localhost'
) {
// special for robots.txt
if (req.url === '/robots.txt') {
next();
return;
}
res.redirect(301, 'https://' + req.hostname + req.url);
}
// www or not
if (redirectowww && !req.hostname.startsWith('www.')) {
res.redirect(301, 'https://www.' + req.hostname + req.url);
}
// www or not
if (wwwredirecto && req.hostname.startsWith('www.')) {
const host = req.hostname.slice(4, req.hostname.length);
res.redirect(301, 'https://' + host + req.url);
}
// for test
if (test && req.url === '/test/exit') {
res.send('exit');
exit(0);
return;
}
next();
});
app.engine(
'html',
ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)],
}),
);
app.set('view engine', 'html');
app.set('views', 'src');
app.get('*.*', express.static(path.join(__dirname, '.', 'dist')));
app.get(ROUTES, express.static(path.join(__dirname, '.', 'static')));
app.get('*', (req, res) => {
global['navigator'] = req['headers']['user-agent'];
const http =
req.headers['x-forwarded-proto'] === undefined ? 'http' : req.headers['x-forwarded-proto'];
const url = req.originalUrl;
// tslint:disable-next-line:no-console
console.time(`GET: ${url}`);
res.render(
'../dist/index',
{
req: req,
res: res,
providers: [
{
provide: REQUEST,
useValue: req,
},
{
provide: RESPONSE,
useValue: res,
},
{
provide: 'ORIGIN_URL',
useValue: `${http}://${req.headers.host}`,
},
],
},
(err, html) => {
if (!!err) {
throw err;
}
// tslint:disable-next-line:no-console
console.timeEnd(`GET: ${url}`);
res.send(html);
},
);
});
app.listen(PORT, () => {
console.log(`listening on http://localhost:${PORT}!`);
});
关于node.js - Angular 6 ssr页面负载太大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54168036/
很好,我在一台通过PM2执行的阿帕奇服务器上运行了一个带有ANGLE Universal的Web。。进行更改时,我会生成新版本的Web、将文件上传到主机并重新启动PM2任务。但当访问网络时,这些变化不
我在使用快速服务器构建和提供 Angular Universal 应用程序以获得良好的 SEO 方面遇到了挑战。 当我使用带有命令 "dev:ssr": "ng run motif:serve-ssr
我想在我的 nuxt 项目中使用一个 stencil 库。 我能够让它工作,但是当 vue 组件在服务器端呈现时,我只能让 stencil 的组件呈现在客户端。 我认为最大的问题是 defineCus
我想将我的sveltekit SSR应用托管到AWS服务(Amplify)。我们怎么能做到这一点呢?如果我们使用适配器静态,它是否会影响SSR?如果我们可以使用任何其他AWS服务来托管我们的svelt
我想为我的用户对我的应用进行 SSR。 但我的应用程序代码使用 useEffect 来检测用户屏幕宽度的大小,然后才呈现应用程序。 类似于: App.js // THE LAYOUT INITIA
我正在尝试制作一个 SSR react 应用程序,但无法将 Prop 从 express 传递到组件。 我在做什么错? server.js import AppPage2 from './src/pr
我使用 webpack 捆绑了我的 SSR 存储库(类似 inferno-react 的 lib)。它有 2 个路由文件,1 个用于服务器,1 个用于客户端,完全相同,但使用 require.ensu
当我用react做SSR时,发送给客户端的内容是如何构造的? 它是否等待异步操作完成? 是否等待状态树中的所有组件是否以某种方式保持稳定? 它会在某些生命周期方法中等待异步代码,例如用 await/a
我正在尝试创建一个 Angular 服务,组件可以使用该服务来观看窗口大小调整事件。经过多次尝试,我终于发现这个解决方案效果最好 https://stackoverflow.com/a/4383381
我正在重构一个大量使用 vue 组件的网络应用程序。 目前,vue 组件是使用 twig 模板语言在服务器端呈现的。组件作为静态 html 呈现给页面......没有使用 webpack 或 vue
我是 kibana 的新手,我想知道 kibana 如何在仪表板上生成可视化? 即 是否使用 SSR 生成图形/饼图等? 它是否使用 elastic-charts/charts.js/d3.js 等库
我的主代码 (app.component.html) 上没有任何会导致重新加载的更高级别的 NgIf。我正在使用 transferstate,因此在 SSR 设置公共(public) url 的答案后
我是 flutter 的新手,我想为我的 flutter Web 应用程序实现 SSR。 Flutter web 是否支持 SSR(服务器端渲染)? 我应该如何实现它? 最佳答案 尚未实现,但您可以在
我想知道是否有人可以向我指出如何为 vue SSR(服务器端渲染)设置包裹的资源或示例。 或者包裹不能使用Vue SSR? 最佳答案 应该像安装所需的各种库一样简单: # Yarn $ yarn ad
我使用 Angular SSR,当我刷新页面时,它首先进入登录页面,然后进入所需页面。 我还使用 cookie 来存储 token 。 canActivate( route: ActivatedRou
我在 SSR 上运行的异步管道有问题。没有错误,只有无限循环(似乎服务器正在等待 observable 被解析)。 我在用: @nestjs/ng-universal Angular 9 Fireba
以下内容适用于通过 NextJS 的 SSR。 我正在使用 React 的上下文来跟踪某些已安装组件的 ID。要点是 class Root extends React.Component { ge
我使用 React、react-router、@loadable/component 创建了一个项目。 现在我正在尝试将 SSR 添加到该项目中。我使用react-router进行了服务器端渲染。 然
我是 Angular ssr 的新手,您可以看到下面的代码 问题 如果我直接进入客户端路由,首先会显示 Rendered by server 但很快它就会重新渲染页面并显示: Rendered by
当窗口未定义时,我一直在尝试测试 else block 。当我使用 Next.js 时,窗口在服务器端渲染 (SSR) 期间将是未定义的。目前我找不到办法做到这一点。 非常感谢任何帮助。 我已经尝试在
我是一名优秀的程序员,十分优秀!