在开发环境中使用 Angular CLI 连接 express.js

Posted

技术标签:

【中文标题】在开发环境中使用 Angular CLI 连接 express.js【英文标题】:Hooking up express.js with Angular CLI in dev environment 【发布时间】:2017-08-11 06:11:31 【问题描述】:

我找到了一个很棒的教程,它解释了如何使用 Angular CLI 设置 express.js,但是在本教程中,Angular 应用程序被编译到一个生产 dist 文件夹中: https://scotch.io/tutorials/mean-app-with-angular-2-and-the-angular-cli

如何将 express.js 与 Angular CLI 集成,但我希望 express.js 与 Angular 应用程序的开发版本一起使用,并且如果我对 express 或 angular 应用程序进行更改,我希望 nodemon 重新启动。

已经花费了超过 8 个小时试图让这项工作正常进行。谢谢!

我不想每次对 Angular 应用程序进行更改时都运行“ng build”(这需要很长时间) - 我希望在保存对我的 Angular 应用程序的更改时立即重新加载(就像我正在运行一样'ng serve') 或 express 应用程序。

我找到了一个教程,您可以在其中将 Angular 2 QuickStart 与 Express 连接起来,它可以工作,但我希望使用 Angular CLI。

我了解 Angular CLI 使用 WebPack 而 QuickStart 使用 System.js

【问题讨论】:

【参考方案1】:

新答案

我 15 小时的经验告诉我,尝试为 Angular 应用程序提供服务 在开发过程中使用 Express 并不是一个好主意。正确的方法是将 Angular 和 Express 作为两个不同的应用程序在两个不同的端口上运行。 Angular 将像往常一样在 4200 端口上提供服务,Express 将在 3000 端口上提供服务。然后为 Express 应用的 API 调用配置代理。

将 proxy.config.json 添加到 Angular 项目的根目录:


  "/api/*":
    "target":"http://localhost:3000",
    "secure":false,
    "logLevel":"debug"
  

打开一个新的终端选项卡并运行此命令以启动 Express 应用程序:

nodemon [YOUR_EXPRESS_APP.js] --watch server

(YOUR_EXPRESS_APP.js 通常命名为 server.js 或 app.js。server 是您保存所有 Express 应用程序文件的目录)

打开第二个终端选项卡并运行以下命令来启动 Angular 应用程序:

ng serve --proxy-config proxy.config.json

这将确保在对任何 Angular 应用程序文件进行更改时重新构建 Angular 应用程序并重新加载浏览器。同样,当任何 Express 应用程序文件发生更改时,Express 服务器将重新启动。

你的 Angular 应用在​​这里:http://localhost:4200/

观看此视频,了解如何configure a proxy for your API calls with Angular CLI

注意: 此设置仅适用于开发环境。在生产环境中,您需要运行 ng build 并将 Angular 应用程序放在 dist 目录中,以便由 Express 提供服务。在生产环境中,只有一个应用程序在运行——一个 Express 应用程序为您的 Angular 应用程序提供服务。

以前的答案

使用来自@echonax 的输入,我想出了这个非常快的解决方案:

将 Express 添加到 Angular 2 应用程序(使用 Angular CLI 构建),如 tutorial 在终端中运行:

ng build -w & nodemon server.js --watch dist --watch server

