"Angular Universal third-party library is throwing an error because the window object is

I've been working with the ng2-mqtt library and have integrated it into my component as shown below:

 import 'ng2-mqtt/mqttws31.js';
declare var Paho: any;

However, I encountered the following error:

ReferenceError: window is not defined
    at Object.<anonymous> (/Users/Picchu/Documents/em3/node_modules/ng2-mqtt/mqttws31.js:2143:4)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.require (module.js:483:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/Users/Picchu/Documents/em3/dist/server.js:18707:18)

Any suggestions on how to resolve this issue?

Answer №1

UPDATE

In addition to Leon Li's response, a solution is offered here for preventing the loading of components that rely on Browser APIs such as location or window from being rendered on the server side.

This particular answer provides detailed instructions on how to implement this technique.

import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';

constructor( @Inject(PLATFORM_ID) platformId: Object) {
  this.isBrowser = isPlatformBrowser(platformId);
}

To accomplish this, simply inject PLATFORM_ID into your service and utilize isPlatformBrowser or isPlatformServer to retrieve a Boolean value. This way, you can control the visibility of components that require Browser APIs but cannot be rendered on the server side.

Answer №2

To prevent server errors, one effective approach is to conditionally render components that rely on the window object. This can be achieved by:

<ng-container *ngIf="isBrowser">
   <!-- mqttws31-component -->
   <mqttws31-component></mqttws31-component> 
</ng-container>

The variable isBrowser can be imported from Angular 2 as follows:

import { isBrowser } from 'angular2-universal';

In Angular 4 and above, you can declare this in your browser module like this:

// app.browser
@NgModule({
  providers: [
    { provide: 'isBrowser', useValue: true }
  ]
})

Then, inject it in the constructor of your component:

