One project with multiple package.json files

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! 🙂

Leave a Comment