Next.js Discord

Discord Forum

How to force browser version of esm import and not node?

Unanswered
Cuban Crocodile posted this in #help-forum
Open in Discord
Cuban CrocodileOP
Hi, I'm trying to use https://github.com/google/magika in a new Next.js project and running into issues. As you can see from the package.json this module provides exports for both Node ("node") and browser ("default"): https://github.com/google/magika/blob/main/js/package.json

This is causing issues in Next - when I try to import "magika" alone, it pulls in the Node export, which causes a range of issues since it uses "fs" and several other Node-only modules. This happens even with "use client" and/or dynamic imports.

If I manually modify magika's package.json to remove the "node" exports, everything starts working - this confirms that's the main issue.

54 Replies

Cuban CrocodileOP
Specifically, I get errors like this for static import:
 ⨯ ./node_modules/magika/dist/mjs/src/config.js:1:1
Module not found: Can't resolve 'fs/promises'
> 1 | import * as fs from 'fs/promises';
    | ^
  2 | export class Config {
  3 |     loaded = false;
  4 |     labels = [];

https://nextjs.org/docs/messages/module-not-found


And this for dynamic import:
 ⨯ ./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <!doctype html>
| <html>
| <head>

Import trace for requested module:
./node_modules/@mapbox/node-pre-gyp/lib/util/nw-pre-gyp/index.html
./node_modules/@mapbox/node-pre-gyp/lib/ sync ^\.\/.*$
./node_modules/@mapbox/node-pre-gyp/lib/node-pre-gyp.js
./node_modules/@tensorflow/tfjs-node/dist/index.js
./node_modules/magika/dist/mjs/src/model_node.js
./node_modules/magika/dist/mjs/magika_node.js
./src/app/file_input.tsx
./src/app/page.tsx
But both indicate that it's importing the node version of magika by mistake
@@ts-ignore I am not sure but try importing it using `next/dynamic`
Cuban CrocodileOP
thanks for the suggestion! That's what I meant by 'dynamic import' above, I should have been more specific. (that is, it doesn't work, but it does throw different errors at least, probably because it happens in a different context)
if after, you can try await import("name") and see
something like this
Cuban CrocodileOP
@@ts-ignore Thank you for the extra suggestion. Unfortunately, even that doesn't work. It throws the same kind of errors as dynamic import.
It seems like this is just a Next.js bug
a quick rundown whats happening and what u tried
Cuban CrocodileOP
@gin Importing a module that declares "node" and "default" exports results in the import always resolving to "node", regardless of how it was imported (that is, even with dynamic or await import). For this package in particular, the functionality differs greatly for Node and doesn't work in-browser, as it relies heavily on filesystem APIs for Node. https://github.com/google/magika/blob/main/js/package.json
Expected result: resolves to "default" for both dynamic with ssr: false and await import, since both should be a 'browser' environment for sure.

(Though actually, I'd much prefer a static import so it can be included in SSG)
alright so u trying to import a module which should be working for javascript but it resolves to node and throws expected errors on client?
Cuban CrocodileOP
Seems like the errors happen at build time
otherwise, yes
u followed the documentation on that?
this one
Cuban CrocodileOP
Ah, I should maybe add that I have gotten it working by downgrading to 0.2.12 of that package, which is the version right before the latest where they added the "node" export
The same code fails simply by changing the version to 0.2.13
it only fails when building?
or in dev aswell
i have multiple potential fixes i could try but they are small so could u share some minimalist implementation of magika?
Cuban CrocodileOP
Yep, working on a codesandbox repro right now
👍
See README and page/client.tsx
@Cuban Crocodile
while this technically fixes the issue ->
extend webpack config in next.config with
config.module.rules.push({
      test: /\.html$/,
      use: 'html-loader',
    });

install missing dependencies ->
aws-sdk, html-loader, mock-aws-s3, nock

I wouldnt really recommend this solution
since this package is not really for client usage since its badly documented and has bad practices
the best thing u can do here is relaying the logic to a route handler
and passing the file as binary
btw, for it to compile correctly u have to force the entire route to be rendered dynamically ->
export const dynamic = "force-dynamic";

in page.tsx
now u can run build
not recommended better to solve this using route handlers
Cuban CrocodileOP
@gin am I understanding right that you just got the Node.js version to work somehow? Pretty impressive if so! but I guess that means that there is not in fact a way to resolve the original import issue? Isn't that itself still a Next.js issue?
do the things above and it will work
its the problem of the library
as i said its badly documented, bad practices, and poor implementation
Cuban CrocodileOP
acknowledged, just trying to clarify if this is all to get it to work with the "node" import, and not forcing the "browser" import to be resolved to (it seems like the former)
the error resulted because the libraries referenced modules tried to import html
some random module was importing html which webpack wasnt supporting
so just extended it with the needed plugin
this is what the error was telling me after i forked it
so i just went fixing that and it worked
Cuban CrocodileOP
that is pretty weird indeed. but then why did changing to "browser" import (via downgrading magika to 0.2.12) work?
err, "default" rather
hm yeah maybe they also changed some other things aswell?
even tho the library is weird indeed
Cuban CrocodileOP
true, could be a wrong assumption that it's definitely that