Reputation: 1663
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:
/src
/components
/Base
/App.jsx
/Pages.jsx
/...
/Page1
/Page1Component1.jsx
/Page1Component2.jsx
/...
/Page2
/Page2Component1.jsx
/Page2Component2.jsx
/...
/...
/libs
/bootstrap.js
/jquery.js
/react.js
/...
/scripts
/index.js
/utils.js
/styles
/main.css
/html
/index.html
Right now I have gulp set up to do this:
/dest
to put everything/scripts
, name it main.js
, put it in dest/libs
, name it libs.js
, put it in dest/components
, run it through babel, name it comps.js
, put it in dest/html
file and one /styles
file into destThen here is how the app runs:
index.html
main.js
main.js
requests libs.js
and comps.js
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:
Thanks, and sorry about the rambley question.
Upvotes: 0
Views: 102
Reputation: 120513
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.
Upvotes: 1