Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One project with multiple package.json files

I'm relatively new to modern JS development and I need help or advice about this situation I'm in.

Situation: We have a React-Typescript-Redux project supporting IE8 (React 0.14). Now we're upgrading to IE11 and React 16 but IE8 should be supported.

Requirement: Reduce project maintenance between browser versions by using different packages and/ or config files for each build.

Problem: From research I made so far it seems impossible to use different package.json files and node_modules folders inside the same project with selected tools: npm, Webpack, React, Redux, Typescript. Yarn seems to support multiple package.json files but we'd like to avoid migrating from npm if possible.

Current project structure:

project_root/   node_modules/   src/     components/     utils/     index.tsx     components.css   index.html   package.json   tsconfig.json   webpack.config.json 

What I thought might work was to introduce IE8 subfolder with its package.json and node_modules folder and then reference that folder for the build task somehow but now I'm oblivious how to tell npm to reference it on build.

Proposed project structure:

project_root/   ie8/    node_modules/    package.json   node_modules/   src/     components/     utils/     index.tsx     components.css   index.html   package.json   tsconfig.json   webpack.config.json 

I tried different things found on web, including resolve.modules: [__dirname + "/ie8/node_modules"] but it seems it doesn't work or I misunderstand what it does because I get Cannot find name 'require' errors on several files and Typescript 2.8.3 is referenced in terminal output instead 2.3.4. Without it, project builds with configuration for IE11.

So, can anybody tell me with certainty it's not possible or offer some guidance? This is the closest answer I found so far but doesn't sound final. Alternatively, can project structure like this support what is required or separating project into two is the best bet?

Thanks in advance.

like image 889
skrunic Avatar asked May 22 '18 15:05

skrunic


People also ask

Can you have more than one package json file?

json file, but there is nothing inherently wrong with multiple package. json files within a repo. Some companies do use mono-repos, for which it would make total sense to have multiple package. json files.

How do I add a Git repository to package json?

To npm install a public project that is hosted on Github, and not the NPM registry, add the Github repo to package. json dependencies using the username/repo#branch-name format. Run npm install and npm will download the project and save it into your /node_modules/ folder.


1 Answers

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! :)

like image 144
skrunic Avatar answered Sep 30 '22 03:09

skrunic