在角度通用应用程序(nodejs)上集成newrelic

Posted

技术标签:

【中文标题】在角度通用应用程序(nodejs)上集成newrelic【英文标题】:Integrating newrelic on angular universal application (nodejs) 【发布时间】:2018-06-08 19:11:44 【问题描述】:

我正在 nodejs 应用程序上集成 newrelic,使用 Angular Universal 制作。我正在使用 webpack 进行捆绑

ma​​in.server.aot.ts 中的第一行

const newrelic = require('newrelic');

并在根目录中添加了 newrelic.js

运行构建弹出以下错误:-

ERROR in ./node_modules/@newrelic/native-metrics/lib/pre-build.js
Module not found: Error: Can't resolve '../package' in 'D:\repos\ib-mobile\node_modules\@newrelic\native-metrics\lib'
 @ ./node_modules/@newrelic/native-metrics/lib/pre-build.js 40:12-33
 @ ./node_modules/@newrelic/native-metrics/index.js
 @ ./node_modules/newrelic/lib/sampler.js
 @ ./node_modules/newrelic/lib/agent.js
 @ ./node_modules/newrelic/index.js
 @ ./src/main.server.aot.ts

ERROR in ./node_modules/node-gyp/lib/node-gyp.js
Module not found: Error: Can't resolve '../package' in 'D:\repos\ib-mobile\node_modules\node-gyp\lib'
 @ ./node_modules/node-gyp/lib/node-gyp.js 67:16-37
 @ ./node_modules/@newrelic/native-metrics/lib/pre-build.js
 @ ./node_modules/@newrelic/native-metrics/index.js
 @ ./node_modules/newrelic/lib/sampler.js
 @ ./node_modules/newrelic/lib/agent.js
 @ ./node_modules/newrelic/index.js
 @ ./src/main.server.aot.ts

ERROR in ./node_modules/newrelic/index.js
Module not found: Error: Can't resolve './package' in 'D:\repos\ib-mobile\node_modules\newrelic'
 @ ./node_modules/newrelic/index.js 13:19-39
 @ ./src/main.server.aot.ts

如果我在 webpack 配置中添加 newrelic 作为外部组件

module.exports = 
  entry: root('./src/main.server.aot.ts'),
  output: 
    path: root('dist_server'),
    filename: 'server.js'
  ,
  target: 'node',
  externals: 
    newrelic: true
  
;

然后我得到另一个错误

/home/ubuntu/ib-mobile/dist_server/server.js:79752

module.exports = newrelic;
                 ^

ReferenceError: newrelic is not defined
    at Object.<anonymous> (/home/ubuntu/ib-mobile/dist_server/server.js:79752:18)
    at __webpack_require__ (/home/ubuntu/ib-mobile/dist_server/server.js:26:30)
    at Object.module.exports (/home/ubuntu/ib-mobile/dist_server/server.js:79667:16)
    at __webpack_require__ (/home/ubuntu/ib-mobile/dist_server/server.js:26:30)
    at /home/ubuntu/ib-mobile/dist_server/server.js:91:18
    at Object.<anonymous> (/home/ubuntu/ib-mobile/dist_server/server.js:94:10)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)

Angular 版本 (ng -v)

Angular CLI: 1.6.3
Node: 6.11.0
OS: win32 x64
Angular: 4.4.6
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router
... tsc-wrapped

@angular/cli: 1.6.3
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.3
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.3.4
webpack: 3.10.0

【问题讨论】:

您好,我也面临同样的问题。你有没有运气并自己解决了这个问题?谢谢。 @toph 你必须在服务器包完成后注入自己使用 WebpackBannerPlugin 来做到这一点,const newrelic = require('newrelic'); @UbaidAzad 你能发布整个配置吗?作为答案?我没听懂你想说什么 建议您在注释格式中添加行,这没有任何意义 【参考方案1】:

对于所描述的问题有更优雅的解决方案。您可以设置 webpack 外部字段,如函数:

