Подтвердить что ты не робот

Использование браузера JS-библиотеки с Angular 2

Я хочу использовать libquassel (https://github.com/magne4000/node-libquassel) в моем проекте Angular 2. Библиотека просматривается, поэтому теоретически она должна работать, но я не уверен, как ее импортировать в свой проект.

Я попытался добавить в свой typings.d.ts

declare module 'libquassel';

а затем импортируйте библиотеку с помощью

import * as Quassel from 'libquassel';

но я получаю

EXCEPTION: net.Socket is not a function

когда я пытаюсь запустить свой код, который, я считаю, является другой библиотекой, которая просматривает встроенные в файл client/libquassel.js.

Как я могу использовать эту библиотеку?

Изменить: я отвечу на все вопросы здесь:

  • Моя настройка - это простой проект angular -cli. Никаких причудливых вещей, просто ng new proj1, а затем npm install libquassel --save.
  • У моего index.html нет ничего, что ng new не размещалось там.
  • Я попытался импортировать библиотеку с import * as Quassel from 'libquassel' и var Quassel = require('quassel') (и их перестановками) без ведома (ошибки варьируются от unknown function 'require' до can't find module lib|quassel).
  • Шаги по воспроизведению моего проекта:

    ng new test
    cd test
    npm install libquassel --save
    ng g s quassel
    

Затем добавьте QuasselService в массив providers в app.module.ts. Это было бы хорошей демонстрацией моей проблемы, а именно, как импортировать libquassel в мой QuasselService.

4b9b3361

Ответ 1

Обновить (исправить, на этот раз для реального)

Есть очень веская причина, почему это не работает в вашем коде: потому что я солгал вам. Итак, вот мой настоящий чит на случай, если вы еще не "разобрались" в нем.

Мне все еще нужно require libquassel 2 раза, но первый раз выполняется не вызовом require, который бесполезен, но добавив его в angular-cli.json в раздел scripts:

  "scripts": [
    "../node_modules/libquassel/client/libquassel.js"
  ],

Это важно, потому что "client/libquassel.js" объявляет свой собственный require, но явно не экспортирует его, если вы делаете

require('libquassel/client/libquassel.js');

libquassel custom require остается застрявшим внутри анонимного пространства имен, и вы не можете получить к нему доступ. Добавив его в раздел scripts, с другой стороны, пусть libquassel.js загрязняет глобальное пространство имен (т.е. window) своим require и тем самым заставляет его работать.

Итак, действительные шаги для его работы:

  • Добавьте клиент /libquassel.js в скрипты section из angular-cli.json
  • Используйте дополнительный require для фактического загрузки модуля Quassel
let Quassel = window['require']('quassel'); // note that usingg require('quassel') leads to compilation error
let quasselObj = new Quassel(...);

Вот моя попытка. Похоже, вам нужно require "quassel" 2 раза: первый раз загрузить JS из "../node_modules/libquassel/client/libquassel.js" и второй раз, чтобы разрешить переопределенное require от этого JS фактически разрешает "quassel". Вот трюк, который, похоже, работает для меня в 'main.ts':

require('../node_modules/libquassel/client/libquassel.js');
let Quassel = window['require']('quassel'); // note that using require('quassel') leads to compilation error
let quasselObj = new Quassel(...);

Мне понадобился еще один трюк, чтобы не скомпилировать ошибку компиляции: в частности, мне пришлось использовать window['require'] вместо всего require для второго вызова, так как это вызов внутреннего require, как определено внутри client/libquassel.js и Node/Angular -cli не может справиться с этим.

Обратите внимание, что после этой настройки мое приложение по-прежнему не удалось выполнить ошибку времени выполнения в некоторых AJAX, потому что для просмотра libquassel.js, похоже, требуется прокси-сервер, настроенный на стороне сервера, по адресу URL, например /api/vm/net/connect, и это, вероятно, то, что на стороне сервера net-browsify должен делать, но я не пытался его настроить.

Ответ на комментарии

Похоже, вы используете старую версию Angular -CLI, и если вы обновляете все, то все должно работать нормально.

Вот что ng --version говорит мне на моей оригинальной машине

angular-cli: 1.0.0-beta.28.3
node: 6.10.0
os: win32 x64
@angular/common: 2.4.10
@angular/compiler: 2.4.10
@angular/core: 2.4.10
@angular/forms: 2.4.10
@angular/http: 2.4.10
@angular/platform-browser: 2.4.10
@angular/platform-browser-dynamic: 2.4.10
@angular/router: 3.4.10
@angular/compiler-cli: 2.4.10

Когда я попытался скопировать исходный проект на другой компьютер, у меня также появилась ошибка компиляции require, но когда я обновил Angular -CLI до

@angular/cli: 1.0.0
node: 6.10.0
os: darwin x64
@angular/common: 2.4.10
@angular/compiler: 2.4.10
@angular/core: 2.4.10
@angular/forms: 2.4.10
@angular/http: 2.4.10
@angular/platform-browser: 2.4.10
@angular/platform-browser-dynamic: 2.4.10
@angular/router: 3.4.10
@angular/cli: 1.0.0
@angular/compiler-cli: 2.4.10

он скомпилирован и работает одинаково. Я только что выполнил инструкцию

Пакет "angular -cli" устарел и переименован в "@ angular/cli".

Чтобы избежать проблем, выполните следующие действия:
" npm uninstall --save-dev Angular -cli"
" npm install --save-dev @angular/cli @latest"

а затем обновить angular-cli.json в соответствии с инструкциями ng serve

Ответ 2

Работает как шарм:

declare var require;
const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );

Глядя на папку libquassel в node_module, понял, что в корневом каталоге нет index.js.

Если нет index.js, вы не можете сделать это:

 require( 'libquassel' );

Просто потому, что node не знает, что вам нужно, поэтому вам нужно указать точный путь, который в этом случае не так уж плох.

Кроме того, обратите внимание, что лучше перемещать declare var require; в файл с образцами, расположенный под папкой src, потому что вам может потребоваться его снова объявить, поэтому лучше быть там.

ИЗМЕНИТЬ: Вот что я нашел после попытки создать экземпляр Quassel, как рев:

const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );
var quassel = new Quassel( "quassel.domain.tld",
    4242,
    { backloglimit : 10 },
    function ( next ) {
        next( "user", "password" );
    } );
