简体   繁体   中英

Having trouble with the webpack module resolution

I have a global npm module installed, let's call it abc-cli . Now I have a react app that runs with this command: abc-cli run .

What abc-cli basically does is gets the components in the app and compiles and runs it with its source.

Now I want to publish this app as a separate npm module. So I am using the Webpack to generate the bundle. While resolving modules, webpack is unable to resolve the modules that are a part of the abc-cli . That is obvious, webpack has no idea what abc-cli is.

So my question is how do I make sure that webpack resolves the modules dependencies? Is there any way I can make the webpack run/compile the abc-cli while bundling.

Or the worst case could be how to suppress the module resolution warning or ignore those modules. Because I know that its going to be present.

Example:

In my app , I have an import statement as

import SomeComponent from '@abc/components';

Now while bundling, the webpack won't resolve this module:

Module not found: Error: Can't resolve '@abc/components' in '/home/shishir/app/src/shared/visualizations'

It would be great help if I could get around this.

My webpack configuration:

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'index.js',
    libraryTarget: 'commonjs2'
  },
  resolve: {
    extensions: ['.mjs', '.js', '.jsx']
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        include: path.resolve(__dirname, 'src'),
        exclude: /(node_modules|bower_components|build)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              'es2015',
              'react',
              'stage-2'
            ]
          }
        }
      },
      {
        test: /\.css$/,
        use: [
          { loader: "style-loader" },
          { loader: "css-loader" }
        ]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      }
    ]
  },
  externals: {
    'react': 'commonjs react'
  }
};

I tried the null-loader :

{
        test: require.resolve("@abc/components"),
        use: 'null-loader'
}

but it didnt help.

These're two ways to inform webpack of extra location to look for a module.

// webpack.config.js

module.exports = {
  //...
  resolve: {
    // 1. add extra `node_modules` directory to search path
    modules: ['node_modules', '/abs_path/to/global/node_modules'],
    // 2. use alias to explicitly map a module name to its exact location
    alias: {
      '@abc': '/abs_path/to/global/node_modules/@abc'
    }
  }
};

For your use case, if you only has @abc module sitting outside the conventional local node_modules directory, I'd recommend you use resolve.alias .

Source: https://webpack.js.org/configuration/resolve/#resolvemodules .

If you are doing an import like this:

import SomeComponent from '@abc/components';

You are telling Webpack to import a module named @abc/components from its "resolve root". This resolve root is normally 'node_modules' . (Imagine if @abc/components was an npm package, that'd work fine.)

As you obtained this library from a different source via your command line tool, you will have these dependencies at a different location. Webpack won't magically recognize these, but you have a few simple options:

  1. Make abc-cli copy the abc 's component files to app 's node_modules/@abc .
  2. Create a symlink in app 's node_modules called @abc that points to abc's folder. Webpack traverses symlinks by default and this spares you the time to copy the files each time. Slightly better solution IMO, especially if abc changes more than once in a while.
  3. Tell webpack to also search for modules in @abc 's folder, not just node_modules . You can do that using resolve.modules just like Ngô Hùng Phúc showed in his answer. Be a little careful though, as you are importing the modules like @abc/components you have to point webpack to the directory one level above @abc , and of course this requires abc's component directory to be called @abc .

You need to let webpack know what is your location of that module. My project have structure like this

在此输入图像描述

Ex: I want to import some file in Helper folder I will need to do this

import {isDomExist} from "Helper/Util";

Because below code do this for me

resolve: {
    modules: [
        path.resolve('./React/js/App'),
        path.resolve('./React/js/App/Modules/Client'),
        path.resolve('./React/js/App/Modules/Adnmin'),
        path.resolve('./node_modules')
    ]
},

You can see that I tell webpack to resolve the path come from ./React/js/App.

So Helper folder is live inside App folder webpack will know where to look for.

Below is my full source code for your ref here

Please let me know if this is the fix for you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM