Dynamsoft / barcode-reader-javascript

Dynamsoft Barcode Reader JavaScript SDK for package managers. PDF417, QR Code, DataMatrix, MaxiCode and more are supported.
https://www.dynamsoft.com/barcode-reader/sdk-javascript/
Other
169 stars 111 forks source link

WebpackError: Cannot set property 'engineResourcePath' of undefined #72

Closed rubenkuipers closed 3 years ago

rubenkuipers commented 3 years ago

I have followed your webpack example and I'm trying to implement this example into a Gatsby app. During development, when running in the browser, everything is running fine with the config below:

services/dbr.js

/* eslint-disable no-console */
import { BarcodeReader, BarcodeScanner } from "dynamsoft-javascript-barcode";

BarcodeReader.engineResourcePath = "/dbr/"; // Static folder path

// Please visit https://www.dynamsoft.com/customer/license/trialLicense to get a trial license
BarcodeReader.productKeys = process.env.GATSBY_DYNAMSOFT_TRIAL_KEY;

BarcodeScanner.bPlaySoundOnSuccessfulRead = true;

// DBR.BarcodeReader._bUseFullFeature = true; // Control of loading min wasm or full wasm.
export {
    BarcodeReader,
    BarcodeScanner
}

But when I try to build the app using npm run build = gatsby build, I get the following message: WebpackError: TypeError: Cannot set property 'engineResourcePath' of undefined on line 4

Any idea what is going wrong here?

My versions: node: v12.20.0 javascript-barcode: 8.0 gatsby: 2.28.1

Keillion commented 3 years ago

Hi @rubenkuipers ,

I write a test program for gatsby. Work well.

But the test program is not perfect. I learned that gatsby is similar to react. React will refresh or delete something accroding its life cycle logic. You may get unexpected errors when pages become complex.

So don't follow webpack sample or the test sample in this case. dbrjs react sample is a better one for getting started.

Other api in doc:

engineResoucePath

bPlaySoundOnSuccessfulRead Notice: It's an instance property.

rubenkuipers commented 3 years ago

Hi @Keillion, I have tried both examples (react and webpack) with the same result. I think this has something to do with the static html build step of Gatsby.

When I load the library and modify the settings in the same file as the scanner component it seems to work.

// import DBR from 'services/dbr';
import DBR from "dynamsoft-javascript-barcode";
import React from 'react';
import './BarcodeScanner.css';

class ScannerComp extends React.Component {
    constructor(props){
        super(props);
        this.scanner = null;
    }
    async componentDidMount(){

        DBR.BarcodeReader.engineResourcePath = "/dbr/";
        // Please visit https://www.dynamsoft.com/customer/license/trialLicense to get a trial license
        DBR.BarcodeReader.productKeys = process.env.GATSBY_DYNAMSOFT_TRIAL_KEY;
        // DBR.BarcodeReader._bUseFullFeature = true; // Control of loading min wasm or full wasm.

        try{
            this.scanner = this.scanner || await DBR.BarcodeScanner.createInstance();

            if(this.bDestroyed){
                this.scanner.destroy();
                return;
            }

            this.scanner.setUIElement(this.elRef.current);
            // this.scanner.onFrameRead = results => {
            //     if (results.length){
            //        console.log(results)
            //     }
            // };
            this.scanner.onUnduplicatedRead = (txt, result) => {
                this.props.onReadSuccess(result)
            };
            await this.scanner.open();
            this.props.onInit();

        } catch(ex){
            // this.props.appendMessage(ex.message);
            console.error(ex);
        }
    }
}
Keillion commented 3 years ago

@rubenkuipers Yes, I have reproduce the error. No error when run develop, but error when run build. I'm looking into it.

Keillion commented 3 years ago

@rubenkuipers

Gatsby's SSR environment has the two aspects not compatible with dbrjs:

1) webpack.target is not web, so SSR will load dbr.mjs. dbr.mjs is for nodejs and dbr.browser.mjs is for web.

2) document, navigator, HTMLCanvasElement and so on, are undefined. Several sync init functions can't run.

Thus dbrjs can't work.

solution:


1) A walkaround is loading dbrjs async, so dbrjs will not be reached in SSR process.

const DBR = await import("dynamsoft-javascript-barcode");

test gatsby - load dbrjs async


2) Or load components, who use dbrjs, asynchronously.

const Foo = React.lazy(() => import('../componets/Foo));

Maybe the 2rd solution is why dbrjs can work in the same file as the scanner component.


I'm thinking about a better builtin solution in latter version.

Nowsdays only walkaround.

rubenkuipers commented 3 years ago

@Keillion Thanks for investigating and providing the workarounds. I will use workaround 2 for now..

Keillion commented 3 years ago

DBRJS supports SSR to some extent in keillion-dynamsoft-javascript-barcode@0.20210123145106.0.

You can check https://github.com/dynamsoft-rd-0/dbrjs-mass-samples/blob/master/dbrjs-gatsby/src/dbr.js for usage.

But I still don't know why DBR.BarcodeReader is undefined in SSR environment. 😒

This change will be release in one or two week.

@rubenkuipers