console.log( 'quassel', quassel );

И вот мой консольный журнал:

введите описание изображения здесь Но, сказав это, я понял, что внутри libquassel.js есть проблема, как ниже:

в строке 10, они делают это:

   var net = require('net');

И, глядя на их package.json, нет такой вещи, как net и есть net-browserify-alt;

Итак, если они меняют этот импорт на:

 var net = require('net-browserify-alt'),

Все будет работать.

Сказав это, очевидно, что вы не хотите редактировать свой node_module, но я действительно удивлен тем, как это работает даже за пределами angular и webpack, потому что ясно, что они упомянули неправильный узел_модуль, который, если вы google, есть только один пакет с именем net, который у меня был, и он пуст и фиктивный!!!!

** ********** ОБНОВЛЕНИЕ: ********** **

Что именно нужно сделать:

1- запустить ng eject

который будет генерировать webpack.conf.js внутри вашего корневого каталога.

2- внутри найдите свойство resolve и добавьте:

 "alias":{
     'net':'net-browserify-alt'
  },

поэтому ваше решение, вероятно, будет выглядеть следующим образом:

"resolve": {
    "extensions": [
      ".ts",
      ".js"
    ],
      "alias":{
         'net':'net-browserify-alt'
      },
    "modules": [
      "./node_modules"
    ]
  },

3- импортировать и использовать его:

declare var require;
const Quassel = require( 'libquassel/lib/libquassel.js' );
console.log( 'Quassel', Quassel );
var quassel = new Quassel( "quassel.domain.tld",
    4242,
    { backloglimit : 10 },
    function ( next ) {
        next( "user", "password" );
    } );
console.log( 'quassel', quassel );

ПРИМЕЧАНИЕ:

Взглянув на конфигурацию webpack, похоже, что webpack любит переопределить пару модулей:

"node": {
    "fs": "empty",
    "global": true,
    "crypto": "empty",
    "tls": "empty",
    "net": "empty",
    "process": true,
    "module": false,
    "clearImmediate": false,
    "setImmediate": false
  }

Я точно не знаю, почему, но этот список находится в конфигурации webpack и, кажется, делает net undefiend (empty) и поэтому нам нужно создать псевдоним.

Ответ 3

Angular -cli использует webpack

вам нужно будет добавить JS файл в приложения [0].scripts в ваш файл angular -cli.json, который затем упаковывается, как если бы он был загружен тегом.

apps:[
{
  ...
  "scripts": [
    "../node_modules/libquassel/client/libquassel.js"
  ],

Если вы это сделаете, вы можете получить его, добавив declare var Quassel :any; в свой src/typings.d.ts или компонент.

let quassel = new Quassel("localhost", 4242, {}, function(next) {
  next("user", "password");
});
quassel.connect();

Ответ 4

Ключевой проблемой является браузерная библиотека libquassel содержит внутри нее глобальную функцию require. Это противоречит стандартной функции require.

Существует много способов решения этой проблемы, но одно решение - скопировать /libquassel/client/libquassel.js (и мини-версию) в каталог /src/app/.

Затем запустите поиск и замените в этих файлах, чтобы изменить ВСЕ вхождения от require до _quasselRequire_

Вы сделаете это как для libquassel.js, так и libquassel.min.js.

Чтобы использовать это, вы сделаете что-то вроде этого в quassel.service.ts:

import { Injectable } from '@angular/core';
import * as dummyQuassel1 from './libquassel.js'

var dummyQuassel2 = dummyQuassel1; // something just to force the import

declare var _quasselRequire_ :any;

@Injectable()
export class QuasselService {

  constructor() { 

    // set up in the constructor as a demo

    let Quassel = _quasselRequire_( 'quassel' );
    console.log('Quassel', Quassel);

    var quassel = new Quassel( 
        "quassel.domain.tld",
        4242,
        { backloglimit : 10 },
        function ( next ) {
            next( "user", "password" );
        } 
    );

    console.log('quassel', quassel);

    quassel.on('network.init', function(networkId) {
        console.log("before net");
        var network = quassel.getNetworks().get(networkId);
        console.log("after net");
        // ...
    });

    console.log("before connect");
    quassel.connect();  
    console.log("after connect");
  }

  getQuassel() {
      return 'My Quassel service';
  }
}

Это само по себе приводит к ошибке:

POST http://localhost:4200/api/vm/net/connect 404 (не найдено)

и

Ошибка: нечистое, неопределенное событие "ошибка".     при новой ошибке (native)     в Quassel.n.emit(http://localhost:4200/main.bundle.js:570:4210) [angular]     в Socket. (http://localhost:4200/main.bundle.js:810:19931) [angular]     на Socket.EventEmitter.emit(http://localhost:4200/main.bundle.js:573:1079) [angular]...

Но, как я понимаю, это довольно нормально, если у меня нет Express и т.д.

Примечание: имя _quasselRequire_ может быть любым, что вам подходит.