我正在尝试让我的angular应用程序支持ssr,在official documentation中它说我应该运行
webpack --config webpack.server.config.js --progress --colors
但是我不能让它正确编译:
ERROR in ./server.ts
Module not found: Error: Can't resolve './server/main' in '/home/lucaswxp/reduza/reduza-angular'
@ ./server.ts 18:9-33
带问题的线路:
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./server/main');
这些文件应该是动态创建的,这就是为什么"require“需要它们的原因,但dist文件夹中没有"server/main.js”文件,这是我在dist文件夹中得到的:
out-tsc/
e2e/
src/
node_modules/
reduza-ui/ <-- my project name
main.08ht283hg20s3.js
server.js
server.js.map
和我的angular.json配置:
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/reduza-ui",
"main": "src/server.main.ts",
"tsConfig": "src/server.tsconfig.app.json"
},
"configurations": {
"stable": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
}
没有“服务器”文件夹。我不知道我错过了什么?我尝试手动包含编译后的文件dist/reduza-ui/main.08ht283hg20s3.js
,但在访问localhost:4000
时出现以下错误
TypeError: Cannot read property 'moduleType' of undefined
at /home/lucaswxp/reduza/reduza-angular/dist/server.js:151:1457
at e.invoke (/home/lucaswxp/reduza/reduza-angular/dist/server.js:1809:7001)
at Object.onInvoke (/home/lucaswxp/reduza/reduza-angular/dist/server.js:137:1986)
at e.invoke (/home/lucaswxp/reduza/reduza-angular/dist/server.js:1809:6941)
at t.run (/home/lucaswxp/reduza/reduza-angular/dist/server.js:1809:2171)
at e.run (/home/lucaswxp/reduza/reduza-angular/dist/server.js:137:2710)
at e.bootstrapModuleFactory (/home/lucaswxp/reduza/reduza-angular/dist/server.js:151:1388)
at md (/home/lucaswxp/reduza/reduza-angular/dist/server.js:1673:888)
at p.engine (/home/lucaswxp/reduza/reduza-angular/dist/server.js:1794:10074)
at p.render (/home/lucaswxp/reduza/reduza-angular/dist/server.js:1984:1029)
发布于 2019-03-03 13:04:58
这是文档中的一个错误。
他们的文档代码是
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./server/main');
然而,这是不正确的,或者至少不是很清楚。
要点1:您不应该在生产模式下构建。
尽管您在文档中看到了他们希望您在package.json的脚本部分中包含的一行代码,但如下所示
ng run my-project:server:production
您不应该这样做,原因有两个:首先,他们更改angular.json的指令不包括生产构建。其次,生产构建(如果您只是从实际的非服务器应用程序的生产中复制)是以一种在文件名中包含散列的方式进行的,这将导致一个名为main.a220df2.js
的文件。这当然不是很理想,因为这意味着你必须一直改变你的server.ts。
因此,要么禁用散列"outputHashing": "none"
,要么干脆不通过调用ng run my-project:server
进行生产构建(简单地删除:production
)。
要点2:使用正确的require
实际的require()调用应该指向您构建的main.server.ts
,它是angular.json
中projects:PROJECTNAME:architect:server
部分下的引用。文档已经将outputPath定义为"outputPath": "dist/my-project-server",
,这意味着我们在dist/my-project-server/main.js
中有一个文件(首先处理第1点并禁用outputHashing,或者根本不在生产模式下构建)。在您的server.ts
中,这个文件必须是require
d。
因此,在您的示例中,一旦禁用了outputHasing或在生产模式下停止构建,就应该包含./dist/reduza-ui/main.js
文件。
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/reduza-ui/main');
额外的提示:在文档的最顶端,您可以看到指向整篇文章的完整代码的链接:https://angular.io/generated/zips/universal/universal.zip。在那里你可以看到真正的代码应该是什么样子的。
让它完全工作的最后两个技巧:
第一
文档用server.ts写着类似这样的内容:
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
browser
是你的应用程序的实际默认版本,所以你的常规构建。如果你使用ng build
,你最终会在dist/
中拥有一个文件夹,这是你实际的默认应用。这个应用是由browser
开发的。在您的示例中,您将服务器版本命名为reduza-ui
,因此在dist中,您的实际应用程序可能被命名为reduza-ui-default
。在server.ts中,有几个地方需要使用'reduza-ui-default'
而不是'browser'
。
第二
此时,当您编译服务器、启动服务器并在浏览器中请求第一个页面时,您将进入控制台:
StaticInjectorError(Platform: core)[InjectionToken Application Initializer -> InjectionToken DocumentToken]:
Right-hand side of 'instanceof' is not an object
这是因为webpack最小化了你的server.ts。使用以下命令禁用该功能
optimization: {
minimize: false
},
在webpack.server.config.js
中。
https://stackoverflow.com/questions/54716371
复制