Интеграция newrelic в универсальное приложение angular (nodejs)

Я интегрирую newrelic в приложение nodejs, созданное с помощью angular universal. Я использую веб-пакет для связывания

первая строка в main.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

и если я добавлю 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

person Ubaid Azad    schedule 28.12.2017    source источник
comment
Здравствуйте, я сталкиваюсь с теми же проблемами. Удалось ли вам решить эту проблему самостоятельно? Спасибо.   -  person toph    schedule 02.09.2018
comment
@toph вы должны ввести себя после завершения сборки сервера, используйте для этого WebpackBannerPlugin, const newrelic = require('newrelic');   -  person Ubaid Azad    schedule 03.09.2018
comment
@UbaidAzad, можете ли вы опубликовать всю конфигурацию. как ответ? Я не понимаю, что ты пытаешься сказать   -  person Pardeep Jain    schedule 30.10.2018
comment
предложение, которое вы рекомендуете, добавить строку в закомментированном формате, что не имеет никакого смысла   -  person Pardeep Jain    schedule 30.10.2018


Ответы (2)


Нашел хакерский способ обойти эту проблему!

TLDR

По сути, все, что нужно сделать, это настроить веб-пакет для добавления импорта в начало файла server.js, и все работает.

Проблема

Итак, все, что вы сделали, правильно, однако, сообщая веб-пакету, что вы хотите, чтобы модуль newrelic был внешним, вы сообщаете ему, что экземпляр newrelic будет доступен в памяти при запуске приложения. Мы, очевидно, этого не сделали, и поэтому мы получаем ошибку, о которой вы упоминали выше. Я думаю, что вариант использования этой функции предназначен для браузера, где вы включаете сценарии с <script src="{http://example.com/script.js}" />, и поэтому вы не хотите, чтобы веб-пакет пытался разрешить зависимость от node_modules.

Решение

Вместо использования свойства «внешние» мы просто добавим наш стандартный импорт nodejs var newrelic = require('newrelic'); в файл, который запускает приложение узла expressjs (точно так же, как ожидают новые реликвии).

Для того, чтобы это сделать, нам понадобится следующее:

  • БаннерWebpackПлагин
  • Знание того, какой выходной фрагмент / файл работает в нашем экспресс-приложении nodejs.

Чтобы установить BannerWebpackPlugin, просто выполните следующие действия: npm install --save-dev banner-webpack-plugin

Что касается чанка/файла, вы можете просмотреть журнал ошибок (из этого фрагмента ошибки видно, что это фрагмент/файл server.js):

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

Или вы можете просмотреть свойство "entry" файлов веб-пакета и найти фрагмент, который генерируется веб-пакетом (В моем случае это также "сервер", который выводит на server.js.)

Теперь, когда у нас есть эта информация, нам просто нужно добавить конфигурацию баннера в наш фрагмент через раздел плагинов конфигурации веб-пакета.

Вот так выглядел мой:

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

На этом этапе вы должны быть в состоянии запустить свою сборку веб-пакета и заставить работать ваши новые реликвии!

Если вы ранее включали требование в код своего приложения, теперь вы можете удалить его, и импорта веб-пакета должно быть достаточно для запуска агента newrelic.

person sansomguy    schedule 19.12.2018
comment
Есть ли способ использовать newrelic в самой кодовой базе с этим решением? Например. -newrelic.noticeError('things went wrong'); Я получаю сообщения об ошибках Cannot Fine Name 'newrelic' даже после объявления его глобальной переменной в файле typings.d.ts. - person Skeeterdrums; 19.12.2018
comment
Обновление - исправлены некоторые проблемы с путями, реализовано, что это решение, вероятно, не будет работать для проекта веб-пакета, предназначенного для Интернета, поскольку требование недоступно. - person Skeeterdrums; 19.12.2018
comment
Мне пришлось немного изменить вышеизложенное (похоже, API-интерфейс BannerPlugin мог измениться)? Для моего приложения Angular Universal я использовал new webpack.BannerPlugin({ banner: 'const nr = process.env.NR_LICENSE ? require(\'newrelic\') : false;', raw: true }), - person bmarti44; 05.04.2019

Существует более элегантное решение описанной проблемы. Вы можете установить внешнее поле веб-пакета, например функцию:

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

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

Это скажет веб-пакету оставить const newrelic = require('newrelic'); как есть в связанном файле. Все, что вам нужно, это разместить node_modules с newrelic рядом с вашим работающим сервером. Второе решение — установить для свойства libraryType output значение commonjs, а затем следующее externals синтаксис будет работать:

externals : {
    newrelic : {
        commonjs: 'newrelic'
    }
}
person Timon Thelure    schedule 30.01.2019