2

Currently in the process of migration Material-UI from v0 to v3, I'm facing multiple issues of files importing dependencies from the wrong location.

Let's take the @babel/runtime dependency as an example.

Below are extracts of my package.json and yarn.lock files:

"dependencies": {
  "@material-ui/core": "3.0.0",
  "@material-ui/icons": "3.0.0",
  "react-swipeable-views": "0.12.16",
  "react-swipeable-views-utils": "0.12.16",
},
"devDependencies": {
  "babel-cli": "6.26.0",
  "babel-core": "6.26.3",
  "babel-loader": "7.1.5",
  "babel-runtime": "6.26.0",
  "babel-regenerator-runtime": "6.5.0",
},
"@material-ui/core@3.0.0":
  version "3.0.0"
  dependencies:
    "@babel/runtime" "7.0.0-rc.1"
"@material-ui/icons@3.0.0":
  version "3.0.0"
  dependencies:
    "@babel/runtime" "7.0.0-rc.1"
react-event-listener@^0.6.0, react-event-listener@^0.6.2:
  version "0.6.3"
  dependencies:
    "@babel/runtime" "7.0.0-rc.1"
react-swipeable-views-core@^0.12.16:
  version "0.12.16"
  dependencies:
    "@babel/runtime" "7.0.0-beta.42"
recompose@^0.28.2:
  version "0.28.2"
  dependencies:
    "@babel/runtime" "7.0.0-beta.56"

@babel/runtime@7.0.0-beta.42":
  version "7.0.0-beta.42"
  dependencies:
    core-js "^2.5.3"
    regenerator-runtime "^0.11.1"
"@babel/runtime@7.0.0-beta.56":
  version "7.0.0-beta.56"
  dependencies:
    regenerator-runtime "^0.12.0"
"@babel/runtime@7.0.0-rc.1":
  version "7.0.0-rc.1"
  dependencies:
    regenerator-runtime "^0.12.0"

Also sharing a chunk of my webpack config since I have an hunch it might be the culprit here:

rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: "babel-loader",
    query: {
      presets: [["es2015", {loose: true, modules: false}], "react", "stage-0"],
      plugins: ["transform-decorators-legacy"],
      cacheDirectory: true,
    },
  },
],
entry: [
  "babel-regenerator-runtime",
  path.resolve(__dirname, sourcePath, `${jsFilename}.js`),
],

And my babelrc:

{
  "presets": [
    "es2015",
    "react",
    "stage-0",
    "flow"
  ],
  "plugins": [
    "transform-decorators-legacy",
    ["transform-runtime", {
      "polyfill": false,
      "regenerator": true
    }],
    ["babel-plugin-root-import", {
      "rootPathSuffix": "src"
    }]
  ]
}

All my webpack errors refer to a getPrototypeOf file missing in the @babel/runtime/helpers directory:

ERROR in ./node_modules/@material-ui/core/styles/withTheme.js
Module not found: Error: Can't resolve '@babel/runtime/helpers/getPrototypeOf' in '/project/node_modules/@material-ui/core/styles'    
 @ ./node_modules/@material-ui/core/styles/withTheme.js 20:46-94
 @ ./node_modules/@material-ui/core/styles/index.js
 @ ./src/components/Root.js
 @ ./src/app.js
 @ multi babel-regenerator-runtime ./src/app.js

ERROR in ./node_modules/react-event-listener/dist/react-event-listener.cjs.js
Module not found: Error: Can't resolve '@babel/runtime/helpers/getPrototypeOf' in '/project/node_modules/react-event-listener/dist'   
 @ ./node_modules/react-event-listener/dist/react-event-listener.cjs.js 10:38-86
 @ ./node_modules/@material-ui/core/Popover/Popover.js
 @ ./node_modules/@material-ui/core/Popover/index.js
 @ ./src/components/Header/AnonymousMenu.js
 @ ./src/components/Header/index.js
 @ ./src/components/ListeningRoute.js
 @ ./src/components/Root.js
 @ ./src/app.js
 @ multi babel-regenerator-runtime ./src/app.js

And if I search for the file in node_modules, all directories except the root one contain the file:

$ for dir in $(find node_modules -name 'runtime'); do ls $dir/helpers/getPrototypeOf.js; done
node_modules/recompose/node_modules/@babel/runtime/helpers/getPrototypeOf.js
node_modules/@material-ui/icons/node_modules/@babel/runtime/helpers/getPrototypeOf.js
node_modules/@material-ui/core/node_modules/@babel/runtime/helpers/getPrototypeOf.js
node_modules/react-event-listener/node_modules/@babel/runtime/helpers/getPrototypeOf.js
ls: cannot access 'node_modules/@babel/runtime/helpers/getPrototypeOf.js': No such file or directory

node modules are supposed to search dependencies recursively so we can have multiple versions of a package used concurrently without breaking the project, yet in this case they are actually searching them in the root node_modules/ directory.

Other confusion comes from the fact that we still use babel v6 in our project, yet @babel gets installed in project/node_modules.

Can someone explain why this behavior happens, if this is a yarn-only issue, and how to fix this issue ? Or might it be something related to webpack ?

I wanted to have concurrent versions of Material-ui v0 and v3 for some transition period, but the current solution is a hard migration to v3 (as well as migrating babel from v6 to v7). This is really blocking us for the migration.

Note: cp node_modules/@material-ui/core/node_modules/@babel/runtime/helpers/getPrototypeOf.js node_modules/@babel/runtime/helpers removes all webpack errors...

tk421
  • 5,775
  • 6
  • 23
  • 34
Adrien Lemaire
  • 1,744
  • 2
  • 20
  • 29

1 Answers1

2

In webpack there is an option called resolve. You will have to set the resolve option so that @material-ui will use their own node_modules. Currently @material-ui imports dependencies using the upper most node_modules which you have installed through npm or yarn.

In your webpack config include

module.exports = {
    ...

    resolve : {
        modules : ['node_modules']
    },

    ...
}

By doing so webpack will look at node_modules in relative directories.

Wesgur
  • 3,140
  • 3
  • 18
  • 28
  • Indeed, my webpack config had resolve: { extensions: [".js"], modules: [path.resolve(__dirname, "./node_modules")], }, Which forced resolution from the root node_modules. Modifying it to your code resolved the issue. Many thanks @Wesgur! – Adrien Lemaire Aug 29 '18 at 00:40
  • 1
    No problem :) Ran into the same issue but no where to find a solution. – Wesgur Aug 29 '18 at 00:42