angular - Angular 12 IVY angular-universal AppServerModuleNgFactory 不存在
问题描述
早上好,首先,对不起我糟糕的英语,但我需要帮助。
情况:Angular 12 + Universal SSR 我从 Angular 11 View Engine(完美运行)更新到 Angular 12,我想使用 SSR 的 Ivy。
问题:我们有多个网站的 1 个 SSR,在不同的项目中,并且运行 PM2 服务器。
如果我在 SSR 项目 AppServerModuleNgFactory 中使用,我会收到该消息
TypeError:无法读取未定义的属性“moduleType”
在预览 Angular 11 视图引擎 main.js 存在 AppServerModuleNgFactory 但在新的 Angular 12 Ivy main.js 不存在 AppServerModuleNgFactory
非常感谢
const { AppServerModuleNgFactory } = require(Path.resolve(
process.cwd(),
"lib/sites-ssr/main"
));
const fileLocation = Path.resolve(process.cwd(), "views") + "/index" + req.query.hashfile + ".html";
const indexHtml = readFileSync(fileLocation, "utf-8").toString();
const url = SITE_CONFIG.public_path + req.originalUrl.split("?")[0]";
renderModuleFactory(AppServerModuleNgFactory, {
document: indexHtml,
url: url,
})
.then((html) => {
res.status(200).send(new SSRResponse({
posts: global["posts_ssr"],
},html));
})
.catch((err) => {
console.log(err);
res.sendStatus(500);
});
但是,如果我在没有 NgFactory 的情况下使用 AppServerModule,我会收到该消息
TypeError:无法读取未定义的属性“名称”
我在控制台中打印的下一个对象
<ref *1> [class AppServerModule] { 'ɵfac': [Function: AppServerModule_Factory], 'ɵmod': { type: [Circular *1], bootstrap: [ [Function] ], declarations: [], imports: [] ,出口:[],transitiveCompileScopes:null,模式:null,id:null},'ɵinj':{提供者:[],进口:[[Array]]}}
这里的结构主要项目
-Project
-tsconfig.json
-package.json
-angular.json
-src
-app
-app.server.module.ts
-projects
-projectName
-main.server.ts
-tsconfig.app.json
-tsconfig.server.json
-src
-main.ts
文件:package.json
"scripts": {
"build": "ng run projectName:build:production --optimization=true",
"build-server": "ng run projectName:server:production"
}
角.json
"projectName": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/projectName",
"index": "projects/projectName/src/index.html",
"main": "projects/projectName/src/main.ts",
"polyfills": "projects/projectName/src/polyfills.ts",
"tsConfig": "projects/projectName/tsconfig.app.json",
"aot": true,
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "projects/projectName/src/environments/environment.ts",
"with": "projects/projectName/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "none",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": false,
"aot": true,
"serviceWorker": false,
},
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "nameProject:build:production"
},
"development": {
"browserTarget": "nameProject:build:development"
}
},
"defaultConfiguration": "development"
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/nameProject/tsconfig.app.json",
"projects/nameProject/tsconfig.spec.json",
"projects/nameProject/e2e/tsconfig.json"
],
"exclude": ["**/node_modules/**"]
}
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/server",
"main": "./projects/nameProject/main.server.ts",
"tsConfig": "./projects/nameProject/tsconfig.server.json",
"bundleDependencies": false
},
"configurations": {
"production": {
"sourceMap": false,
"optimization": true,
},
}
},
}
}
构建 main.ts
import "zone.js";
enableProdMode();
document.addEventListener("DOMContentLoaded", () => {
platformBrowserDynamic()
.bootstrapModule(ProjectNameModule)
.catch((err) => console.log(err));
});
构建 tsconfig.app.json
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/app",
"types": []
},
"angularCompilerOptions": {
"enableIvy": true,
"preserveWhitespaces": false,
"genDir": "compiled",
"skipMetadataEmit": true
},
"files": ["./src/main.ts", "./src/polyfills.ts"],
"include": ["src/**/*.d.ts"]
}
构建 ../../tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": false,
"declaration": false,
"module": "es2020",
"moduleResolution": "node",
"target": "es2015",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"importHelpers": true,
"typeRoots": ["node_modules/@types"],
"lib": ["es2018", "dom"],
"types": ["node"],
},
"exclude": ["node_modules"],
"files": [
"./projects/nameProject/src/main.ts",
"./projects/nameProject/main.server.ts",
"./src/polyfills.ts",
"./custom.d.ts",
"./src/app/app.module.ts",
],
"angularCompilerOptions": {
"enableIvy": true
}
}
服务器 main.server.ts
import "zone.js";
enableProdMode();
export { AppServerModule } from "../../src/app/app.server.module";
export { renderModule, renderModuleFactory } from "@angular/platform-server";
应用服务器模块
import {
ServerModule,
ServerTransferStateModule,
} from "@angular/platform-server";
import { AppComponent } from "./app.component";
import { NameProjectModule } from "../../projects/nameProject/src/app/nameProject.module";
import { NgModule } from "@angular/core";
@NgModule({
imports: [NameProjectModule, ServerModule, ServerTransferStateModule],
bootstrap: [AppComponent],
providers: [],
exports: [],
})
export class AppServerModule {}
服务器 tsconfig.server.json
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"outDir": "../../out-tsc/app-server",
"baseUrl": "./",
// Set the module format to "commonjs":
"module": "commonjs",
"types": ["node"]
},
"files": [
"main.server.ts",
"server.ts"
],
"exclude": ["test.ts", "**/*.spec.ts"],
// Add "angularCompilerOptions" with the AppServerModule you wrote
// set as the "entryModule".
"angularCompilerOptions": {
"entryModule": "src/app/app.server.module#AppServerModule",
"enableIvy": true
}
}
结构项目SSR,弹出顺序为app.ts -> view-render.controller.ts -> server.ts -> env-selector.ts
-Project
-lib
-app.ts
-server.ts
-controllers
-view-renderer
-view-renderer.controller.ts
-sites-ssr
-environments
env-selector.ts
-main.js
应用程序.ts
constructor() {
this.app = express();
this.config();
this.app.use(express.json());
this.routes.routes(this.app); // routes in view-render.controller.ts
this.app.disable("view cache");
}
视图-render.controller.ts
const { AppServerModuleNgFactory } = require("../../sites-ssr/main");
public routes(app) {
this.app = app;
app.route("*").post((req, res) => {
this.proxyRequest(req, res);
});
}
proxyRequest(req, res) {
setEnv(this.app, req, res)
.then((env) => {
const fileLocation =
Path.resolve(process.cwd(), "views") +
"/index" +
req.query.hashfile +
".html";
const indexHtml = readFileSync(fileLocation, "utf-8").toString();
const url = SITE_CONFIG.public_path + req.originalUrl.split("?")[0];
res.render(fileLocation, { req }, function (err, html) {
renderModuleFactory(AppServerModuleNgFactory, {
document: html,
url: url,
})
.then((html) => {
res.send(
new SSRResponse(
{
posts: global["posts_ssr"],
},
html
)
);
}
})
.catch((err) => {
console.log(err);
res.sendStatus(500);
});
});
})
.catch((err) => {
console.log(err);
});
}
解决方案
推荐阅读
- spamassassin - SpamAssassin RDNS_DYNAMIC 和 HELO_DYNAMIC_IPADDR
- c++ - 从我的对象返回静态数组
- coldfusion - ColdFusion 列表值替换
- typescript - 用空的 Promise 替换 http 调用
- django - UserProfile db 在 django 中显示(无)
- html - 如何将 UI 简单下拉列表转换为可点击?
- linux - Bash 函数忽略 set -e
- python - Python压缩字符串不太正确
- vue.js - 如何对所有元素使用相同的插槽元素?
- django - 在 django rest 中仅允许特定用户(即创建该模型的用户)访问视图