这会将 Angular 应用程序重新构建到 dist 文件夹中,并且每次发生这种情况时节点服务器都会重新启动。但是,此设置不会自动刷新浏览器:(

更多信息在这里:

https://github.com/jprichardson/reload

【讨论】:

这帮助我理解了 ngCli 在做什么。我不想在这里堆积更多的答案,但我最终有一个backendfronend 文件夹,复制ng build 生成的index.html,然后只用node app.js 运行我的服务器和我的构建资产服务器ng serve --live-reload=false,所以它不会尝试继续重新连接到 WDS。研究如何重定向该请求,但现在这似乎可行并且与此答案相似,但后端和前端更加分开 Angular 文档现在很好地涵盖了这里描述的代理方法。见Proxying to a backend server。 我正在处理完全相同的问题。您能否详细说明为什么不建议在 express 上提供 Angular 服务?我的第一个想法正是你的答案加上 Yusuf 的并发解决方案(花了 5 个小时重新发明了一个***......)但我突然想到,从 express 服务 Angular 将是一个更优雅的解决方案,因为它只是一个服务(?)而不是代理。是因为易于实现,还是更正确地反映了生产环境?很想听听你对这个问题的看法。谢谢。【参考方案2】:

"etayluz" solution 很好。但我想为 NEW ANSWER 添加一个附加选项,以不打开两次终端。

首先你必须同时安装包(https://www.npmjs.com/package/concurrently);

npm install concurrently --save 

然后您可以将以下代码添加到您的 package.json 文件中。

"start": "concurrently \"npm run serve-api\" \"npm run serve\"",
"serve": "ng serve --port 3333 --proxy-config proxy.config.json", // You could add --port for changing port
"serve-api": "nodemon [YOUR_EXPRESS_APP.js] --watch server",

npm start 足以运行您的项目。

【讨论】:

etayluz 解决方案与并发是完美的并且工作正常。好主意。 这只是为了开发。也不要在应用“一个容器一个进程”的 heroku 和类似平台上工作【参考方案3】:

使用 angular-cli,ng buildng build --prod 命令将为您提供捆绑文件以及 index.html。让你的 app.js(node/express) 定位到这个文件。

例子:

app.use( express.static(__dirname + '/src' ) ); //<- it will automatically search for index.html under src folder.

【讨论】:

'ng build' 将我的 Angular 应用程序构建到 dist 文件夹中。这需要时间。我不想等待这么久,每次需要进行更改时手动构建 Angular 应用程序。这就是为什么我想要 express 指向使用 Angular CLI 生成的 Angular 2 应用程序的开发版本的原因。有可能吗? @etayluz 如果您像ng build -w 一样添加-w,cli 将监视客户端发生的更改并再次重新构建(根据增量)。这样能解决问题吗? @etayluz nope :/ 我将保持原样回答,以便人们对情况有所了解。也许你可以就这个主题向 angular-cli 提出问题? ng build --watch 在第一次运行时需要一些时间,但每次您进行更改时它会在 1 或 2 秒内编译。 @gyc 这也是我的经验,这就是为什么我说“重新构建(根据增量)”,但我猜 OP 有不同的经验。【参考方案4】:

更长的解释

我花了相当多的时间来弄清楚如何在我自己的开发环境中做到这一点。我想出的最好的是结合了许多 echonax、squirrelsareduck 和 Max 的解决方案的双重实现,但利用内置的 Angular CLI 策略来观察前端/Angular 变化,并使用 nodemon 来观察后端/表达变化。简而言之,您最终会运行两个进程(ng build 和 nodemon)来启动并运行您的开发环境,但它会自动重建并在一个 Express Web 服务器下运行所有​​内容。

您需要运行的第一个过程是构建 Angular dist 文件夹,并观察对 Angular 前端所做的任何更改。对我们来说幸运的是,Angular CLI 可以使用以下命令在本机上执行此操作(在 Angular CLI >= 1.5 上测试):

ng build --watch

您需要让它在后台运行,但这将监视 Angular 代码中所做的任何更改,并即时重建捆绑包。

第二个过程涉及使用 nodemon 来运行您的 Express 服务器,并且可能需要更多的设置和规划,具体取决于您的后端/Express 设置的范围。只需确保 Express 指向 dist 文件夹中的索引文件。这里最大的优势是,您可以使用 gulp-nodemon 将所有这些添加到 Gulpfile 中,以便在运行 nodemon 以观察后端/Express 之后执行更多顺序任务,例如检查后端、运行与构建并行的测试、缩小后端,或者任何你能想到的使用 Gulp 的东西。使用 npmYarn 将 nodemon 添加并安装到项目的依赖项中,然后运行以下命令来启动您的 Express 服务器:

nodemon app.js

app.js 替换为您用于构建 Express 后端的任何文件,它现在应该在您的后端发生更改时重新构建。 p>

tldr;

在后台运行两个单独的进程以启动您的开发环境。第一次运行:

ng build --watch

其次,将 nodemon 添加到您的项目依赖项中,并在后台运行以下命令,其中 app.js 被替换为您的 Express 文件调用:

nodemon app.js

奖金

既然您询问了如何自动重新加载浏览器,那么最好的办法是利用名为 LiveReload 的浏览器插件。由于我们已经使用 nodemon 来监视我们的后端,如果您还没有将 nodemon 和 LiveReload 作为两个任务运行,您可能会认真考虑使用 Gulp。在 Gulp 中实现 LiveReload 的最佳选择是使用 gulp-refresh 插件,因为这是 gulp-livereload 插件的更新版本。你最终会得到一个类似这样的 Gulpfile:

const defaultAssets = require('./config/assets/default'),
  gulp = require('gulp'),
  gulpLoadPlugins = require('gulp-load-plugins'),
  runSequence = require('run-sequence'),
  plugins = gulpLoadPlugins(),
  semver = require('semver');
  
// I store the locations of my backend js files in a config file, so 
// that I can call them later on. ie; defaultAssets
gulp.task('nodemon', function () 
  // Node.js v7 and newer use different debug argument
  const debugArgument = semver.satisfies(process.versions.node, '>=7.0.0') ? '--inspect' : '--debug';

  return plugins.nodemon(
    script: 'app.js',
    nodeArgs: [debugArgument],
    ext: 'js,html',
    verbose: true,
    watch: defaultAssets.server.allJS
  );
);

// Watch Files For Changes
gulp.task('watch', function () 
  // Start LiveReload
  plugins.refresh.listen();

  // Watch backend for changes
  gulp.watch(defaultAssets.server.allJS).on('change', plugins.refresh.changed);
  // Watch frontend dist folder for changes
  gulp.watch('./dist').on('change', plugins.refresh.changed);
);
  
  
gulp.task('default', function (done) 
  runSequence(['nodemon', 'watch'], done);
);

现在您只需运行 gulp 命令代替 nodemon app.js 即可启动您的 Express 服务器。

【讨论】:

【参考方案5】:

我也想知道这个。 Max Schwarzmüller 的关于 MEAN 堆栈的 Udemy 课程中有一个用于集成 Express 和 Angular 的示例代码。在该示例代码的 package.json 文件中,使用 scripts.build 属性为 webpack 提供一个命令,该命令监视 angular 文件并相应地更新。我不想在这里复制他的代码,但这是一般的想法。其余的将需要一些发现工作。

在自述文件中,他建议运行运行 webpack 的 npm run build,然后在一个新的终端中为节点服务器运行 npm start。所以理论上,这会运行两个程序,就像你在你的答案版本中建议的那样。但是,它以一种更“脚本化”/预定义的方式来启动 Angular 构建过程,而不是导航到 Angular 子目录并在其中输入 ng build --watch 并单独启动 Express 应用程序。

【讨论】:

【参考方案6】:

也许您可以添加一个名为“concurrently”或(npm-run-all、parallelshell)的依赖项。

npm i concurrently --save-dev

然后像这样编辑 package.json: `

"scripts": 
        "dev": "concurrently \"ng build -w\"  \"cross-env NODE_ENV=development node .\" "
    

` 这可能行得通。

参考资料:

concurrently 示例:https://***.com/a/30950298/7421101,

npm-run-all 示例:https://***.com/a/38213212/7421101,

parallelshell 示例:https://***.com/a/42373547/7421101。

【讨论】:

【参考方案7】:

src目录下的proxy.conf.json文件,代码-


  "/api/*": 
    "target": "http://localhost:3000",
    "secure": false,
    "logLevel": "debug",
    "changeOrigin": true
  

然后编辑package.json,添加这3个条目-(用你在Angular项目根目录中的express文件替换back.js)

"scripts": 
    "client": "ng serve",
    "server": "nodemon back.js",
    "start": "npm-run-all -p client server"
  

现在运行 npm start 将在开发环境中同时启动 Angular 和 Express。

【讨论】:

以上是关于在开发环境中使用 Angular CLI 连接 express.js的主要内容,如果未能解决你的问题,请参考以下文章

由angular命令行工具(angular-cli)生成的目录和文件

Angular 5 在运行时使用 Angular CLI 加载语言环境

Visual Studio Code作为Angular开发工具常用插件安装json-server安装与使用angular/cli安装失败问题

如何在离线时安装 npm 包?

angular-cli:依赖于环境的 CSS

如何使用 Angular Cli 运行 tslint?