Search code examples
javascriptnode.jswebpackpackaging

How to get node package consumer directory from node_modules?


I am trying to create a simple node module that creates a set of folders in the app that consumes it. I exported a simple createLayout function that creates the folders. I pushed my changes to git and did an npm i from another folder. Lets call the modules creator and consumer for the sake of explanation. When I try to call createLayout in consumer I am running in to several issues. I am in E:\ drive.

Below is the index.js in creator:

import {sync} from 'mkdirp';

export function createLayout(config) {
  sync('./folder1');
}

And index.js in consumer:

var createLayout = require('creator').createLayout;
createLayout();
// with config createLayout({path: __dirname})

This results in creating a folder in E:\ not relative to consumer. So I tried including __dirname:

sync(__dirname + '/folder1');

Once again, this also creates a folder in E:\ not relative to consumer. I searched for bit like in various modules to see how they are doing when they are reading the config file, for instance webpack uses process.cwd. So I tried that too.

sync(process.cwd() + '/folder1');

Same, results in creating a folder in E:\ not relative to consumer. Then I tried to pass the __dirname or cwd through a config object.

// get __dirname from the `consumer` in config.path
sync(config.path + '/folder1');

But it ends up in following error:

Error: EPERM: operation not permitted, mkdir 'E:\'

I tried logging all the values in both creator and consumer:

console.log(__dirname, process.cwd(), config.path)
// creator: / / E:\projects\consumer
// consumer: E:\projects\consumer E:\projects\consumer E:\projects\consumer

I am using webpack with babel to pack the creator, plain js in consumer. I do not know what am I doing wrong. I am pretty new to nodejs ways of working.

Update

I am noticing that this is occurring only when I use webpack to build the creator. A simple module.exports works normally as anyone would expect. So I am including my webpack config file:

module.exports = {
  entry: [
    './index.js'
  ],
  output: {
    filename: 'creator.js',
    path: __dirname + '/dist',
    library: 'creator',
    libraryTarget: 'umd'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel'
      }
    ]
  },
  externals: {
    fs: 'fs'
  }
};

Solution

  • Correct solution is adding this line in config:

    target: 'node'
    

    this will make webpack to ignore modules like fs and mkdirp and some other.

    Now no longer need to specify externals.


    Incorrect solution given before:

    Just add mkdirp to externals and it will resolve you problem:

      externals: {
        fs: 'fs',
        mkdirp: 'mkdirp'
      }