undecaf/zbar-wasm

Build fails when using in Next.js App directory router.

Closed this issue · 2 comments

Describe the bug

Hello! I fail to build when trying to use this library within the Next.JS app directory router. I tried several methods like dynamic import, but none worked. Also, it works with npm run dev.
Thank you.
Next.js 14.0.2

To Reproduce
using node v20.8.0 (npm v10.1.0)
npx create-next-app@latest
** default settings ***
overwrite
src/app/page.tsx
as

'use client'
import { scanImageData } from "@undecaf/zbar-wasm";

export default function Home() {
  scanImageData(new ImageData(1, 1));
  return (
    <></>
  )
}

overwrite
next.config.ts
as

/** @type {import('next').NextConfig} */

const nextConfig = {
    transpilePackages: ['@undecaf/zbar-wasm'],
}

module.exports = nextConfig

and
npm run build

error message

Failed to compile.

static/media/index.33c29f02.mjs from Terser
  x 'import.meta' cannot be used outside of module code.
    ,-[24:1]
 24 |     });
 25 | }
 26 | "function" == typeof SuppressedError && SuppressedError;
 27 | var e, r = (e = import.meta.url, async function() {
    :                 ^^^^^^^^^^^
 28 |     let t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
 29 |     var r, n, i = t;
 30 |     i.ready = new Promise((t, e)=>{
    `----

  x 'import.meta' cannot be used outside of module code.
    ,-[33:1]
 33 |     var o, s, a, c = Object.assign({}, i), _ = "object" == "object", u = "function" == typeof importScripts, A = "object" == typeof process && "object" == typeof process.versions && "string" == typeof process.versions.node, f = "";
 34 |     if (A) {
 35 |         const { createRequire: t } = await Promise.resolve().then(()=>g);
 36 |         var h = t(import.meta.url), l = h("fs"), R = h("path");
    :                   ^^^^^^^^^^^
 37 |         f = u ? R.dirname(f) + "/" : h("url").fileURLToPath(new URL("./", import.meta.url)), o = (t, e)=>(t = U(t) ? new URL(t) : R.normalize(t), l.readFileSync(t, e ? void 0 : "utf8")), a = (t)=>{
 38 |             var e = o(t, !0);
 39 |             return e.buffer || (e = new Uint8Array(e)), e;
    `----

  x 'import.meta' cannot be used outside of module code.
    ,-[34:1]
 34 |     if (A) {
 35 |         const { createRequire: t } = await Promise.resolve().then(()=>g);
 36 |         var h = t(import.meta.url), l = h("fs"), R = h("path");
 37 |         f = u ? R.dirname(f) + "/" : h("url").fileURLToPath(new URL("./", import.meta.url)), o = (t, e)=>(t = U(t) ? new URL(t) : R.normalize(t), l.readFileSync(t, e ? void 0 : "utf8")), a = (t)=>{
    :                                                                           ^^^^^^^^^^^
 38 |             var e = o(t, !0);
 39 |             return e.buffer || (e = new Uint8Array(e)), e;
 40 |         }, s = function(t, e, r) {
    `----

  x 'import.meta' cannot be used outside of module code.
     ,-[98:1]
  98 |             B("failed to asynchronously prepare wasm: " + t), P(t);
  99 |         });
 100 |     }
 101 |     i.locateFile ? F(T = "zbar.wasm") || (O = T, T = i.locateFile ? i.locateFile(O, f) : f + O) : T = new URL("zbar.wasm", import.meta.url).href;
     :                                                                                                                            ^^^^^^^^^^^
 102 |     var L, M = (t)=>{
 103 |         for(; t.length > 0;)t.shift()(i);
 104 |     }, x = (t)=>{
     `----

  x 'import', and 'export' cannot be used outside of module code
     ,-[385:1]
 385 | }, Symbol.toStringTag, {
 386 |     value: "Module"
 387 | }));
 388 | export { a as ZBarConfigType, l as ZBarImage, c as ZBarOrientation, R as ZBarScanner, h as ZBarSymbol, s as ZBarSymbolType, d as getDefaultScanner, o as getInstance, y as scanGrayBuffer, E as scanImageData, B as scanRGBABuffer }; //# sourceMappingURL=index.mjs.map
     : ^^^^^^
     `----

Caused by:
    0: failed to parse input file
    1: Syntax Error
Error: 
  x 'import.meta' cannot be used outside of module code.
    ,-[24:1]
 24 |     });
 25 | }
 26 | "function" == typeof SuppressedError && SuppressedError;
 27 | var e, r = (e = import.meta.url, async function() {
    :                 ^^^^^^^^^^^
 28 |     let t = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
 29 |     var r, n, i = t;
 30 |     i.ready = new Promise((t, e)=>{
    `----

  x 'import.meta' cannot be used outside of module code.
    ,-[33:1]
 33 |     var o, s, a, c = Object.assign({}, i), _ = "object" == "object", u = "function" == typeof importScripts, A = "object" == typeof process && "object" == typeof process.versions && "string" == typeof process.versions.node, f = "";
 34 |     if (A) {
 35 |         const { createRequire: t } = await Promise.resolve().then(()=>g);
 36 |         var h = t(import.meta.url), l = h("fs"), R = h("path");
    :                   ^^^^^^^^^^^
 37 |         f = u ? R.dirname(f) + "/" : h("url").fileURLToPath(new URL("./", import.meta.url)), o = (t, e)=>(t = U(t) ? new URL(t) : R.normalize(t), l.readFileSync(t, e ? void 0 : "utf8")), a = (t)=>{
 38 |             var e = o(t, !0);
 39 |             return e.buffer || (e = new Uint8Array(e)), e;
    `----

  x 'import.meta' cannot be used outside of module code.
    ,-[34:1]
 34 |     if (A) {
 35 |         const { createRequire: t } = await Promise.resolve().then(()=>g);
 36 |         var h = t(import.meta.url), l = h("fs"), R = h("path");
 37 |         f = u ? R.dirname(f) + "/" : h("url").fileURLToPath(new URL("./", import.meta.url)), o = (t, e)=>(t = U(t) ? new URL(t) : R.normalize(t), l.readFileSync(t, e ? void 0 : "utf8")), a = (t)=>{
    :                                                                           ^^^^^^^^^^^
 38 |             var e = o(t, !0);
 39 |             return e.buffer || (e = new Uint8Array(e)), e;
 40 |         }, s = function(t, e, r) {
    `----

  x 'import.meta' cannot be used outside of module code.
     ,-[98:1]
  98 |             B("failed to asynchronously prepare wasm: " + t), P(t);
  99 |         });
 100 |     }
 101 |     i.locateFile ? F(T = "zbar.wasm") || (O = T, T = i.locateFile ? i.locateFile(O, f) : f + O) : T = new URL("zbar.wasm", import.meta.url).href;
     :                                                                                                                            ^^^^^^^^^^^
 102 |     var L, M = (t)=>{
 103 |         for(; t.length > 0;)t.shift()(i);
 104 |     }, x = (t)=>{
     `----

  x 'import', and 'export' cannot be used outside of module code
     ,-[385:1]
 385 | }, Symbol.toStringTag, {
 386 |     value: "Module"
 387 | }));
 388 | export { a as ZBarConfigType, l as ZBarImage, c as ZBarOrientation, R as ZBarScanner, h as ZBarSymbol, s as ZBarSymbolType, d as getDefaultScanner, o as getInstance, y as scanGrayBuffer, E as scanImageData, B as scanRGBABuffer }; //# sourceMappingURL=index.mjs.map
     : ^^^^^^
     `----

Caused by:
    0: failed to parse input file
    1: Syntax Error


> Build failed because of webpack errors
   Creating an optimized production build  .%    

Or else the environment in which the behavior occurs needs to be specified:

  • Which target environment (Node/browser/other)?
  • Which type of modules (ESM/CommonJS/other)?
  • Which framework(s)?
  • Which devtools, including their configuration files?
  • package.json content
{
  "name": "test-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@undecaf/zbar-wasm": "^0.10.1",
    "next": "14.0.2",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "autoprefixer": "^10.0.1",
    "eslint": "^8",
    "eslint-config-next": "14.0.2",
    "postcss": "^8",
    "tailwindcss": "^3.3.0",
    "typescript": "^5"
  }
}
  • Any other context about the problem

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Error 'import.meta' cannot be used outside of module code: your build process is producing CommonJS modules but seems to bundle the ES module of zbar-wasm. That module uses import.meta which is invalid in CommonJS modules.

Solution: either make Next.js build ES modules instead of CommonJS modules, or make your build process bundle the CommonJS modules of zbar-wasm. Details can be found here. As I am not familiar with the new (proprietary) Next.js bundler, I can only point you to the example configuration files for Webpack, Rollup and esbuild as a starting point.

Thank you for answering my question. Now I understand that the build process of SSR frameworks like Next.js is so complicated that I almost gave up. 🙃 Maybe using CSR frameworks such as Vite with React would be more feasible... Anyway, I appreciate your great work.Thanks.