Angular Universal 12(服务器端)在延迟加载时不加载模块
Posted
技术标签:
【中文标题】Angular Universal 12(服务器端)在延迟加载时不加载模块【英文标题】:Angular Universal 12 ( Server side ) not loading modules on lazy load 【发布时间】:2021-11-29 02:06:17 【问题描述】:我有一个只有一个模块的小型应用程序,该应用程序工作正常,但它没有在页面源上呈现组件。 问题是当我使用 npm run dev:s-s-r 启动应用程序时,一切都很好(在页面源代码上,您有在标签之后加载的组件(在我的情况下为主页组件),您可以看到元标签,所以一切看起来工作正常),在 npm run serve:s-s-r 上仍然是一样的,一切看起来都很好,似乎一切正常。 但问题是当我发布应用程序时,在服务器上,标签后缺少 home-component。
这是 npm run dev:s-s-r 页面源的图片:
这是已发布版本的页面来源图片:
这里是 tsconfig.server.json
"extends": "./tsconfig.app.json",
"compilerOptions":
"outDir": "./out-tsc/server",
"target": "es2019",
"types": [
"node"
]
,
"files": [
"src/main.server.ts",
"server.ts"
],
"angularCompilerOptions":
"entryModule": "./src/app/app.server.module#AppServerModule"
这是我的 server.ts 文件:
import 'zone.js/dist/zone-node';
import ngExpressEngine from '@nguniversal/express-engine';
import * as express from 'express';
import join from 'path';
import AppServerModule from './src/main.server';
import APP_BASE_HREF from '@angular/common';
import existsSync from 'fs';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express
const server = express();
const distFolder = join(process.cwd(), 'dist/browser');
const indexhtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', ngExpressEngine(
bootstrap: AppServerModule,
));
server.set('view engine', 'html');
server.set('views', distFolder);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => );
// Serve static files from /browser
server.get('*.*', express.static(distFolder,
maxAge: '1y'
));
// All regular routes use the Universal engine
server.get('*', (req: express.Request, res: express.Response) =>
res.render(indexHtml, req, providers: [ provide: APP_BASE_HREF, useValue: req.baseUrl ] );
);
return server;
function run(): void
const port = process.env.PORT || 4000;
// Start up the Node server
const server = app();
server.listen(port, () =>
console.log(`Node Express server listening on http://localhost:$port`);
);
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode'))
run();
export * from './src/main.server';
<!-- end snippet -->
**Here is main.serve.ts file:**
import '@angular/platform-server/init';
import enableProdMode from '@angular/core';
import environment from './environments/environment';
if (environment.production)
enableProdMode();
export AppServerModule from './app/app.server.module';
export renderModule, renderModuleFactory from '@angular/platform-server';
export AppServerModule from './app/app.server.module';
export renderModule, renderModuleFactory from '@angular/platform-server';
**Here is app.server.module.ts file:**
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
import NgModule from '@angular/core';
import ServerModule from '@angular/platform-server';
import AppModule from './app.module';
import AppComponent from './app.component';
@NgModule(
imports: [
AppModule,
ServerModule,
],
bootstrap: [AppComponent],
)
export class AppServerModule
这里是 app.server.module.ts 文件:
import NgModule from '@angular/core';
import ServerModule from '@angular/platform-server';
import AppModule from './app.module';
import AppComponent from './app.component';
@NgModule(
imports: [
AppModule,
ServerModule,
],
bootstrap: [AppComponent],
)
export class AppServerModule
这里是 app.module.ts 文件:
import HttpClientModule from '@angular/common/http';
import NgModule from '@angular/core';
import BrowserModule from '@angular/platform-browser';
import RouterModule from '@angular/router';
import AppRoutingModule from './app-routing.module';
import AppComponent from './app.component';
@NgModule(
declarations: [
AppComponent
],
imports: [
BrowserModule.withServerTransition( appId: 'serverApp' ),
HttpClientModule,
RouterModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
)
export class AppModule
这是我的 app-routing.module.ts 文件:
import NgModule from '@angular/core';
import RouterModule, Routes from '@angular/router';
const routes: Routes = [
path : '',
redirectTo : 'home',
pathMatch : 'full',
,
path : 'home',
loadChildren : () => import('./home/home.module').then(m => m.HomeModule)
,
path : '**',
redirectTo : '',
pathMatch : 'full',
,
];
@NgModule(
imports: [
RouterModule.forRoot(routes)
],
exports: [RouterModule]
)
export class AppRoutingModule
编辑: 我目前找到的解决方案是在 tsconfig.server.json 文件中添加 module: commonjs,该应用程序比平时慢了一点,但它正在完成它的工作。如果有人有更好的解决方案,请随时留下答案。
【问题讨论】:
你在使用 angular service-worker/pwa 吗? @Pieterjan 不,我没有使用任何东西,我只是创建了新的应用程序,添加了@nguniversal/express-engine,添加了一个模块并使其延迟加载,我在组件中添加了元标记在那个延迟加载的模块中,就是这样,我没有做任何其他事情或将任何其他包添加到应用程序中。 您找到解决方案了吗?我这边也有同样的问题。 解决方案在我发布的帖子的末尾(在编辑部分)。我在 tsconfig.server.json 文件中添加了模块:commonjs,应用程序比平时慢,但它正在完成它的工作。 @Shakir 可以分享tsconfig.server.json
的代码
【参考方案1】:
您缺少 Angular Universal 所需的 initialNavigation
属性。
@NgModule(
imports: [RouterModule.forRoot(routes,
initialNavigation: 'enabled'
)],
exports: [RouterModule],
)
export class AppRoutingModule
【讨论】:
如果我添加 initialNavigation: 'enabled' 它根本不会打开我部署的应用程序,它只是在加载应用程序的选项卡上有微调器,但它根本没有打开。 还有@LukaszGawrys,initialNavigation: 'enabled' 在 Angular v11 link987654321@ 之后可以 1:1 替换为 enabledBlocking以上是关于Angular Universal 12(服务器端)在延迟加载时不加载模块的主要内容,如果未能解决你的问题,请参考以下文章
Angular 2 Universal - 使用手写笔和 pug 模板的服务器端渲染
Angular 5 Universal 在服务器端渲染期间等待 http 请求返回
使用 Angular Universal 在服务器端运行时找不到模块环境
Angular Universal 与 i18n(服务器端渲染)