(context, request, callback) => 
    var regex = new RegExp(`^newrelic$`);

    if (regex.test(request)) 
        return callback(null, `commonjs $request`);
    
    callback();
 

这将告诉 webpack 将 const newrelic = require('newrelic'); 保留在捆绑文件中。您只需将带有 newrelic 的 node_modules 放在正在运行的服务器附近。 第二种解决方案是将output的libraryType属性设置为commonjs,然后下面的externals语法将起作用:

externals : 
    newrelic : 
        commonjs: 'newrelic'
    

【讨论】:

【参考方案2】:

找到了解决此问题的 hacky 方法!

TLDR

基本上所有这些都是配置 webpack 以在 server.js 文件的顶部添加导入,然后 BAM 就可以工作了。

问题

所以你所做的一切都是正确的,但是通过告诉 webpack 你希望 newrelic 模块是外部的,你告诉它 newrelic 实例在运行应用程序时将在内存中可用。 我们显然没有这样做,这就是为什么我们会收到您上面提到的错误。 我认为此功能的用例是针对浏览器的,您在其中包含带有 &lt;script src="http://example.com/script.js" /&gt; 的脚本,因此您不希望 webpack 自己关心尝试解决来自 node_modules 的依赖关系。

解决方案

我们将不使用“externals”属性,而是简单地将我们的标准 nodejs import var newrelic = require('newrelic'); 添加到运行 expressjs 节点应用程序的文件中(就像人们期望的新遗物一样)。

为此,我们需要以下内容:

横幅Webpack插件 了解我们的 nodejs express 应用程序正在运行哪个输出块/文件。

要安装 BannerWebpackPlugin,只需执行以下操作:npm install --save-dev banner-webpack-plugin

至于 chunk/file 您可以查看错误日志(您可以从这个错误 sn-p 看到它的 server.js 块/文件):

ReferenceError: newrelic is not defined at Object.<anonymous> (/home/ubuntu/ib-mobile/dist_server/server.js:79752:18)

或者您可以查看 webpack 文件的“入口”属性并找到由 webpack 生成的块(在我的情况下,这也是一个输出到 server.js 的“服务器”。

现在我们有了这些信息,我们只需要通过 webpack config plugins 部分将横幅配置添加到我们的块中。

这就是我的样子:

plugins: [
...,
    new BannerPlugin(
        chunks: 
            server:
                beforeContent: 'var newrelic = require("newrelic");'
            
       
    ),
...]

此时您应该能够运行您的 webpack 构建并让您的新遗物工作!

如果您之前在应用程序代码中包含 require,现在可以将其删除,并且 webpack 导入应该足以让 newrelic 代理运行。

【讨论】:

有没有办法在代码库本身中使用 newrelic 这个解决方案?例如。 -newrelic.noticeError('things went wrong'); 即使在 Typings.d.ts 文件中将其声明为全局变量后,我仍然收到“无法正确命名 'newrelic'”的错误。 更新 - 修复了一些路径问题,意识到这个解决方案可能不适用于针对 web 的 webpack 项目,因为 "require" 不可用。 我不得不稍微修改一下上面的内容(好像 BannerPlugin api 可能已经改变了)?对于我的 Angular Universal 应用程序,我使用了 new webpack.BannerPlugin( banner: 'const nr = process.env.NR_LICENSE ? require(\'newrelic\') : false;', raw: true ),

以上是关于在角度通用应用程序(nodejs)上集成newrelic的主要内容,如果未能解决你的问题,请参考以下文章

在 NativeScript App 上集成 Android 服务

如何在 Xamarin.Android 应用上集成新的 Google 登录?

使用 nginx 在 laravel forge 上集成 Laravel 5.2 wordpress

在 Fabric.js 画布上集成 Flash 动画(或派生格式)

无法在 iOS 上集成 localytics-react-native

如何在使用 Typescript 的 Ionic App 上集成 API.AI?