samsam2310 / zbar.wasm

A wasm build of C/C++ ZBar barcode scanning library.
GNU Lesser General Public License v2.1
222 stars 30 forks source link

Support for Webpack 5 #8

Closed M4GNV5 closed 3 years ago

M4GNV5 commented 3 years ago

Hey,

webpack comes with experimental WASM support. I've been trying to use this library with next.js, but so far without luck:

Without any configuration:

error - ./node_modules/zbar.wasm/dist/zbar.wasm.bin
Module parse failed: Unexpected character '' (1:0)
The module seem to be a WebAssembly module, but module is not flagged as WebAssembly module for webpack.
BREAKING CHANGE: Since webpack 5 WebAssembly is not enabled by default and flagged as experimental feature.
You need to enable one of the WebAssembly experiments via 'experiments.asyncWebAssembly: true' (based on async modules) or 'experiments.syncWebAssembly: true' (like webpack 4, deprecated).
For files that transpile to WebAssembly, make sure to set the module type in the 'module.rules' section of the config (e. g. 'type: "webassembly/async"').
(Source code omitted for this binary file)

Setting syncWebAssembly gives the same error.

Adding the following to my nextjs config:

  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.wasm(\.bin)?$/,
      use: [
        {
          loader: 'file-loader',
        },
      ],
    })

    config.experiments = config.experiments || {}
    config.experiments.syncWebAssembly = true
    return config
  },

The website compiles but tries to load http://localhost:3000/_next/919afea9035a50020a842aba55b2024a.bin which does not exist (error 404). And thus cases an error WASM was not loaded

Any tips on getting this to run? Maybe now that webpack has WASM support the fetch/file-loader hack could even be replaced?

samsam2310 commented 3 years ago

Hi @M4GNV5 ,

Since the Webpack still marks webassembly as an experimental feature, I'd prefer to keep using the file-loader rather than enable the flags. I'm not familiar with next.js and webpack 5. However, the file-loader is a well known loader for webpack and is used for the resources like images, I think it should still be available for webpack 5. So I suggest you to check if the file-loader can works for other files and to figure out why the file-loader didn't work for wasm.bin.

Enable the experiment could also be an option. But I don't want the users to be forced enabling the flags if they don't want to. And I also don't want to make the initialization process complicated. Thus, I don't think I'm going to change the default loading logic for now.

For those who want to use the webpack webassembly loader, try to replace the load.ts with some other implementation by some webpack replacement plugin . For these cases, the file zbar.wasm could be used directly instead of using zbar.wasm.bin. And, If you feel your implementation is general enough, a PR is also welcome.

Hope this reply to your question.

alexhorn commented 3 years ago

You need to configure webpack 5 to treat .bin as a static file and output it into the static file folder.

Here's a working next.config.js for Next.js 11:

module.exports = {
  reactStrictMode: true,
  webpack: config => {
    config.module.rules.push({
      test: /\.bin$/i,
      type: 'asset/resource',
      generator: {
        // important, otherwise it will output into a folder that is not served by next
        filename: 'static/[hash][ext][query]'
      }
    })
    return config
  },
}
hadrien-f commented 3 years ago

As anyone successfully used the lib with angular or webpack5 ? I am struggling with the configuration since changing webpack config with angular is not easy.

I tried to change the load.js file and loading dynamically the module but I must be missing something

markpeterfejes commented 3 years ago

@hadrien-f I managed to use the library without any problems with Angular v12.

The only thing I needed was the @angular-builders/custom-webpack builder, pointing it to my extra webpack config with the help of @alexhorn:

import { Configuration } from 'webpack';

export default (config: Configuration) => {
    config.module?.rules?.push({
        test: /\.bin$/i,
        type: 'asset/resource',
        generator: {
            filename: 'assets/[hash][ext][query]',
        },
    });
    return config;
};
M4GNV5 commented 3 years ago

I will close this issue, as it seems to work with different frameworks and a correct configuration.