OK, so after some more research I stumbled upon Lerna which mostly allows me to do what I wanted (from what I've seen so far). It requires specific project tree setup, like this:
project_root/
node_modules/
packages/
components/ // Components shared between projects
components/
MyComponent.jsx
index.jsx
legacy/
output/
build.js // React 0.14 build
node_modules/
package.json // project specific dependencies
index.jsx // project specific entry
.babelrc
modern/
output/
build.js // React 16 build
node_modules/
package.json // project specific dependencies
index.jsx // project specific entry
.babelrc
package.json // contains devDependencies shared between projects
lerna.json
webpack.config.js
index.html
Then, in components/index.jsx I specified require commands for different versions based on global variable:
if(PROJECT_SRC == "legacy"){
React = require('../legacy/node_modules/react');
ReactDOM = require('../legacy/node_modules/react-dom');
} else {
React = require('../modern/node_modules/react');
ReactDOM = require('../modern/node_modules/react-dom');
}
Note: This is probably bad practice but the only way at the moment I could include different React versions in the build. I'll have to see what problems arise with this approach after the whole project changes to this model.
In webpack.config.js I configured two exports - one for modern and one for legacy. Each points to a different entry index.jsx file, uses webpack.DefinePlugin to set global variable to "legacy" or "modern", and specifies path to common components module to resolve: ['node_modules', path.resolve(__dirname, 'components')]
webpack.config for a single project output looks something like this:
{
entry: "./packages/legacy/index.jsx",
target: "web",
output:
{
filename: "build.js",
path: __dirname + "/packages/legacy/dist/",
libraryTarget: "var",
library: "lib_name"
},
devtool: "source-map",
resolve: {
extensions: [".js", ".jsx", ".json"],
modules: ['node_modules', path.resolve(__dirname, 'components')]
},
plugins: plugins_legacy,
module: {
loaders: [
{
test: /.jsx?$/,
loader: "babel-loader",
exclude: /node_modules/
}
]
}
}
Feel free to comment or point to problems but I hope this will help somebody in the future! :)