biggora / device-uuid

Fast browser device uuid generation library. Written in pure JavaScript, no dependencies.
MIT License
185 stars 96 forks source link

ReferenceError: navigator is not defined #10

Open adaboina21 opened 4 years ago

RusinovAnton commented 4 years ago

could you please give some context on it?

adaboina21 commented 4 years ago

when i am running in node environment getting this error ReferenceError: navigator is not defined.

RusinovAnton commented 4 years ago

This library is designed for in-browser usage in the first place. What are you trying to achieve using it in node env?

adaboina21 commented 4 years ago

yes, i am using this in angular js but still same issue

adaboina21 commented 4 years ago

https://npm.runkit.com/device-uuid

RusinovAnton commented 4 years ago

The reason it throws an error is that there is no navigator object in global scope in node env, which this library essentially relies on. Once again, this library is for usage in browser, not in the node env.

How does it fail while using angular?

ezzabuzaid commented 4 years ago

@RusinovAnton because he is using angular SSR I guess,

you can use the library using a script tag https://raw.githubusercontent.com/biggora/device-uuid/master/lib/device-uuid.min.js

the problem happens because DeviceUUID function is IIFE so it will be invoked directly when you importe it

Screen Shot 2020-02-19 at 9 36 38 PM

the final code after adding the script tag should be like this (window as any).DeviceUUID() with that, another issue will appear tells that window not defined

const $window = (() => { try { return window; } catch (error) { return {} as Window; } })();

you can mock the window to avoid it

mkhalesi commented 3 years ago

@RusinovAnton i have this problem too . when run project in ssr with command : npm run dev:ssr get same error:

return new DeviceUUID(navigator.userAgent);
                        ^
ReferenceError: navigator is not defined

im using a mock browser , in server.ts file :

const MockBrowser = require('mock-browser').mocks.MockBrowser;
const mock = new MockBrowser();
global['navigator'] = mock.getNavigator();
global['window'] = mock.getWindow();
global['document'] = mock.getDocument();

@ezzabuzaid What do you mean by using tag script? I don't know where to put this tag

thanks

ezzabuzaid commented 3 years ago

@mkhalesi

It's been a while and I don't exactly remember what I've done to make it work, my bad didn't provide much information back then and I am no longer working on that project.

I would advise to lazy load the script and run it only in browser env

constructor( @Inject(PLATFORM_ID) platformId) {
  const isBrowser = isPlatformBrowser(platformId);
  // Lazy load "device-uuid"
}
mkhalesi commented 3 years ago

@ezzabuzaid thanks for response

but i checked isPlatformBrowser anywhere project use 'deviceuuid' const deviceId = isPlatformBrowser(this.platfromId) ? new DeviceUUID().get() : ' ' ;

@biggora

ezzabuzaid commented 3 years ago

@mkhalesi This won't work

the issue is when you import the library, the navigator will be immediately be used regardless of where you use DeviceUUID. that's why you have to lazy load it.

mkhalesi commented 3 years ago

@ezzabuzaid Thank you very much for Help i worked based on your tips like this:

 if (isPlatformBrowser(this.platformId)) {
        import('device-uuid').then( module => {
             const deviceId = new module.DeviceUUID().get() ; 
         });  
  }

and worked properly thanks :)

sankar2389 commented 2 years ago

@ezzabuzaid can you please guide me to run the same in react js ssr?

ezzabuzaid commented 2 years ago

@sankar2389 Same steps, check if you're in a browser environment, if so then lazy load the library. I don't have much knowledge in react - you can run the import function in componentDidMount hook as it doesn't run in the server

sankar2389 commented 2 years ago

Solved by calling the library in useEffect.

sakthii05 commented 1 year ago

For next.js, (react) use this code

useEffect(()=>{ import("device-uuid") .then(module=>{ const uuid = new module.DeviceUUID().parse(); const id = new module.DeviceUUID().get(); console.log(uuid, id); })

},[])

joujou144 commented 1 year ago

resolved this with async await in nextjs/react app

const generateDeviceId = async () => {

try {
  const DeviceUUID = await import('device-uuid');
 // slicing it to 10 characters. Otherwise you can maintain the original length by omitting the toUppercase, slice and replace methods
  const deviceIdInstance = new DeviceUUID.DeviceUUID()
    .get()
    .toUpperCase()
    .slice(0, 11)
    .replace(/-/g, '');
  return deviceIdInstance;
} catch (error) {
  alert(error);
}

};