node.jsnuxt.jsstompnuxt3.jssockjs

How to add normal modules to Nuxt 3


I am writing a web application in Nuxt 3 and want to integrate a SockJs over Stomp websocket. Now I have written the component...

<template>
  <div>
    <h1>Test</h1>
  </div>
</template>

<script lang="ts" setup>
import {useRouter, ref} from "#imports";
import SockJS from "sockjs-client";
import {Stomp} from "@stomp/stompjs";

let consoleText = ref<string>("");

interface ConsoleMessage {
  messageContent: string,
  user: string,
}

const props = defineProps<{
  originURL:string,
  publicURL:string,
  privateURL:string
}>();

let stompClient: any = null;
function connect() {
  const socket = new SockJS(props.originURL);
  stompClient = Stomp.over(socket);
  stompClient.connect({}, function () {
    stompClient.subscribe(props.publicURL, function (message: { body: string; }) {
      showMessage(JSON.parse(message.body));
    });
    stompClient.subscribe(props.privateURL, function (message: { body: string; }) {
      showMessage(JSON.parse(message.body));
    });
  });
}

function showMessage(message: ConsoleMessage) {
  consoleText.value = "\n" + message.messageContent + "\n";
}

connect();
</script>

I have imported @stomp/stompjs and sockjs-client via yarn add. What do I have to change in the nuxt.config.ts to make it so that the application loads the modules.

Edit:

Following the advice given by nur_iyad I attempted to write a plugin

import {defineNuxtPlugin} from "nuxt/app";
import SockJS from "sockjs-client";
import {CompatClient, Stomp} from "@stomp/stompjs";
import {Message} from "~/composables/display";

export default defineNuxtPlugin((nuxtApp) => {
    nuxtApp.provide('sock', () => new NuxtSockJs())
})

declare module '#app' {
    interface NuxtApp {
        $sock (): NuxtSockJs
    }
}

export class NuxtSockJs {
    stompInstance: CompatClient | null;

    constructor() {
        this.stompInstance = null;
    }

    connect(originURL:string,
            subscribeURLs:Array<string>,
            displayMessage: (message: Message) => any): void {
        const socket = new SockJS(originURL);
        let stompClient: CompatClient = Stomp.over(socket);
        stompClient.connect({}, function () {
            for(const subscribeURL of subscribeURLs) {
                stompClient.subscribe(subscribeURL, function (message: { body: string; }) {
                    displayMessage(JSON.parse(message.body));
                });
            }
        });
        this.stompInstance = stompClient;
    }
    sendMessage(sendURL: string, message: Message):void {
        (this.stompInstance)!.send(sendURL, {}, JSON.stringify(message));
    }
}

This does not work and just throws the following error:

Uncaught ReferenceError: global is not defined
    at node_modules/sockjs-client/lib/utils/browser-crypto.js

Solution

  • After a long hunt for an answer I have found the solution.

    It is literally just importing the module into any TS activated component, in my case I packaged the SockJS into a composable

    import {CompatClient, Stomp} from "@stomp/stompjs";
    import {Message} from "~/composables/display";
    import SockJS from "sockjs-client";
    
    export class NuxtSockJs {
        stompInstance: CompatClient | null;
        isConnected: boolean;
    
        constructor() {
            this.stompInstance = null;
            this.isConnected = false;
        }
    
        connect(originURL:string,
                subscribeURLs:Array<string>,
                displayMessage: (message: Message) => any): void {
            const socket = new SockJS(originURL);
            this.stompInstance = Stomp.over(socket);
            this.stompInstance.debug = () => {};
            this.stompInstance.connect({}, () => {
                for(const subscribeURL of subscribeURLs) {
                    this.stompInstance!.subscribe(subscribeURL, (message) => {
                        displayMessage(JSON.parse(message.body));
                    });
                }
            });
            this.isConnected = true;
        }
        sendMessage(sendURL: string, message: Message):void {
            (this.stompInstance)!.send(sendURL, {}, JSON.stringify(message));
        }
    }
    

    For anybody interested as to why SockJS would still not work, the following has to be added to the nuxt.config.ts

    export default defineNuxtConfig({
        app: {
            head: {
                script: [
                    {children: 'var global = window;'}
                ]
            }
        }
    });
    

    Hope this helps anybody suffering from the issues I was :))