jackspirou / clientjs

Device information and digital fingerprinting written in pure JavaScript.
http://clientjs.org
Apache License 2.0
2.11k stars 334 forks source link

Not working on nextjs #140

Open devgrigor opened 2 years ago

devgrigor commented 2 years ago

The lib is throwing the following error when next build is ran ReferenceError: navigator is not defined at Object.getBrowser (C:\projects\web-ssd-cms-api-bakcend\web-ssd-website-frontend\node_modules\clientjs\src\vendor\deployJava.js:1150:21) at Object.writePluginTag (C:\projects\web-ssd-cms-api-bakcend\web-ssd-website-frontend\node_modules\clientjs\src\vendor\deployJava.js:1365:24) at Object. (C:\projects\web-ssd-cms-api-bakcend\web-ssd-website-frontend\node_modules\clientjs\src\vendor\deployJava.js:1423:12) at Module._compile (internal/modules/cjs/loader.js:1063:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10) at Module.load (internal/modules/cjs/loader.js:928:32) at Function.Module._load (internal/modules/cjs/loader.js:769:14) at Module.require (internal/modules/cjs/loader.js:952:19) at require (internal/modules/cjs/helpers.js:88:18) at Object. (C:\projects\web-ssd-cms-api-bakcend\web-ssd-website-frontend\node_modules\clientjs\src\modules\java-detection.js:3:18) { type: 'ReferenceError' }

Even if one puts try catch on the block it still does this, because the issue is in import method. It tries to do something with navigator import time, but I believe it should do anything only when new ClientJS is called

praty22 commented 2 years ago

Faced the same issue, any help would be appreciated.

devgrigor commented 2 years ago

Here is the thing, as I understand it, the lib is doing something on require and not on initialization by constructor. Here is a working workaround

  try {
    // This is not working anyway else, it performs an action on require which is
    // throwing error build time
    const client = require('clientjs')
    const browser = new client.ClientJS()
    // The rest of the usage
  }
  catch () {
    // Do nothing
  }
praty22 commented 2 years ago

Didn't work for me, Falling back to fingerprintJs. Thanks for the quick response.

hacknlove commented 2 years ago

You can create a component that you can import and use dynamically

The component:

import { ClientJS  } from 'clientjs'
import { useEffect } from 'react';

export default function ClientJsComponent({ setFingerPrint }) {
  useEffect(() => {
    const client = new ClientJS();
    const fingerprint = client.getFingerprint();
    setFingerPrint(fingerprint);
  }, [])

  return null
}

How to use it

import { useState } from 'react';
import dynamic from 'next/dynamic'

const ClientJs = dynamic(() => import('./components/ClientJs'), { ssr: false });

export default function Page () {
  const [fingerPrint, setFingerPrint] = useState()

  return (
    <>
        {fingerPrint}
        <ClientJs setFingerPrint={setFingerPrint} />
    </>
 )
}

Maybe it's not elegant, but it might do it.

Another option is to copy the ClientJs min script to public, load it with <Script src="/ClientJS.min.js" onLoad={doSomething} /> and run a functión when it's ready

BendingBender commented 2 years ago

You can use the dist/client.base.min.js as described in the docs. This should work without executing any code upon a require call/import. It also has the benefit of being much smaller without losing any functionality on modern browsers.

sangnt-sysvpn commented 1 year ago

You can use the dist/client.base.min.js as described in the docs. This should work without executing any code upon a require call/import. It also has the benefit of being much smaller without losing any functionality on modern browsers.

thanks!! I have tried and succeeded.

git-sujon commented 11 months ago

Here is the thing, as I understand it, the lib is doing something on require and not on initialization by constructor. Here is a working workaround

  try {
    // This is not working anyway else, it performs an action on require which is
    // throwing error build time
    const client = require('clientjs')
    const browser = new client.ClientJS()
    // The rest of the usage
  }
  catch () {
    // Do nothing
  }

thanks this code works for me. It solves my "ReferenceError: navigator is not defined" error when I try to build the next.js application. this is how I implemented it... maybe it can help someone...

` const onFinish = async (values: ILogin) => { try { const ClientJs = require("clientjs"); const client = new ClientJs.ClientJS();

  const fingerprint = client?.getBrowserData();

  const deviceId = client?.getFingerprint();

  const data = {
    ...values,
    devicesInfo: {
      devicesId: deviceId?.toString(),
      devicesModel: fingerprint?.device?.model,
      devicesType: fingerprint?.device?.type,
      devicesVendor: fingerprint?.device?.vendor,
      browserName: fingerprint?.browser?.name,
      browserVersion: fingerprint?.browser?.version,
      engineName: fingerprint?.engine?.name,
      engineVersion: fingerprint?.engine?.version,
      osName: fingerprint?.os?.name,
      osVersion: fingerprint?.os?.version,
      cpuArchitecture: fingerprint?.cpu?.architecture,
      agentClient: fingerprint?.ua,
    },
  };

  const response = await userLogin({ ...data }).unwrap();

  if (response?.data?.accessToken) {
    storeUserInfo({ accessToken: response?.data?.accessToken });
    message.success(`${response?.message}`);
    if (isLoading) {
      return <LoadingPage />;
    }
    const { role } = getUserInfo() as IJwtDecoded;

    router.push(`/${role}`);
  }
} catch (error: any) {
  if (error?.data?.message) {
    message.error(error?.data?.message);
  }
}

}; `

ravi-ojha commented 8 months ago

@BendingBender The problem with including a "pre-minified" JS code is that there's no solid way to verify whether the source and minified version match. This could be a serious risk for certain websites that deal with PII and financial data. Most of today's fav frameworks are webpack/vite based, and they have configs for minifications.

Not saying that the minified files in dist do anything malicious.

DevHeauk commented 7 months ago

same issue

yutingzhao1991 commented 1 week ago

same issue, clientjs should not access navigate during initialization.