webpack: Error: Cannot find module with dynamic import

Do you want to request a feature or report a bug?

bug

What is the current behavior?

When I try to load dynamic module with import('/path/to/my/module.js').then() it work, but when i try to import module with import(rootPath + '/' + myModuleName + '/index.js').then() it doesn’t work.

I got:

 Error: Cannot find module '/Users/hubert_i/Emodyz/launcher-ezgames.eu/modules/test/index.js'.
      at /Users/hubert_i/Emodyz/launcher-ezgames.eu/dist/electron/main.js:10475:9
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:188:7)

If the current behavior is a bug, please provide the steps to reproduce.

What is the expected behavior?

Dynamic import with variable

Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System.

webpack => 3.10.0 npm => 5.6.0 yarn => 1.5.1 Node.js => v9.6.1 Operating System => macOs High Sierra

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 36
  • Comments: 37 (3 by maintainers)

Commits related to this issue

Most upvoted comments

Webpack performs a static analyse at build time. It doesn’t try to infer variables which that import(test) could be anything, hence the failure. It is also the case for import(path+"a.js").

If you need truly dynamic imports, you have to restrict it to a known path:

import("./locales/" + locale + ".js")

In the above example, webpack will create a chunk for each JS file in locale/.

It’s incomprehensible 😢

If i write this it work

import( '/Users/hubert_i/Emodyz/launcher-ezgames.eu/modules/test/index.js')
  .then((m) => {
    console.log(m.name)
  })
  .catch(err => {
    console.error('Error during loading module: ' + err)
    callback()
  })

but when i write this don’t work

const test = '/Users/hubert_i/Emodyz/launcher-ezgames.eu/modules/test/index.js'
import(test)
  .then((m) => {
    console.log(m.name)
  })
  .catch(err => {
    console.error('Error during loading module: ' + err)
    callback()
  })

@meteorplus you can import files dynamically. You only need a static prefix.

why would I even use this I could just import all the files at the top!!

Because it will reduce the main bundle size.

This isn’t dynamic import if we can load dynamically files depending on our variables otherwise why would I even use this I could just import all the files at the top!!

Seriously @ooflorent ?

Would this also work for loading a remote module (over http(s)). I currently am trying to load modules located on a remove server (owned by me). When I import them locally it works fine:

loadJs = ( url, name ) => {
  return new Promise( resolve => {
    import(`/test/${name}`)
    .then((module) => {
      resolve(module.default)
    })
  })
}

However when I try to import over http it fails (no request reaches the backend at all):

import(`http://localhost:3001/api/uicomponents/one/${name}`)

Error: Unhandled Rejection (Error): Cannot find module ‘http://localhost:3001/api/uicomponents/one/[name].js’.

Just in case this helps somebody else who finds this issue, I got the behavior I wanted by adding a rule to my Webpack config to load the files I wanted with file-loader:

{
  test: /\.config\.js$/,
  exclude: /node_modules/,
  loader: "file-loader",
  options: { name: "./conf/[name]-[hash:base36:4].[ext]", },
}

then getting a reference to the output path and dynamically importing it with native import():

const path = require("../conf/" + ENVIRONMENT_NAME + ".config.js");
import(/* webpackIgnore: true */CONFIG_PATH).then(mod => config.init(mod));

This means that all the files matching ../conf/*.config.js get copied to ./conf/ in the build, and a map is established between their original path and the public path. Now, I can use the inline “ignore” comment to cause Webpack to actually emit a native import call, and the argument will be the public path to the file in question. Works great! (…on browsers that support import())

@ooflorent, what if I don’t want to reduce bundle size, but load another webpack packed bundle with all dependencies (even with duplicate dependencies) from absolute path?

I solved this problem by simply removing the opening slash from the dynamic url. this might work for you.

const test = 'Users/hubert_i/Emodyz/launcher-ezgames.eu/modules/test/index.js'
import(`/${test}`)

@rubenberna That’s because webpack uses a simple logic for building its package bundles. It can’t predict what will happen when the code executes. It pre-packs everything it sees within the import() call. If you call import('src/'+path) it will literally package everything in the “src” directory even if “path” is only ever 3 of those files, because the heuristic that webpack uses is so simple. It’s best to just do them individually.

Hi,

If I import each npm package individually with React.Lazy, it’s not a problem:

const GHub = lazy(() => import('react-switch-app-one'))
const Count = lazy(() => import('@ruben.bernardes.dev/counter'))

but if I iterate the paths to create lazy components, webpack cannot find the module:

const packagesPaths = ['react-switch-app-one', '@ruben.bernardes.dev/counter']
const importComponent = path =>
  lazy(() => import(path).catch((e) => console.log(e)));

const loadedAppPaths = packagesPaths.map(app => importComponent(app))
Sidebar.js:25 Error: Cannot find module 'react-switch-app-one'
    at sidebar lazy groupOptions: {} namespace object:5

I would like to load module located in %appdata% in windows or Application Support on macOS how i can do that ?

@MrDarkSkil did you found a solution to that ?

@turbopasi

Yep, many alternatives. Use: https://www.npmjs.com/package/vm2 or https://www.npmjs.com/package/live-plugin-manager

Or:

/**
  * Load custom module with simple require and absolute path
  * 
  * @param {string} path
  */
  private requireDynamically(path: string) {
    path = path.split('\\').join('/');
    return eval(`require('${path}');`);
  }

If you develop a node project and use webpack to build your node project, when you meet the Error: Cannot find module with dynamic import , you can use NodeNative module to replace webpack build create __webpack_require__ function,

webpack.config.js

{
 target: 'node',
    node: {
      __dirname: false,
      __filename: false,
    }
}

eg :

import module from 'module';
const test = '/Users/hubert_i/Emodyz/launcher-ezgames.eu/modules/test/index.js'
module.createRequire(__dirname)(test)
  .then((m) => {
    console.log(m.name)
  })
  .catch(err => {
    console.error('Error during loading module: ' + err)
    callback()
  })

Guys, if you want really dynamic imports with complete control over how/when/what is imported, use SystemJS: https://github.com/systemjs/systemjs

If you want imports that depend on very simple rules, use what webpack comes with by default.

Unsubscribes to issue

Thanks! Using import('../../node_modules/@library-' + myVar) webpack build fails trying to parse to much files (markdown files) from other librairies. But if i specify import('@library-' + myVar)/dist//dist/esm/index.js it’s working.

Webpack performs a static analyse at build time. It doesn’t try to infer variables which that import(test) could be anything, hence the failure. It is also the case for import(path+"a.js").

If you need truly dynamic imports, you have to restrict it to a known path:

import("./locales/" + locale + ".js")

In the above example, webpack will create a chunk for each JS file in locale/.

Is there any specific webpack config required for this? Because this works: this.component = defineAsyncComponent(() => import('@/views/branches/create.vue')); This does not work this.component = defineAsyncComponent(() => import('@/views/' + 'branches/create' + '.vue'));

Reason: Error: Cannot find module ‘@/views/branches/create.vue’

Update Solved, in babel config removed plugin [‘dynamic-import-node’],