DEV Community

André Castelo
André Castelo

Posted on

CRA 5 + yarn workspaces + shared typescript packages

TL;DR:

  • create-react-app doesn't play nice with shared packages inside a monorepo if you have to compile them (which is the case of my typescript shared types package)
  • craco doesn't work officially with CRA 5, but Craco 7 alpha does, at least it works enough for it to fix this issue.
  • craco config:
const fs = require('fs');
const path = require('path');
const cracoBabelLoader = require('craco-babel-loader');

const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);

module.exports = {
  plugins: [
    {
      plugin: cracoBabelLoader,
      options: {
        includes: [resolveApp('../packages')],
      },
    },
  ],
};
Enter fullscreen mode Exit fullscreen mode

This is a quick one. I've been struggling a lot today to use a shared types package in my monorepo. My structure is the following:

/.git
/app  // react application with CRA 5
  /src
  package.json
/gateway
  /src
  package.json
/packages
  /types
    ...
    package.json
package.json
Enter fullscreen mode Exit fullscreen mode

I'm using:

  • create-react-app 5
  • yarn workspaces
  • typescript

The problem

Here I have my gateway and app both depending on packages/types. While gateway worked fine, app complains that I'm importing files outside of app/src, since this is a limitation in CRA configuration.

The solution

I tried ejecting, but went down a rabbit hole where nothing worked. So I reverted those commits and proceeded with craco@7.0.0-alpha.3. Inside app I ran:

$ yarn add craco@7.0.0-alpha.3
Enter fullscreen mode Exit fullscreen mode

And then I found this answer from @robertcoopercode, and edited to suit my needs:

const fs = require('fs');
const path = require('path');
const cracoBabelLoader = require('craco-babel-loader');

const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);

module.exports = {
  plugins: [
    {
      plugin: cracoBabelLoader,
      options: {
        includes: [resolveApp('../packages')],
      },
    },
  ],
};
Enter fullscreen mode Exit fullscreen mode

Thanks man, you saved my day. Now I'm going to create a ticket to drop create-react-app in favor of next.js, and add it to the next technical debt meeting.

Top comments (0)