hannad rehman
hannad rehman

Reputation: 4331

babel-loader not transpiling packages in node_modules even after specifying in exclude block to ignore the package (lerna)

So I am trying out monorepo design with lerna for our react applications. the idea is to create one repo which will have all the react projects as lerna packages as well as some common modules/components which are shared across the applications.

now all these common modules/components are es6 modules. which are not transpiled. because there is continuous development going on the common modules as well. and if we build/transpile them I am sure react HMR will not work after that (a wild guess). following is my directory structure

package.json lerna.json |--packages |--common |--react-app |--constants |--utilities

common contains common react elements like table,accordion etc. which are exported as default es6 modules.

react-app imports common as dependency. react-app has webpack build configuration set.

now when i import common module into my react-app babel transform fails with this error

Button.component.jsx 7:19
Module parse failed: Unexpected token (7:19)
You may need an appropriate loader to handle this file type.
| const { Search } = Input;
| class TextBoxWithButton extends React.Component {
>   static propTypes = {
|     placeholder: PropTypes.string.isRequired,
|     onAction: PropTypes.func.isRequired,
 @ ./src/App/Modules/Todo/Components/Header/Header.component.jsx 10:0-111 16:25-41
 @ ./src/App/Modules/Todo/Todo.component.jsx
 @ ./src/App/Router/index.jsx
 @ ./src/App/Layout/index.jsx
 @ ./src/App/index.jsx
 @ ./src/App.hot.js
 @ ./src/index.jsx

which means babel-loader is unable to parse and transpile whats in the node_nodules folder which makes sense because all dependencies are expected to be already transpiled. but not always. if you manage local dependencies you cannot keep them build all the time (that's what i think)

now I have found some solutions online that enable 1bable-loader not to exclude node_modules or ignoring @mypackagein exclude regex. but nothing is working in my case.

here is what i have tried so far.

  1. remove exlucde: /node_modules/ from babel-loader => not working
  2. use require.resolve('babel-loader') => not working
  3. add resolve.symlinks= false.
  4. add resolve.modules='node_modules' or path.resove(__dirname,'node_modules') => not working
  5. add packages path to babel-loader include include: [srcPath, lernaPackagesPath],

nothing seem to work. is there something that i am missing ? here is the link to my git test repo.

Upvotes: 3

Views: 3663

Answers (1)

hannad rehman
hannad rehman

Reputation: 4331

babel-loader by default will not transpile anything that is in node_modules. you can explicitly say what to transpile in node_modules but after @babel7.0.0 that doesn't seem to work either. there is also a scope of .babelrc which was introduced in @babel7.0.0.

according to the research i did in under normal circumstances node_modules expect to have transpiled commonjs or umd modules. which can be imported by any application. in my case my packages/components where all es6 modules which needed to be transpiled. and my webpack build was failing because babel-loader was simply ignoring them.

so i decided to use @babel/cli to transpile each package where my components reside i had to add .babelrc along with other configurations to my component packages and build them with @babel/cli

here is the scripts in my package.json

"scripts": {
    "start": "babel src --watch --out-dir dist --source-maps inline --copy-files --ignore spec.js,spec.jsx"
  },

and my package.json looks something like this after that

{
  "name": "@pkg/components",
  "version": "1.0.1",
  "description": "a repository for react common components. may or may not be dependent on elements",
  "main": "dist/index.js",
  "author": "hannad rehman",
  "license": "MIT",
  "scripts": {
    "start": "babel src --watch --out-dir dist --source-maps inline --copy-files --ignore spec.js,spec.jsx"
  },
  "dependencies": {
    "@pkg/constants": "^1.0.1",
    "@pkg/elements": "^1.0.1"
  },
  "peerDependencies": {
    "prop-types": "^15.6.2",
    "react": "^16.4.2",
    "react-router-dom": "^4.3.1"
  }
}

with this approach. all of my common packages will be unit tested, linted and built before any application can import them. babel has a watch mode which will make sure transpilation happens always when a change occurs.

lastly and most importantly react HMR works as expected.

UPDATE

the above solution definitely works but after months i changed it by using include property in the babel loader

{
      test: /\.js(x?)$/,
      include: [/node_modules\/@pkg/],
      use: [
        'thread-loader',
        {
          loader: 'babel-loader',
          options: {
            cacheDirectory: true,
            configFile: path.resolve(
              __dirname,
              '../../../../',
              `${env.appConfig.folderSrc}/babel.config.js`,
            ),
          },
        },
      ],
    }

Upvotes: 4

Related Questions