Open trusktr opened 6 years ago
We spent a lot of time wrangling with all of the different things that npm
tree flattening can do with having separated prod and dev archetypes -- prod archetypes having dev dependencies in dev archetypes is the real problem.
This bug shows pretty concisely what we were originally up against (and also include Joel coming up with the brilliant module pattern):
We spent a good amount of time trying to discuss how node require resolution works, what these complexities mean for builder, and why we think the module pattern is the best solution at https://github.com/FormidableLabs/builder#node-require-resolution-and-module-pattern
All that said, I'm totally open for (1) updated documentation if README section isn't clear enough, or (2) a different technical solution that can handle correctly resolving dependencies from dev archetypes through tree flattening in either npm or yarn.
Ah, I see, the "module pattern" is specifically really useful if archetype needs to import a dep from archetype-dev.
In my case I'm not using an archetype-dev, and what I found is that for application dependencies, we have a couple more options without having to introduce a plugin, just using plain Webpack config:
We can write stuff like follows for resolve.alias
:
alias: {
'lodash': path.join(path.dirname(require.resolve('<ARCHETYPE>')), 'dependencies', 'lodash'),
},
where files in <ARCHETYPE>/dependencies
contain something like
// <ARCHETYPE>/dependencies/lodash.js
module.exports = require('lodash')
Another thing that works in the Webpack case is just adding the archetype to resolve.modules
:
// <ARCHETYPE>/config/webpack.config.js
const alsoResolveRelativeToArchetype = () => [
// when the ARCHETYPE is `npm link`ed, or in older versions of NPM, loaders will be found in the
// ARCHETYPE's node_modules.
path.relative(CWD, path.join(path.dirname(require.resolve('builder-js-package')), 'node_modules')),
// otherwise, loaders can also be found in the app's node_modules when
// deps are flattened (f.e. when the ARCHETYPE is not `npm link`ed).
'node_modules',
]
// ...
resolve: {
modules: alsoResolveRelativeToArchetype(),
},
resolveLoader: {
modules: alsoResolveRelativeToArchetype(),
},
That will cause dependencies of the ARCHETYPE to have precedence over app dependencies, so lodash
can be found there first if it isn't installed by the app.
Sidenote, despite not having a dev
archetype, I see these (seemingly harmless) errors in the console.
I wonder if there's alternatives to the
module.exports = require
trick. At first sight, it's strange and not clear what that does, as no one ever does that sort of thing.Are there any alternatives that may have even been considered (even if they didn't work)?