Aleksandar Dimitrov
Aleksandar Dimitrov

Reputation: 9487

How to modularize a legacy JavaScript project

I need to use webpack to build a legacy JS project that so far did not have a build system.

The project is split up into ~30 JS files, all of which assign functions and fields to a single global myApp mega-object. Previously, all these files were included separately in one namespace. It looked somewhat like this:

myApp.js:

const myApp = {
  saySomething: function(x) {
    console.log(x);
  },
  something: "something"
};

someModule.js:

myApp.anotherModule = {
  foo: function(x) {
    myApp.someModule.bar(x);
  }
};

anotherModule.js:

myApp.someModule = {
  bar: function(x) {
    myApp.saySomething(x);
  },
  start: function() {
    myApp.someModule.foo(myApp.something);
  }
};

The entrypoint would call myApp.someModule.start(), the control flow would weave between the different parts of the mega-object.

I tried factoring out an index.js like so:

const myApp = require('./myApp');
myApp.someModule = require('./someModule');
myApp.anotherModule = require('./anotherModule');

(with the appropriate module.exports declarations in the respective files.)

But when e.g. anotherModule's start function calls myApp.someModule.foo(), that's not in scope. I can't bring it into scope with require in the module itself — I'd have to include someModule, which would in turn have to include anotherModule, etc.

Is there a way out of this mess without having to refactor the entire project (and utterly break the test suite, etc.?)

In other words: can I use webpack to assemble a mega-object and not isolate its parts' respective scope?

Upvotes: 1

Views: 193

Answers (1)

Lorenzo Catalano
Lorenzo Catalano

Reputation: 477

you should pass a myApp reference to the require

require('./someModule')(myApp);

and the module should export a function accepting myApp as parameter

myApp.anotherModule = function(myApp) {
  return {
       foo: function(x) {
       myApp.someModule.bar(x);
     }
  }
};

so

myApp.someModule = require('./someModule')(myApp);

executes the function and returns your object with functions binded to myApp

Upvotes: 1

Related Questions