magiclabs / magic-js

Magic browser/React Native JavaScript SDK is your entry-point to integrating passwordless authentication inside your application.
https://magic.link/docs/api-reference/client-side-sdks/web
Apache License 2.0
455 stars 85 forks source link

Critical dependency: require function is used in a way in which dependencies cannot be statically extracted #295

Closed picks44 closed 2 years ago

picks44 commented 2 years ago

🐛 Description

When upgrading from magic-sdk v6.2.1 to magic-sdk v8.1.0 within a perfectly working VueJS3 project, I am getting this warning when serving my app (yarn serve):

 WARNING  Compiled with 1 warning                                                                                                                                                                                 
 warning  in ./node_modules/magic-sdk/dist/es/index.js
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

🌎 Environment

Software Version(s)
magic-sdk 8.1.0
Browser Chrome
yarn 1.22.17
Operating System Windows
smithki commented 2 years ago

Please provide a reproducible example and we'll take a look.

Gyunbie commented 2 years ago

Please provide a reproducible example and we'll take a look.

I just created a Nuxt project with TailwindCSS preset and installed Moralis with dependencies and I get this error

smithki commented 2 years ago

Please provide a reproducible example and we'll take a look.

Adamj1232 commented 2 years ago

@smithki Same issue breaking our build using Magic-SDK 8.1.0 at Blocknative I have had to add CI=false to the build command in the package.json to allow building/deployment in our CI environment

Screen Shot 2022-03-16 at 3 45 15 PM

The prop value with an expression type of ChainExpression could not be resolved. Please file issue to get this fixed immediately.
Compiled with warnings.
 ./node_modules/magic-sdk/dist/es/index.js
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
bmeeder22 commented 2 years ago

+1

Gyunbie commented 2 years ago

Please provide a reproducible example and we'll take a look.

This is pretty reproducible in like 5 minutes, depending on how much you want to develop your library. Again, creating a Nuxt project with TailwindCSS preset and installing Moralis dependencies makes this error show up on my screen.

Adamj1232 commented 2 years ago

Please provide a reproducible example and we'll take a look. @smithki We have customers sending us this issue trying to make Magic available to their customers and their build breaking. Please update us on the progress of this so we can pass along

smithki commented 2 years ago

Thank you for the code sample @Adamj1232. I'm off-the-clock this week but will make time for this early next week.

smithki commented 2 years ago

After digging into this issue a bit, the warning appears to be related to this code being inlined into magic-sdk's ESM output:

var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
  if (typeof require !== "undefined")
    return require.apply(this, arguments);
  throw new Error('Dynamic require of "' + x + '" is not supported');
});

This could either be resolved at the ESBuild layer, but can be worked around for your individual purpose by adjusting your bundler config to resolve magic-sdk to its CommonJS entrypoint (magic-sdk/dist/cjs/index.js), which won't manifest this warning. It is also valid to ignore this warning using whatever API/plugin your bundler provides to silence noisy logs. This warning in context of magic-sdk will not manifest any bugs at runtime.

picks44 commented 2 years ago

Wonderfull, thanks @smithki

Adamj1232 commented 2 years ago

@smithki can you give an idea of what this bundler config would look like to resolve to CommonJS entrypoint? We have multiple customers asking for examples

smithki commented 2 years ago

@Adamj1232 that would really depend on your bundler. I suggest looking for docs specific to your tooling. Unfortunately, there is no "conventional wisdom" to share.

Adamj1232 commented 2 years ago

@Adamj1232 that would really depend on your bundler. I suggest looking for docs specific to your tooling. Unfortunately, there is no "conventional wisdom" to share.

Do you have examples for webpack and rollup? Those are the most common for our users

smithki commented 2 years ago

I can point you to these resources, but have not yet attempted to write a working example:

For the record, I don't work at Magic anymore. All I can provide is limited "free" support like this. If you are looking for extra help, I suggest you reach out to Magic's support team directly, or try StackOverflow.

Ethella commented 2 years ago

Thx @smithki, I'll take it from here.

Though I'm not an expert on ESbuild, I will start to check the demo in the thread. @Adamj1232 Feel free to ping me for any more context you have.

Adamj1232 commented 2 years ago

@Ethella I have a fix for react using CRACO

const path = require("path");

module.exports = {
  reactScriptsVersion: "react-scripts" /* (default value) */,

  webpack: {
    alias: {
      "magic-sdk": path.resolve(
        __dirname,
        "node_modules/magic-sdk/dist/cjs/index.js"
      ),
    },
  },
};

For pure webpack I believe alias is nested with resolve ... resolve.alias...

These would be helpful to add to your documentation

Ethella commented 2 years ago

I was about to say I found no issues reported during the build because you already fixed it 🚀.

I'll update our doc to reflect your suggestion. Thx a lot!

andreisucman commented 2 years ago

Hey, @Adamj1232 how to do the same for node.js? I can't upload my backend to Heroku because of this same problem. I could solve it for the frontend using your suggestion, but how about node.js? Thank you a lot.

Adamj1232 commented 2 years ago

@andreisucman you would have to look into the documentation for the compiler you are using.

andreisucman commented 2 years ago

@Adamj1232 . I'm using webpack. Here is my config. How can I modify it?

module.exports = {
    mode: 'production',
    entry: './lib/engine.mjs',
    output: {
        library: 'engine',
        libraryTarget: 'umd',
        globalObject: 'this',
        umdNamedDefine: true,
        filename: 'engine.js',
    },
}
Adamj1232 commented 2 years ago

I think it would be something like this but you would have to do some testing to confirm. Official docs for webpack - https://webpack.js.org/configuration/resolve/#resolvealias

module.exports = {
    mode: 'production',
    entry: './lib/engine.mjs',
    output: {
        library: 'js-chess-engine',
        libraryTarget: 'umd',
        globalObject: 'this',
        umdNamedDefine: true,
        filename: 'engine.js',
    },
  resolve: {
    alias: {
        "magic-sdk": path.resolve(__dirname, "node_modules/magic-sdk/dist/cjs/index.js"),
    }
  }
}

@andreisucman If this ends up working it would be great to respond here so others know what works for webpack

andreisucman commented 2 years ago

Thank you @Adamj1232. I'll test and write.

andreisucman commented 2 years ago

@Adamj1232 It worked! Thanks again. Here is the full snippet for node js using webpack (make sure to update mode, entry, and output per your project).

const path = require("path");

module.exports = {
  mode: "production",
  entry: "./lib/engine.mjs",
  output: {
    library: "engine",
    libraryTarget: "umd",
    globalObject: "this",
    umdNamedDefine: true,
    filename: "engine.js",
  },
  resolve: {
    alias: {
      "magic-sdk": path.resolve(
        __dirname,
        "node_modules/magic-sdk/dist/cjs/index.js"
      ),
    },
  },
};