设置Angular Universal App进行开发

时间:2018-04-12 21:49:17

标签: node.js angular webpack angular-cli angular-universal

我用Angular-CLI创建了一个项目。 (使用命令:ng new my-angular-universal)。 然后我仔细地按照https://github.com/angular/angular-cli/wiki/stories-universal-rendering

的所有说明进行操作

它为--prod构建并且运行正常。但是,我没有说明如何设置--dev版本并将其标记为--watch

我尝试从npm"脚本"中删除--prod标志,它甚至不能以开发模式运行。它建立得很好但是当我在浏览器中打开它时,这就是我所看到的(直接打印到响应):

 TypeError: Cannot read property 'moduleType' of undefined
    at C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:7069:134
    at ZoneDelegate.invoke (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:105076:26)
    at Object.onInvoke (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:6328:33)
    at ZoneDelegate.invoke (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:105075:32)
    at Zone.run (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:104826:43)
    at NgZone.run (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:6145:69)
    at PlatformRef.bootstrapModuleFactory (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:7068:23)
    at Object.renderModuleFactory (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:52132:39)
    at View.engine (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:104656:23)
    at View.render (C:\Users\Mikser\documents\git\my-angular-universal\dist\server.js:130741:8)

我使用的npm软件包的版本目前是最新的:

  • @ angular / * - @ 5.2。*
  • @ angular / cli @ 1.7.3

除了ts-loader之外,不得不降级它,因为它没有工作:

  • ts-loader @ 3.5.0

因此,如果有人有任何关于如何使这项工作的信息,将非常感谢!或者您可能知道一些项目模板,其中配置了--dev--prod构建的Angular Universal App以及--watch的能力吗?

6 个答案:

答案 0 :(得分:2)

正如贡献者指出的那样,它可能不是最有效和最快速的开发方式,但我不想接受变通方法。此外,在不同的服务器上正面和背面托管会带来CORS问题,我从未计划过我的应用程序在不同的主机上运行,​​我希望它与API方法一起在同一主机上运行。

--dev版本的问题是:

使用以下命令构建时:

ng build --app 1 --output-hashing=false(请注意,没有--prod标志)

AppServerModuleNgFactory./dist-server/main.bundle

中失踪了

我认为这与提前(--aot)编译有关,如果您正在构建--prod,这是默认行为。因此,来自https://github.com/angular/angular-cli/wiki/stories-universal-rendering的说明包含仅为生产构建配置快速服务器的说明。由于服务器无需动态呈现html模板,因此工作--dev构建命令将为:

ng build --app 1 --output-hashing=false --aot

这就摆脱了TypeError: Cannot read property 'moduleType' of undefined

现在观看这整个混乱:

在单独的命令窗口中运行它们:

  1. ng build --watch
  2. ng build --app 1 --output-hashing=false --aot --watch
  3. webpack --config webpack.server.config.js --progress --colors --watch
  4. 要让服务器在更改时重新启动,您必须安装nodemon包并按如下方式运行:

    1. nodemon --inspect dist/server--inspect如果您希望使用chrome调试服务器)
    2. 其他一些重要的事情:

      Angular / CLI具有为通用应用程序生成必要的脚手架的命令:

      ng generate universal

      并生成main.ts的固定版本,以避免client angular bootstrap issuedocument.addEventListener('DOMContentLoaded', () => { platformBrowserDynamic().bootstrapModule(AppModule) .catch(err => console.log(err)); });

      我实施TransferState

      后偶然发现的问题

答案 1 :(得分:0)

基本上有两个部分 - 服务器和UI。在开发UI时,我只使用ng serve。这意味着当我在IDE中对代码进行更改时,浏览器会自动刷新。并且,这里没有使用服务器部分。

我做prod构建并运行服务器只进行最终测试,看看是否一切都按预期工作(由于任何3PP库DOM操作或AOT相关问题等没有错误)。

Here,我创建了一个Angular Universal项目的骨架结构。由于我在项目中广泛使用Vagrant和Docker,因此我在Vagrant客户系统中的Docker容器中运行服务器。对于UI的开发,我不会运行服务器。简单地说,使用了ng serve

如果您在上面的Github链接中查看我的结构,您将在自述文件中找到有关如何运行它以进行开发和生产的详细信息。

答案 2 :(得分:0)

Web服务器处理程序server.ts使用服务器包

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

这就是为什么在编译server.ts文件之前需要编译服务器包的原因。

