Angular 通用特定路由不加载
Angular universal specific route does not load
我在 Angular Universal 中遇到了一个奇怪的问题,当使用整页条目访问所有路由时,所有路由都正常工作,一个除外!这是我当前的配置:
应用路线:
const routes: Routes = [{
path: '',
pathMatch: 'full',
redirectTo: '/home'
}, {
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
}, {
path: 'home',
loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
}, {
path: 'foo',
loadChildren: () => import('./foo/foo.module').then(m => m.FooModule)
}, {
path: '**',
loadChildren: () => import('./not-found/not-found.module').then(m => m.NotFoundModule)
}];
server.ts:
import 'zone.js/dist/zone-node';
import * as express from 'express';
import {join} from 'path';
import * as proxy from 'http-proxy-middleware';
// Express server
const app = express();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', (_, options: { req, res }, callback) => {
const engine = ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP),
{provide: 'headers', useFactory: () => options.req.headers, deps: []}
]
});
engine(_, options, callback);
});
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
app.use(`/app/`, createRoutes());
function createRoutes() {
const router = express.Router();
router.get('*.*', express.static(DIST_FOLDER, {
maxAge: '1y'
}));
router.get('*', (req, res) => {
res.render('index', {req, res}, (error, html) => {
return res.send(html);
});
});
return router;
}
const apiProxy = proxy('/api', { target: 'http://localhost:8000'});
app.use('/api', apiProxy);
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}/app`);
});
HomeRoutingModule:
import { HomeComponent } from './home.component';
const routes: Routes = [{ path: '', component: HomeComponent }];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class HomeRoutingModule { }
HomeComponent 对某些 HTTP 处理服务和 primeNg 的 MessageService
有两个依赖项。
因此,当我访问 http://localhost:4200/app/query
时,一切正常,然后我可以正确地浏览应用程序。但是当我访问 http://localhost:4200/app
或 http://localhost:4200/app/home
时什么也没有发生,我什至没有得到响应,甚至我尝试添加到 express 中的 index
路由渲染的回调也没有被调用。
我在 dist/server/main.js
中进行了一些挖掘,并将问题缩小到以下函数:
function _render(platform, moduleRefPromise) {
return moduleRefPromise.then((/**
* @param {?} moduleRef
* @return {?}
*/
(moduleRef) => {
/** @type {?} */
const transitionId = moduleRef.injector.get(platform_browser["ɵTRANSITION_ID"], null);
if (!transitionId) {
throw new Error(`renderModule[Factory]() requires the use of BrowserModule.withServerTransition() to ensure
the server-rendered app can be properly bootstrapped into a client app.`);
}
/** @type {?} */
const applicationRef = moduleRef.injector.get(core["ApplicationRef"]);
return applicationRef.isStable.pipe((Object(first["a" /* first */])((/**
* @param {?} isStable
* @return {?}
*/
(isStable) => isStable))))
.toPromise()
.then((/**
* @return {?}
*/
() => {
/** @type {?} */
const platformState = platform.injector.get(PlatformState);
/** @type {?} */
const asyncPromises = [];
// Run any BEFORE_APP_SERIALIZED callbacks just before rendering to string.
/** @type {?} */
const callbacks = moduleRef.injector.get(BEFORE_APP_SERIALIZED, null);
if (callbacks) {
for (const callback of callbacks) {
try {
/** @type {?} */
const callbackResult = callback();
if (Object(core["ɵisPromise"])(callbackResult)) {
asyncPromises.push(callbackResult);
}
}
catch (e) {
// Ignore exceptions.
console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e);
}
}
}
/** @type {?} */
const complete = (/**
* @return {?}
*/
() => {
/** @type {?} */
const output = platformState.renderToString();
platform.destroy();
return output;
});
if (asyncPromises.length === 0) {
return complete();
}
return Promise
.all(asyncPromises.map((/**
* @param {?} asyncPromise
* @return {?}
*/
asyncPromise => {
return asyncPromise.catch((/**
* @param {?} e
* @return {?}
*/
e => { console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e); }));
})))
.then(complete);
}));
}));
}
这里发生的是,对于 /home
路由,我永远无法进入以 const platformState = platform.injector.get(PlatformState);
开头的回调。我不确定为什么会这样想。
有人有什么想法可以帮忙吗?
更新#1:
我设法将问题缩小到我在 HomeComponent
的 ngOnInit
中使用的 RxJS 运算符。对于这个组件,我正在做一些轮询,所以我有类似的东西:
timer(0, 15000).pipe(
mergeMap(() => this.dataService.fetchData())
).subscribe(...)
为了提供最小的非工作组件,我从我的组件中删除了所有内容并将以下内容添加到 ngOnInit
:
timer(0, 20000).subscribe(
(...args) => console.log(args),
(...args) => console.error(args)
);
现在,当我尝试访问该路线时,它仍然没有加载(如预期的那样),但我在服务器的控制台中看到了来自订阅的值。
您可以在应用程序稳定后触发轮询,在组件中注入 ApplicationRef
,并订阅 isStable
我在 Angular Universal 中遇到了一个奇怪的问题,当使用整页条目访问所有路由时,所有路由都正常工作,一个除外!这是我当前的配置:
应用路线:
const routes: Routes = [{
path: '',
pathMatch: 'full',
redirectTo: '/home'
}, {
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
}, {
path: 'home',
loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
}, {
path: 'foo',
loadChildren: () => import('./foo/foo.module').then(m => m.FooModule)
}, {
path: '**',
loadChildren: () => import('./not-found/not-found.module').then(m => m.NotFoundModule)
}];
server.ts:
import 'zone.js/dist/zone-node';
import * as express from 'express';
import {join} from 'path';
import * as proxy from 'http-proxy-middleware';
// Express server
const app = express();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', (_, options: { req, res }, callback) => {
const engine = ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP),
{provide: 'headers', useFactory: () => options.req.headers, deps: []}
]
});
engine(_, options, callback);
});
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
app.use(`/app/`, createRoutes());
function createRoutes() {
const router = express.Router();
router.get('*.*', express.static(DIST_FOLDER, {
maxAge: '1y'
}));
router.get('*', (req, res) => {
res.render('index', {req, res}, (error, html) => {
return res.send(html);
});
});
return router;
}
const apiProxy = proxy('/api', { target: 'http://localhost:8000'});
app.use('/api', apiProxy);
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}/app`);
});
HomeRoutingModule:
import { HomeComponent } from './home.component';
const routes: Routes = [{ path: '', component: HomeComponent }];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class HomeRoutingModule { }
HomeComponent 对某些 HTTP 处理服务和 primeNg 的 MessageService
有两个依赖项。
因此,当我访问 http://localhost:4200/app/query
时,一切正常,然后我可以正确地浏览应用程序。但是当我访问 http://localhost:4200/app
或 http://localhost:4200/app/home
时什么也没有发生,我什至没有得到响应,甚至我尝试添加到 express 中的 index
路由渲染的回调也没有被调用。
我在 dist/server/main.js
中进行了一些挖掘,并将问题缩小到以下函数:
function _render(platform, moduleRefPromise) {
return moduleRefPromise.then((/**
* @param {?} moduleRef
* @return {?}
*/
(moduleRef) => {
/** @type {?} */
const transitionId = moduleRef.injector.get(platform_browser["ɵTRANSITION_ID"], null);
if (!transitionId) {
throw new Error(`renderModule[Factory]() requires the use of BrowserModule.withServerTransition() to ensure
the server-rendered app can be properly bootstrapped into a client app.`);
}
/** @type {?} */
const applicationRef = moduleRef.injector.get(core["ApplicationRef"]);
return applicationRef.isStable.pipe((Object(first["a" /* first */])((/**
* @param {?} isStable
* @return {?}
*/
(isStable) => isStable))))
.toPromise()
.then((/**
* @return {?}
*/
() => {
/** @type {?} */
const platformState = platform.injector.get(PlatformState);
/** @type {?} */
const asyncPromises = [];
// Run any BEFORE_APP_SERIALIZED callbacks just before rendering to string.
/** @type {?} */
const callbacks = moduleRef.injector.get(BEFORE_APP_SERIALIZED, null);
if (callbacks) {
for (const callback of callbacks) {
try {
/** @type {?} */
const callbackResult = callback();
if (Object(core["ɵisPromise"])(callbackResult)) {
asyncPromises.push(callbackResult);
}
}
catch (e) {
// Ignore exceptions.
console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e);
}
}
}
/** @type {?} */
const complete = (/**
* @return {?}
*/
() => {
/** @type {?} */
const output = platformState.renderToString();
platform.destroy();
return output;
});
if (asyncPromises.length === 0) {
return complete();
}
return Promise
.all(asyncPromises.map((/**
* @param {?} asyncPromise
* @return {?}
*/
asyncPromise => {
return asyncPromise.catch((/**
* @param {?} e
* @return {?}
*/
e => { console.warn('Ignoring BEFORE_APP_SERIALIZED Exception: ', e); }));
})))
.then(complete);
}));
}));
}
这里发生的是,对于 /home
路由,我永远无法进入以 const platformState = platform.injector.get(PlatformState);
开头的回调。我不确定为什么会这样想。
有人有什么想法可以帮忙吗?
更新#1:
我设法将问题缩小到我在 HomeComponent
的 ngOnInit
中使用的 RxJS 运算符。对于这个组件,我正在做一些轮询,所以我有类似的东西:
timer(0, 15000).pipe(
mergeMap(() => this.dataService.fetchData())
).subscribe(...)
为了提供最小的非工作组件,我从我的组件中删除了所有内容并将以下内容添加到 ngOnInit
:
timer(0, 20000).subscribe(
(...args) => console.log(args),
(...args) => console.error(args)
);
现在,当我尝试访问该路线时,它仍然没有加载(如预期的那样),但我在服务器的控制台中看到了来自订阅的值。
您可以在应用程序稳定后触发轮询,在组件中注入 ApplicationRef
,并订阅 isStable