export class SomeComponent implements OnInit {
  constructor(@Inject('isBrowser') private isBrowser: boolean)
  ngOnInit() { 
    // Example usage, can be anywhere within this Component
    if (this.isBrowser) { 
      alert('We're in the browser!');
    }
}

Answer №3

To incorporate Angular 6 in server.ts, follow these steps:

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync('dist/browser/index.html').toString();
const win = domino.createWindow(template);

global['window'] = win;
global['document'] = win.document;
global['DOMTokenList'] = win.DOMTokenList;
global['Node'] = win.Node;
global['Text'] = win.Text;
global['HTMLElement'] = win.HTMLElement;
global['navigator'] = win.navigator;

Answer №4

window is not recommended for use in universal applications on the server side, as Node.js does not support window. Using a dummy variable like global.window could interfere with Angular's detection of global variables.

If a package relies on window, it is advisable to open an issue in the repository or fork the package and modify it to avoid using window.

Even if the issue with using window is resolved, packages that depend on it are likely designed for client-side specifics and may not function correctly on the server side.

The description of the package states:

Depends on the library from:

The description of the library mentions:

The Paho JavaScript Client is an MQTT browser-based client library written in Javascript that uses WebSockets to connect to an MQTT Broker.

In cases where a third-party Angular module is not intended for server-side usage, it should be stubbed or mocked. A dummy module containing fake directives and services can be imported into app.server.ts instead of the real module.

Answer №5

Employment opportunity available for ng9+

// app.module.ts
@NgModule({
  providers: [
    { provide: 'isBrowser', useValue: true }
  ]
})

Update the absolute path by removing the first /:

/assets/images/... to assets/images/...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to smoothly animate dragging a component in React

I am having trouble dragging a component with CSS transform animation applied to it. The drag functionality doesn't seem to work properly as the component only moves based on the animation and cannot be dragged. Is there any solution to make the drag ...

What is the process for creating a duplicate element within the target div after the original element has been dropped?

Imagine a scenario where the "HI" div is dragged into the "DRAG HERE" div, causing the "HI" div to be removed from its original location. What if, instead of disappearing, dragging the "HI" div to another location generated a new "HI" div? /** * Fu ...

Assign a dynamic class to an element within an ngFor iteration

I am working with a template that includes an app-subscriber component being iterated over using *ngFor: <app-subscriber *ngFor="let stream of streams" [stream]="stream" [session]="session" (speakEvents)='onSpeakEvent($event)'> ...

Unable to extract property from object in context due to its undefined status

Having trouble with the useContext hook in my React app for managing the cart state. Keep getting an error stating that the function I'm trying to destructure is undefined. I'm new to using the context API and have tried various solutions like e ...

Exploring the application of URL parameters in HTML code

How can I use URL parameters retrieved with Javascript in my HTML? <script> var url_string = window.location.href; //window.location.href var url = new URL(url_string); var c = url.searchParams.get("name"); console.log(c); </script> I am tryi ...

Learn the method of showcasing a JavaScript variable value within an HTML href tag

Currently, I am in the process of rewriting my URL and category name to be passed into the URL. For this purpose, I am creating a URL friendly string using the following JavaScript function: function getUrlFriendlyString(str) { // convert spaces to &ap ...

Deactivate background hover effects for bar charts in Recharts

Is there a way to disable the gray background that appears when hovering over bar charts in Recharts? I'm using version 1.4.1 and my code looks like this: import React from "react" // Recharts import { Bar, BarChart, CartesianGrid, ResponsiveContain ...

Ensuring the protection of API requests in a Phonegap/Cordova application

As I work on developing a Phonegap application that requests data from my server via API, I want to ensure that only authorized users are able to access this data. To achieve this, I have implemented HTTP basic authentication. This method involves includi ...

What is the best way to organize the size of multiple files into a single HTML card?

Is there a way to automatically arrange multiple items (photos/videos) within a single HTML card, similar to how it is done on Facebook or Instagram? I am looking for a library or JavaScript code that can help me achieve this without extending the size of ...

What is the best way to access an angular route directly through the browser?

Hello, I'm encountering some difficulties with Express rendering certain routes. When I go to the website example.com, everything functions correctly. However, when I try to access a route like example.com/login, I receive an error stating Cannot get ...

Comparing plain objects and class instances for modeling data objects

What is the recommended approach for creating model objects in Angular using TypeScript? Is it advisable to use type annotation with object notation (where objects are plain instances of Object)? For example, let m: MyModel = { name: 'foo' } ...

Ways to effectively implement a function type specified in an interface

Consider the following interface: interface MyProps { onEvent: (name: string, data: any) => void; } Is there a way to utilize the function type in order to avoid unused parameter errors during compilation? eventHandler = (name: string, data: any) = ...

Filtering a Material Table based on numeric ranges in Angular 7

In my Angular 7 project, I am utilizing Material Table. The table in question displays a variety of objects. One of the properties each object has is 'number of promotions,' and I am looking to implement filters based on number ranges (e.g., un ...

Troubleshooting the malfunction of the CSS display property

I've created a div with a number displayed initially. When I hover over the div, the number disappears and a paragraph is revealed. Upon hovering out, the paragraph hides and the number reappears. My attempts to achieve this using CSS (display: none ...

Guide on increasing a basic counter and a counter with an object component using redux

(I need help fixing my code) I am trying to write a counter increment code to better understand Redux in the following situations: Increasing a simple counter Increasing a counter with an object Currently facing an issue where counter1 is undefined on the ...

Is it advisable to include auto-generated files in an npm package upon publication?

I have a TypeScript NPM package where my build process compiles all *.ts files into myLib.d.ts, myLib.js, and myLib.js.map. In order for my NPM package to function properly, it requires the src/*.ts files as well as the auto-generated myLib.* files. Howe ...

Vue.js - The dissonance between data model and displayed output

Below is a simplified example of my issue: <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script> <script src="https://unpkg.com/vue/dist/vue.js"></script> ...

Creating a Countdown in Javascript Using a Variable

I want the date to change from the first date to the second date. At the start, it should display 'Starts:' in bold followed by the remaining time. Once it switches to the second date, it should show 'Ends:' in bold and then the remaini ...

What is the best way to iterate over a nested array of objects and render them in my HTML using Angular/Ionic?

One of the challenges I'm facing involves working with an interface structured like this: export interface SeriesCard { type: string, imageUrl: string, title: string, category: string, seriesItems: SeriesItems[]; } Currently, my Service con ...

Ensure that each Javascript function call in MVC 4 waits for the previous one to complete before executing

I am trying to run two JavaScript functions, but the second function needs to wait for the first function to finish. View: <button id="DefinirEstab" class="btn btn-success btn-lg" data-toggle="modal" data-target="#myModal" onclick="saveContrato(); Cou ...