因此拥有手表系统意味着

  • 观看/重新编译客户端捆绑包
  • 观看/重新编译服务器包
  • 创建服务器捆绑包后重新编译server.ts

所有这些都需要一些时间(特别是如果你这样做的话)

我建议像Saptarshi Basu所提到的那样尽可能地使用ng serve进行开发,并经常检查角度通用。

否则,应该可以通过某种任务(grunt / gulp / ...)实现所需的功能,这些任务会依次触发ng build ...并重新编译server.ts文件。

答案 3 :(得分:0)

对于开发,请运行触发npm run start的{​​{1}}。当前设置有热模块重新加载,因此它将监视您的更改并更新您的开发视图。我使用了相同的说明,并在https://github.com/ariellephan/angular5-universal-template

工作

简而言之,要进行开发,请运行ng serve并查看npm run start

对于制作,请运行http://localhost:4200npm run build:ssr并查看npm run serve:ssr

答案 4 :(得分:0)

毫无疑问,这有点混乱,因为我们最好希望有一个命令来统治所有的命令。 我想出了一个可以的解决方案,我的输出将是: dist /浏览器 dist / ng-server

使用可执行的npm-run-all程序包(我发现它在Windows机器上比并发程序工作得更好),我运行三个监视任务:浏览器,ng-server和nodeJS。监视节点具有一个预定义的任务,该任务仅运行一个小的实用程序/帮助程序/文件,该文件监视dist / ng-server文件夹的存在并在找到后自动终止。

要使所有这些正常工作(基于截至2018年11月的通用启动器存储库),需要对package.json进行一些修改。首先,为了支持ng运行命令上的--watch标志,我们需要更新compile-cli(如果有内存的话),ng update --all应该注意这一点,在此过程中为您提供最新的angular / cli版本(假设您已在全球范围内安装了最新的cli版本。

package.json

  1. ng更新--all
    • 角6 +
    • angular / cli 7 +
  2. yarn add / npm安装以下内容
    • chokidar
    • npm-run-all (与-p标志并行运行我们的任务。-p杀死所有进程,-l在控制台中为每个正在运行的任务指定特定的颜色和名称)
    • ts-node(以ts格式运行nodejs)
    • nodemon //用于重启ts-node
  3. 添加类似于util / await-file.js的内容(经过一些考虑,我在下面添加了我自己的文件监视程序代码,即使它并非完全出于显示目的而编写的……) / li>
  4. 像下面一样修改您的package.json脚本
  5. 按照我的示例,
  6. 修改您的angular.json以匹配您的文件夹名称,主要是将“服务器”的outputPath从dist / server更改为dist / ng-server。

package.json脚本

"dev": "npm-run-all -p -r -l watch:ng-server watch:browser watch:node",
"watch:browser": "ng build --prod --progress --watch --delete-output-path",
"watch:ng-server": "ng run ng-universal-demo:server --watch --delete-output-path",
"watch:node": "yarn run watch:file-exist && yarn run ts-node",
"ts-node": "nodemon --exec ts-node server.ts -e ts,js",
"watch:file-exist": "node utils/await-file.js",

util / await-file.js

const chokidar = require('chokidar');
const fs = require('fs');
const path = require('path');
const DIR_NAME = 'ng-server';

const DIST_PATH = './dist';

// creates dist folder if it doesn't exist - prior to adding it to the watcher.
if (!fs.existsSync(DIST_PATH)) {
  fs.mkdirSync(DIST_PATH);
}

const watcher = chokidar.watch('file, dir', {
  ignored: '*.map',
  persistent: true,
  awaitWriteFinish: {
    stabilityThreshold: 5000,
    pollInterval: 100
  }
});

const FOLDER_PATH = path.join(process.cwd(), 'dist');
watcher.add(FOLDER_PATH);

console.log(`file-watcher running, waiting for ${DIST_PATH}/${DIR_NAME}`);

function fileFound() {
  console.log(`${DIR_NAME} folder found - closing`);
  watcher.close();
  process.exit();
}

watcher
  .on('add', function (filePath) {
    const matchWith = path.join('dist', DIR_NAME);
    const paths = filePath.split(path.sep);
    const fileName = paths[paths.length - 1];
    if ((filePath.indexOf(matchWith) >= 0)
      && fileName.indexOf('.js') > fileName.length - 4) {
      fileFound();
    }
  })
  .on('error', error => console.log(`Watcher error: ${error}`));

答案 5 :(得分:0)

“ npm run start”并使用“ http:// localhost:4200”对我有效。即使使用Angular 10