我正在尝试将我的角度应用程序设置为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文件夹中得到的: / p>
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)
答案 0 :(得分:0)
这是文档中的错误。
他们的文档代码为
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./server/main');
但是,这不正确,或者至少不是很清楚。
尽管您在文档中看到一行,但他们希望您将其包含在package.json的脚本部分中,例如
ng run my-project:server:production
您不应这样做,有两个原因:首先,他们更改angular.json的指令不包括生产版本。其次,生产构建(如果您只是从实际的非服务器应用的生产中复制的)是通过在文件名中包含哈希来进行的,该哈希将导致文件名为main.a220df2.js
。这当然不是理想的,因为这意味着您必须一直更改server.ts。
因此,要么禁用哈希"outputHashing": "none"
,要么干脆不通过调用ng run my-project:server
进行生产构建(只需删除:production
)。
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或根本不以生产模式构建)。
确实需要在您的require
中server.ts
来存储此文件。
因此,在您的情况下,一旦您禁用了输出,则应包含文件./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
中。