Search code examples
angularjswebsocketwebpackkarma-runnerstomp

How to use stomp with angular 1.5/es6 and webpack


I am struggling to include stomp in my project. With both versions jmesnil/stomp-websocket or the subspequent forkJSteunou/webstomp-client.

I tried to import properly:

import Stomp from 'stompjs';//or 'webstomp-client';
import SockJS from 'sockjs-client';

and to load it like:

angular.module('app', [
uiRouter, ngTranslate, ngTranslateStaticFilesLoader, ngResource, ngFilter,
uiBootstrap, Stomp, SockJS
])

But I get the following error (with both versions):

Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:modulerr] Failed to instantiate module {"VERSIONS":{"V1_0":"1.0","V1_1":"1.1","V1_2":"1.2"}} due to:
Error: [ng:areq] Argument 'module' is not a function, got Object

(Even if webstomp.js has "function webpackUniversalModuleDefinition(root, factory) " on top, which apparently is not fullfilling its purpose)

It is possible to bypass this errors by importing it "wildly" directly on top the controllers where used, but then all karma tests are not running (error is : Error: Cannot find module "net"), even though node: { net: 'empty', tls: 'empty', dns: 'empty' } is added to webpack.config.js.

At this point anything I am trying just feels like weird black magic.

Is there a "constellation" of lib versions, angular wrappers, etc that is know to work properly with my setup (angular 1.5 / es6 / webpack 1.14 / karma) ?


Solution

  • Do not add it as a dependency to your angular module. The Stomp library is not an angular module. There might be a bridge available, but I don't think it is necessary.

    To use Stomp with Webpack 2, simple require it at the tomp of the file where you are using Stomp and then use it as if it was a global variable.

    const Stomp = require("stompjs/lib/stomp.js").Stomp;
    

    Inside your controller/service:

    Stomp.client(...);
    

    Edit

    This solution will be a bit more difficult to unit test, because you will not be able to replace the dependency easily the "angular way". To solve that issue, you might define it in your main module file as a constant and than use the DI provided by AngularJS.

    Main Module File

    const Stomp = require("stompjs/lib/stomp.js").Stomp;
    
    angular
        .module('app', [
            // dependencies
        ])
        .constant('Stomp', Stomp)
        // other controllers/services/etc.
    

    Controller/Service

    function MyController(Stomp) {
    
        Stomp.client(...);
    
    }