gpt4 book ai didi

Angular Universal 预生成页面 : The selector "app-root" did not match any elements

转载 作者:行者123 更新时间:2023-12-02 14:27:20 25 4
gpt4 key购买 nike

我一直在尝试拼凑如何预生成现有 Angular 通用应用程序的页面。我陷入了这个异常(exception):

The selector "app-root" did not match any elements.

执行 node dist/pre-render.js / 时出现该异常.

请注意,此应用程序可以与 ng serve 配合使用。和npm run build:universal; npm run serve:universal 。所以这不仅仅是忘记在 app.module 中放入一些东西那么简单的declarations .

重现步骤:

  1. 运行npm run build:universal
  2. 运行node dist/pre-render.js /
  3. 观察错误 The selector "app-root" did not match any elements

设置如下:

package.json脚本部分

我认为这与 the Angular guide 相同.

"build:universal": "npm run build:client-and-server-bundles && npm run webpack:server",
"serve:universal": "node dist/server.js",
"build:client-and-server-bundles": "ng build --prod && ng build --prod --app 1 --output-hashing=false",
"webpack:server": "webpack --config webpack.server.config.js --progress --colors"

webpack.server.config.js

这也是straight out of the guide ,除非你会注意到我还有一个额外的 entry这产生了我的 pre-render.js来自 pre-render.ts 的脚本接下来我将展示它。

const path = require('path');
const webpack = require('webpack');


module.exports = {
entry: {
server: './server.ts',
'pre-render': './pre-render.ts'
},
resolve: { extensions: ['.js', '.ts'] },
target: 'node',
// This makes sure we include node_modules and other third-party libraries.
externals: [/(node_modules|main\..*\.js)/],
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.ts$/,
loader: 'ts-loader'
}]
},
plugins: [
// Temporary Fix for issue: https://github.com/angular/angular/issues/11580
// for 'WARNING Critical dependency: the request of a dependency is an expression'
new webpack.ContextReplacementPlugin(
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
};

pre-render.ts

我从 the guide's server.ts file 得到了提示和来自 a book by Philippe Martin 。该指南尚未解释如何执行此操作,并且 Philippe 书中的示例对我不起作用。

import 'zone.js/dist/zone-node';
import { renderModuleFactory } from '@angular/platform-server';
import { enableProdMode } from '@angular/core';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

const args = process.argv.slice(2);
if (args.length !== 1) {
process.stdout.write('Usage: node dist/pre-render.js <url>');
process.exit();
}

enableProdMode();
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');

renderModuleFactory(
AppServerModuleNgFactory,
{
url: args[0],
extraProviders: [
provideModuleMap(LAZY_MODULE_MAP)
]
}
).then(rendered => {
process.stdout.write(rendered);
});

说实话,我不知道extraProviders是什么。属性用于,或者如果 provideModuleMap(...)扔进去是正确的。但如果我不给它任何 extraProviders然后我得到这个错误:

NullInjectorError: No provider for InjectionToken MODULE_MAP

很明显,属性(property)对于某些事物来说一定很重要。

此外,我注意到插入 document旁边的属性(property)urlextraProviders没有任何效果,即使document property 是一个没有任何 <app-root> 的字符串元素。

最佳答案

所缺少的是 document属性包含 <app-root></app-root>字符串中某处的元素。

当我将此对象作为第二个参数传递给 renderModuleFactory 时,它起作用了。请注意添加 document属性:

document: `<!DOCTYPE html>
<html>
<body>
<app-root></app-root>
</body>
</html>`,
url: args[0],
extraProviders: [
provideModuleMap(LAZY_MODULE_MAP)
]

现在,虽然这会导致某些内容被渲染,但它并不完全正确,因为我们从 document 开始。与我们的 index.html 的内容不同的字符串.

要解决这个问题,只需执行 Angular Universal Starter 在 its prerender.ts file 中所做的操作即可。 :

const index = readFileSync(join('browser', 'index.html'), 'utf8');

renderModuleFactory(AppServerModuleNgFactory, {
document: index,
url: route,
extraProviders: [
provideModuleMap(LAZY_MODULE_MAP)
]
})

注意他们如何读取编译后的 browser/index.html 的内容文件并使用 that 字符串作为 document属性。

关于Angular Universal 预生成页面 : The selector "app-root" did not match any elements,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49521894/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com