Reputation: 14399
I am experementing a bit with react and browserify and have these wishes:
I have managed to do the things described above but I ran into this specific situation:
In some places of my code I want to use react with addons and as such require it like this: var React = require('react/addons)
. I don't do this in all parts of my code and it is not done in 3rd party dependencies such as react-router. This seems to create a conflict. Either the browserified bundle will only be available through var React = require('react/addons)
which breaks 3rd party dependencies, or I will have to bundle react both with or without addons which menas that react is bundled and downloaded twice.
I tried to use aliasify and make react
an alias for react/addons
but I couldn't make it work. Should this be possible?
Another acceptable solution would be to bundle just the addons in a separate bundle and through that make both react
and react/addons
available through calls to require
. Is any of this possible?
Addition As a comment to the first comment by BrandonTilley, this is not just applicable to React and addons. Lodash also comes with a number of different distributions and I would like to be able to choose the version to use in my webapp in this case as well.
Upvotes: 7
Views: 1765
Reputation: 92190
Notice that what you want to achieve is documented here: Browserify partitionning
I'm packaging my app in 2 parts: appLibs.js
and app.js
.
I've done this for caching too but I choose to put all the code that does not change often in a single bundle instead of splitting it like you want, but you can use the same trick.
Here's the code that might interest you:
var libs = [
"react",
"react/addons", // See why: https://github.com/substack/node-browserify/issues/1161
... other libs
];
gulp.task('browserify-libs', function () {
var b = browserify(...);
libs.forEach(function(lib) {
b.require(lib);
});
return b.bundle().......
});
gulp.task('browserify',['browserify-libs'],function () {
var b = browserify(...);
libs.forEach(function(lib) {
b.external(lib);
});
return b.bundle().......
});
This way, React is only bundled once in appLibs.js
and can be required inside app.js
using both react
and react/addons
If you really want to bundle your libs in separate files, bundle then with b.require("myLib")
, but in this case be sure to check that the libraries do not have direct dependencies. If a lib to bundle has a dependency in React, this means that lib will be packaged in the bundle, potentially leading to multiple bundles having React inside them (and making weird failures at runtime). The library should rather use peerDependencies
so that b.require
does not try to package these dependencies
Upvotes: 2
Reputation: 14399
Thanks for all suggestions but the solution I have chosen is a "shim" if that is the correct term. Looks like this:
module.exports = require('react/addons');
Now, either if react or react/addons is required I get react/addons
Upvotes: 0
Reputation: 1622
Sounds like the perfect use case for factor-bundle
.
From the browserify handbook:
factor-bundle splits browserify output into multiple bundle targets based on entry-point. For each entry-point, an entry-specific output file is built. Files that are needed by two or more of the entry files get factored out into a common bundle.
Upvotes: 0