How Can I Use Gulp And Browserify For My Javascript App?

- 1 answer

I am finally trying to bring a modern build system to my app, and I'm hoping someone can help. I think I need a few paradigm shifts.

So this is how my app is structured:


Right now I have gulp set up to do this:

  • Make a new folder /dest to put everything
  • Combine everything in /scripts, name it main.js, put it in dest
  • Combine everything in /libs, name it libs.js, put it in dest
  • Combine everything in /components, run it through babel, name it comps.js, put it in dest
  • Copy the one /html file and one /styles file into dest

Then here is how the app runs:

  • Open index.html
  • That page requests main.js
  • main.js requests libs.js and comps.js
  • Everything works

But here is the issue I'm running into: A lot of stuff here relies on other stuff being global.index.js waits for comps.js and libs.js to load, then calls ReactDOM.render(<App />...), which means both ReactDOM and App need to be global.

Now I'm trying to add something that needs require(), and I try to use Browserify for it. But Browserify takes the code that needs the require and wraps it up in a way that, I believe, makes nothing global.

I realize that I need to turn my app into actual modules, instead of just a bunch of files that concatenate and call each other. And I know that avoiding global variables will be a good thing in the long run. But I'm having a really hard time figuring out how.

For example, I have >50 React modules. It seems wrong to add module.exports to every single one of those, and then import them all to the main file. Further, some of the things in /lib are libraries that don't export as modules, they're made to be run in the <head> tag, like Google Charts.

So I guess my questions are:

  • Where should my module exports be, and how do they fit into my gulp tasks? Do I concatenate then export?
  • How do I deal with libraries that aren't modules?
  • Is my app really poorly laid out, and I just need to restructure from scratch?

Thanks, and sorry about the rambley question.



First, there's nothing wrong with your file structure.

Second, the best thing you can do is follow the "one module, one file" rule. That does mean adding module.exports or export default to every single file. That's just good JavaScript. But it doesn't mean importing them all into your main file, which brings us to:

Third, think in modularity. Files should require or import precisely what they need and nothing they don't. For example, if your App uses Page1 and Page1 uses Page1Component1, then that's how your imports should work:

App -> Page1 -> Page1Component1
             -> Page1Component2
    -> Page2 -> Page2Component1
             -> ...

This ensure separation of concerns and protects your code from easy-to-trigger errors later on (like those from nested dependency changes). And your build system should generate one file (but you can tackle performance later if needed with chunking and so forth).

And you're correct that in this kind of structure, using Browserify or Webpack will ensure that nothing is global - and that's a good thing (though I will note that you can tell them explicitly to expose components, which is sometimes necessary for libraries).

And that leaves libraries that you don't control that you can't import. This does not apply to Bootstrap, jQuery, or React, which all have require-able modules from NPM. But assuming that you have a library you didn't mention that is not available through NPM, you can still include it globally in your HTML with a script tag and tell Browserify or Webpack to expose it for requiring.