DISCLAIMER! This post was written way back in 2015 and contains generally bad advice. Back in the day it was a questionable but effective abuse of commonjs module resolution, these days most bundler's offer much better alternatives. (I tried to look through old webpack docs to find out if resolve.alias worked like it does now, but I couldn't find a concrete answer. Either way I was ignorant of it when I wrote this.)
## Problem
Nested folders are cool. Relative require statements are not.
client
components
component1.jsx
component2.jsx
mixins
ClassNameMixin.jsx
node_modules
react
lodash
webpack
public
server
If I would like to require ClassNameMixin from component1 I would use the following line:
var ClassNameMixin = require('../mixins/ClassNameMixin.jsx');
When the project scales these relative requires would only get worse. Soon we are counting folder levels and writing things like:
var whyIsThisFileHere = require('../../../../../public/someFolder/whyIsThisFileHere.js');
var marmoset = require('../folderZ/orange/southAmerica/marmoset.js');
var ribbon = require('../../gibbon/with/a/ribbon.js');
It's messy, it's confusing and it makes it really easy to tangle logic together. It's dependency spaghetti code.
## Solution
As it turns out node/webpack/browserify will recursively search through your folder structure for any and all node_modules folders. It doesn't really matter where your hide them, if you require('radical')
node will look through your folder structure for node_modules/radical
and proceed from there.
So the solution is to put your client code in it's own special node_modules folder.
client
node_modules
myApp
components
component1.jsx
component2.jsx
mixins
ClassNameMixin.jsx
node_modules
react
lodash
webpack
public
server
With this new structure we can require files from a fixed point. Hooray!
var ClassNameMixin = require('myApp/mixins/ClassNameMixin');
## Bonus Perks
The real magic of this technique though is that we have created an app structure identical to npm's own node_modules folder.
Say we decide that ClassNameMixin and a bunch of other files would be pretty useful across many projects but these files are tangled up in myApp's business logic.
We could solve this by creating a myTools module just under our custom node_modules
. Then we can slowly refactor code until we have two discreet modules. myApp and myTools.
client
node_modules
myApp
components
component1.jsx
component2.jsx
myTools
mixins
ClassNameMixin.jsx
OtherMixin.jsx
MoreMixins.jsx
node_modules
react
lodash
webpack
public
server
From there it's just a matter of moving myTools to it's own repo and we can run the old npm publish. Once we've run npm install myTools, myApp's references will still match up. Gravy.
client
node_modules
myApp
components
component1.jsx
component2.jsx
node_modules
react
lodash
webpack
mytools
public
server
## A Word of Warning
A lot of people like to outright ignore all node_modules folders from git. You can fix this with some simple reverse ignoring.
node_modules
!client/node_modules