Resolving require paths with webpack

JavascriptWebpack

Javascript Problem Overview


I'm still confused how to resolve module paths with webpack. Now I write:

myfile = require('../../mydir/myfile.js') 

but I'd like to write

myfile = require('mydir/myfile.js') 

I was thinking that resolve.alias may help since I see a similar example using { xyz: "/some/dir" } as alias then I can require("xyz/file.js").

But if I set my alias to { mydir: '/absolute/path/mydir' }, require('mydir/myfile.js') won't work.

I feel dumb because I've read the doc many times and I feel I'm missing something. What is the right way to avoid writing all the relative requires with ../../ etc?

Javascript Solutions


Solution 1 - Javascript

Webpack >2.0

See wtk's answer.

Webpack 1.0

A more straightforward way to do this would be to use resolve.root.

http://webpack.github.io/docs/configuration.html#resolve-root

> resolve.root > > The directory (absolute path) that contains your modules. May also be an array of directories. This setting should be used to add individual directories to the search path.

In your case:

webpack config
var path = require('path');

// ...

  resolve: {
    root: path.resolve('./mydir'),
    extensions: ['', '.js']
  }
consuming module
require('myfile')

or

require('myfile.js')

see also: http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories

Solution 2 - Javascript

For future reference, webpack 2 removed everything but modules as a way to resolve paths. This means root will not work.

https://gist.github.com/sokra/27b24881210b56bbaff7#resolving-options

The example configuration starts with:

{
  modules: [path.resolve(__dirname, "app"), "node_modules"]
  // (was split into `root`, `modulesDirectories` and `fallback` in the old options)

Solution 3 - Javascript

resolve.alias should work exactly the way you described, so I'm providing this as an answer to help mitigate any confusion that may result from the suggestion in the original question that it does not work.

a resolve configuration like the one below will give you the desired results:

// used to resolve absolute path to project's root directory (where web pack.config.js should be located)
var path = require( 'path' );
...
{
  ...
  resolve: {
    // add alias for application code directory
    alias:{
      mydir: path.resolve( __dirname, 'path', 'to', 'mydir' )
    },
    extensions: [ '', '.js' ]
  }
}

require( 'mydir/myfile.js' ) will work as expected. If it does not, there must be some other issue.

If you have multiple modules that you want to add to the search path, resolve.root makes sense, but if you just want to be able to reference components within your application code without relative paths, alias seems to be the most straight-forward and explicit.

An important advantage of alias is that it gives you the opportunity to namespace your requires which can add clarity to your code; just like it is easy to see from other requires what module is being referenced, alias allows you to write descriptive requires that make it obvious you're requiring internal modules, e.g. require( 'my-project/component' ). resolve.root just plops you into the desired directory without giving you the opportunity to namespace it further.

Solution 4 - Javascript

In case anyone else runs into this problem, I was able to get it working like this:

var path = require('path');
// ...
resolve: {
  root: [path.resolve(__dirname, 'src'), path.resolve(__dirname, 'node_modules')],
  extensions: ['', '.js']
};

where my directory structure is:

.
├── dist
├── node_modules
├── package.json
├── README.md
├── src
│   ├── components
│   ├── index.html
│   ├── main.js
│   └── styles
├── webpack.config.js

Then from anywhere in the src directory I can call:

import MyComponent from 'components/MyComponent';

Solution 5 - Javascript

My biggest headache was working without a namespaced path. Something like this:

./src/app.js
./src/ui/menu.js
./node_modules/lodash/

Before I used to set my environment to do this:

require('app.js')
require('ui/menu')
require('lodash')

I found far more convenient avoiding an implicit src path, which hides important context information.

My aim is to require like this:

require('src/app.js')
require('src/ui/menu')
require('test/helpers/auth')
require('lodash')

As you see, all my app code lives within a mandatory path namespace. This makes quite clear which require call takes a library, app code or a test file.

For this I make sure that my resolve paths are just node_modules and the current app folder, unless you namespace your app inside your source folder like src/my_app

This is my default with webpack

resolve: {
  extensions: ['', '.jsx', '.js', '.json'],
  root: path.resolve(__dirname),
  modulesDirectories: ['node_modules']
}

It would be even better if you set the environment var NODE_PATH to your current project file. This is a more universal solution and it will help if you want to use other tools without webpack: testing, linting...

Solution 6 - Javascript

I have resolve it with Webpack 2 like this:

module.exports = {
  resolve: {
    modules: ["mydir", "node_modules"]    
  }
}

You can add more directories to array...

Solution 7 - Javascript

If you're using create-react-app, you can simply add a .env file containing

NODE_PATH=src/

Source: https://medium.com/@ktruong008/absolute-imports-with-create-react-app-4338fbca7e3d

Solution 8 - Javascript

Got this solved using Webpack 2 :

   resolve: {
      extensions: ['', '.js'],
        modules: [__dirname , 'node_modules']
    }

Solution 9 - Javascript

This thread is old but since no one posted about require.context I'm going to mention it:

You can use require.context to set the folder to look through like this:

var req = require.context('../../mydir/', true)
// true here is for use subdirectories, you can also specify regex as third param

return req('./myfile.js')

Solution 10 - Javascript

Simply use babel-plugin-module-resolver:

$ npm i babel-plugin-module-resolver --save-dev

Then create a .babelrc file under root if you don't have one already:

{
    "plugins": [
        [
            "module-resolver",
            {
                "root": ["./"]
            }
        ]
    ]
}

And everything under root will be treated as absolute import:

import { Layout } from 'components'

For VSCode/Eslint support, see here.

Solution 11 - Javascript

I didn't get why anybody suggested to include myDir's parent directory into modulesDirectories in webpack, that should make the trick easily:

resolve: {
    modulesDirectories: [
      'parentDir',
      'node_modules',
    ],
    extensions: ['', '.js', '.jsx']
  },

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongpblView Question on Stackoverflow
Solution 1 - JavascriptAndyCunninghamView Answer on Stackoverflow
Solution 2 - JavascriptwtkView Answer on Stackoverflow
Solution 3 - JavascriptsethroView Answer on Stackoverflow
Solution 4 - JavascriptAlex KlibiszView Answer on Stackoverflow
Solution 5 - JavascriptSystematicFrankView Answer on Stackoverflow
Solution 6 - JavascriptDamian PavlicaView Answer on Stackoverflow
Solution 7 - JavascriptBrian BurnsView Answer on Stackoverflow
Solution 8 - JavascriptAaqibView Answer on Stackoverflow
Solution 9 - JavascriptaltShiftDevView Answer on Stackoverflow
Solution 10 - JavascriptLuciaView Answer on Stackoverflow
Solution 11 - Javascriptdaniele bertellaView Answer on Stackoverflow