Angular Universal / Server端渲染丢失的文件

时间:2019-02-15 20:09:29

标签: angular-cli

我正在尝试将我的角度应用程序设置为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)

1 个答案:

答案 0 :(得分:0)

这是文档中的错误。

他们的文档代码为

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.jsonprojects:PROJECTNAME:architect:server下的引用。该文档将outputPath定义为"outputPath": "dist/my-project-server",,这意味着我们在dist/my-project-server/main.js中有一个文件(首先要注意点1,并禁用outputHashing或根本不以生产模式构建)。 确实需要在您的requireserver.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中。