react-workspaces / react-workspaces-playground

āš›ļø šŸˆ Zero Config Create-React-App Monorepos with Yarn Workspaces, Lerna and React Storybook.
https://react-workspaces.github.io/react-workspaces-playground/
764 stars 128 forks source link

How to use with react-app-rewired? #9

Closed fgiarritiello closed 4 years ago

fgiarritiello commented 5 years ago

Hi,

I'm using "@react-workspaces/react-scripts": "3.0.0-alpha-04" and "react-app-rewired": "2.1.3" and I'm getting the following error when starting the app:

Error: Cannot find module 'react-scripts/package.json' at Function.Module._resolveFilename (module.js:548:15) at Function.resolve (internal/module.js:18:19)

Any idea how to fix this?

F1LT3R commented 5 years ago

Do you have a repo with your setup that I can look at?

fgiarritiello commented 5 years ago

I don't have a repo but I can show you the project setup and some of the main dependencies.

/packages
   |---/ReactApp
   |       |--- package.json
   |---/UI-Library-with-storybook
   |       |--- package.json
   |       |--- .babelrc
|--- package.json
|--- lerna.json

ReactApp / package.json

{
  "name": "React App",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "@react-workspaces/react-scripts":"2.1.1-workspaces-09",
    "UI-Library": "1.0.0",
    "react-app-rewire-less": "2.1.3",
    "react-app-rewire-styled-components": "3.0.2",
    "react-router-dom": "4.3.1"
  },
  "devDependencies": {
    "cross-env": "5.2.0",
    "customize-cra": "0.2.13",
    "react-app-rewired": "2.1.3"
  },
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test --env=jsdom"
  },
  "browserslist": {
    "development": [
      "last 2 chrome versions",
      "last 2 firefox versions",
      "last 2 edge versions"
    ],
    "production": [
      ">0.25%",
      "not op_mini all",
      "ie 11"
    ]
  }
}

UI-library / package.json

{
  "name": "UI-Library",
  "version": "1.0.0",
  "private": true,
  "description": "UI Framework",
  "main": "dist/index.js",
  "license": "ISC",
  "dependencies": {
    "antd": "3.18.2"
  },
  "devDependencies": {
    "@babel/cli": "7.1.2",
    "@babel/core": "7.1.2",
    "babel-preset-react-app": "5.0.3",
    "@storybook/addon-actions": "3.4.8",
    "@storybook/addon-backgrounds": "3.4.8",
    "@storybook/addon-console": "1.0.4",
    "@storybook/addon-info": "3.4.8",
    "@storybook/addon-knobs": "3.4.8",
    "@storybook/addon-notes": "3.4.8",
    "@storybook/addon-viewport": "3.4.8",
    "@storybook/react": "4.0.0-alpha.14",
    "babel-core": "6.26.3",
    "babel-plugin-import": "1.8.0",
    "babel-plugin-styled-components": "1.5.1",
    "babel-plugin-transform-class-properties": "6.24.1",
    "babel-preset-env": "1.7.0",
    "babel-preset-react": "6.24.1",
    "babel-preset-stage-3": "6.24.1",
    "css-loader": "2.0.0",
    "less": "2.7.2",
    "less-loader": "4.0.5",
    "storybook-addon-jsx": "5.3.0",
    "style-loader": "0.21.0",
    "url-loader": "1.0.1"
  },
  "scripts": {
    "build": "babel ./ --out-dir ./dist --delete-dir-on-start --copy-files",
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "NODE_ENV=development yarn build --watch --source-maps",
    "start-story": "start-storybook -p 3001 -s ./public -c .storybook"
  }
}

/package.json

{
    "name": "center-suite-clients",
    "private": true,
    "workspaces": [
        "packages/*"
    ],
    "scripts": {
        "init": "lerna init --independent --exact",
        "boot": "lerna bootstrap",
        "start": "cd packages/center-connect-web && npm run start"
    },
    "dependencies": {
        "prop-types": "15.7.2",
        "styled-components": "4.2.0"
    },
    "devDependencies": {
        "babel-eslint": "10.0.1",
        "babel-loader": "8.0.5",
        "eslint": "5.16.0",
        "eslint-config-airbnb": "17.0.0",
        "eslint-config-airbnb-base": "13.0.0",
        "eslint-config-prettier": "2.9.0",
        "eslint-config-react-app": "2.1.0",
        "eslint-import-resolver-webpack": "0.10.1",
        "eslint-plugin-flowtype": "2.50.0",
        "eslint-plugin-import": "2.13.0",
        "eslint-plugin-jsx-a11y": "6.1.0",
        "eslint-plugin-prettier": "2.6.2",
        "eslint-plugin-react": "7.10.0",
        "lerna": "3.13.0",
        "prettier": "1.13.7"
    }
}
Remimstr commented 5 years ago

I use craco instead of react-app-rewired (tried both but only craco worked, I can't remember exactly why).

My configuration consists of having a craco.config.js at the root level of my repo:

craco.config.js

const path = require("path");

module.exports = {
  reactScriptsPath: path.join(
    __dirname,
    "node_modules/@react-workspaces/react-scripts"
  )
};

Note that I override the react-scripts path to point to the F1LT3R's package in the root level node_modules directory (it'll be there because of yarn workspace hoisting).

Then in each of my apps, I have the following scripts:

app/myApp/package.json

scripts: {
  start: craco start --config ../../craco.config.js,
  build: craco build --config ../../craco.config.js,
  etc.
}

I don't like having to do relative references to my shared configuration file but at least I can run my apps! Hope that helps :)

F1LT3R commented 5 years ago

@fgiarritiello is your Lerna.json really in your packages dir?

fgiarritiello commented 5 years ago

@F1LT3R my bad. The lerna.json is in the root folder. I updated the above comment. Thanks

fgiarritiello commented 5 years ago

I'll try Remimstr's solution when I have time. Right now I'm just stuck with using "react-scripts": "2.0.0-next.a671462c" since it still supported monorepos

F1LT3R commented 5 years ago

Out off interest, why are you using rewired/craco? What does that get you?

fgiarritiello commented 5 years ago

rewired allows you to override, without ejecting, the babel and webpack configurations that CRA creates out of the box. In my case I need to override the configs so that I can use the AntDesign UI library.

Remimstr commented 5 years ago

The reason I override CRA with craco is for the same reason as @fgiarritiello (AntDesign)

F1LT3R commented 5 years ago

I would think it is possible to extend react-workspaces to allow the same kind of overrides. I'm just not sure that I want to do the work of supporting something other than vanilla CRA.

I'm not sure if this project should try to support all possible tools that rewire CRA, that could end up being a huge headache; or maybe it's easy. I'd have to have the time to use craco/rewired to really get a feel for what they were doing and how easy that was to override - and I'm not sure I can commit to that right now.

Supporting Ant Design however, that seems more reasonable.

Are you only using craco/rewired to support Ant, or are there other things you are also using these for?

@Remimstr , @fgiarritiello ? ^^

fgiarritiello commented 5 years ago

@F1LT3R I understand your concern. However supporting either rewired or craco will allow more flexibility in expanding the default configuration with different libraries. If you just support Antd then you will restrict this library to people that only use Antd but there might be other frameworks that need a different type of config. In addition, I use rewired to change configuration for styled-components. Here is the config-overrides.js file

const { injectBabelPlugin } = require('react-app-rewired');
const rewireStyledComponents = require('react-app-rewire-styled-components');
const rewireLess = require('react-app-rewire-less');
const themes = require('..i/themes');

/* config-overrides.js */
module.exports = function override(config, env) {
  config = injectBabelPlugin(
    ['import', { libraryName: 'antd', style: true }],
    config,
  );

  config = rewireLess.withLoaderOptions({
    javascriptEnabled: true,
    modifyVars: themes(),
  })(config, env);

  config = rewireStyledComponents(config, env, {
    displayName: env !== 'production',
  });

  return config;
};
Remimstr commented 5 years ago

@F1LT3R First of all I should probably clarify that Antd should just work out of the box with CRA, but there are 2 very compelling reasons to override the default configurations:

1) adding custom theme styling 2) making components import on demand (through use of a babel plugin)

To accomplish either of these tasks, you need to use some override mechanism (react-app-rewired, craco, etc.). The official docs suggest using react-app-rewired: https://ant.design/docs/react/use-with-create-react-app

Unfortunately, I don't think it's quite as simple as just supporting Antd, however if you were to add support react-app-rewired, that should generally solve this problem for anyone just using Antd and following their official guide.

Personally I completely understand your hesitation and I'm fine to continue using craco.

F1LT3R commented 5 years ago

Am I right in thinking that Rewired would be preferred over Craco if only one had to be supported?

fgiarritiello commented 5 years ago

For CRA +2.0 the docs actually suggest that we use https://github.com/arackaf/customize-cra. Iā€™m still using rewired because the version of CRA Iā€™m using is < 2.0

Remimstr commented 5 years ago

Am I right in thinking that Rewired would be preferred over Craco if only one had to be supported?

I think that is a reasonable assumption, craco seems much less popular than rewired.

@fgiarritiello customize-cra says right in the docs that it depends on react-app-rewired, looks like you won't be escaping it anytime soon ;)

fgiarritiello commented 5 years ago

By the way I was able to use monorepo with CRA v3 using the following solution https://github.com/facebook/create-react-app/issues/1333#issuecomment-505718147

F1LT3R commented 5 years ago

Rather than support any/all of the following:

Would it be better to just support Ant Design out of the box?

ghost commented 4 years ago

Any update on this issue? šŸ˜£ i want use antd šŸ˜£

abrkn commented 4 years ago

Has anyone managed to get react-app-rewired to work?

abrkn commented 4 years ago

Some work seems to be going on here: https://github.com/with-heart/react-app-rewire-workspaces

F1LT3R commented 4 years ago

@abrkn - are people trying to get all of rewired working? Or are people only trying to get this working with Ant Design?

F1LT3R commented 4 years ago

Ok, I've had the chance to look at Ant Design. It's great!

I was successful in adding AntD to React Workspaces Playground locally, but I think it would be better to support react-app-rewired out of the box.

F1LT3R commented 4 years ago

@fgiarritiello - I think react-app-rewired will need to support Yarn Workspaces.

The issue with finding react-scripts/package.json is that React App Rewired assumes react-scripts is a real directory. Whereas Yarn Workspaces will hoist react-scripts by default.

It may be possible to set react-scripts in the Yarn Workspaces no-hoist object to make this work. It's not an ideal situation, but it "should" work.

F1LT3R commented 4 years ago

So after updated my root package.json like so:

{
  "workspaces": {
    "packages": [
      "packages/apps/*",
      "packages/components",
      "packages/storybook"
    ],
    "nohoist": [
      "packages/apps/**/webpack-dev-server",
      "**/babel-loader",
      "**/babel-jest",
      "**/@react-workspaces/react-scripts"
    ]
  },}

... my @react-workspaces/react-scripts does appear in the packages/apps/app-one/node_modules/ directory.

However, it still fails with the same react-scripts/package.json error, because there is no react-scripts directory.

Again, I would need to submit a PR to react-app-rewired to make this work, but this seems messy as the Yarn Workspaces resolution code would have to live in two libraries (react-workspaces and react-app-rewired).

What might be better is to find a way to over-ride react-app-rewired scripts from within react-workspaces. I am not sure how that would work yet.

F1LT3R commented 4 years ago

Luckily react-app-rewired has --custom-scripts and process.env.REACT_SCRIPTS_VERSION (which are the same thing) as well as --config-overrides. This should hopefully let us specify @react-workspaces/react-scripts as the ~"custom scripts version" that should allow us to bootstrap create-react-app with the Yarn Workspaces compatible Babel Loader configuration.

... all this to say ...

I am able to yarn start apps in the react-workspaces-playground repo using react-app-rewired with...

1) The following Yarn Workspaces config in the root package.json:

{
  "workspaces": {
    "packages": [
      "packages/apps/*",
      "packages/components",
      "packages/storybook"
    ],
    "nohoist": [
      "packages/apps/**/webpack-dev-server",
      "**/babel-loader",
      "**/babel-jest",
      "**/@react-workspaces/react-scripts"
    ]
  }
}

2) This packages/apps/app-one/package.json

{
  "dependencies": {
    "@react-workspaces/react-scripts": "^3.0.1-alpha-07",
    "react-app-rewired": "^2.1.5",
  },
  "scripts": {
    "start": "react-app-rewired start"
  }
}

3) The following command:

# where pwd=${root}/packages/apps/app-one/
yarn start --scripts-version $(pwd)/node_modules/@react-workspaces/react-scripts
F1LT3R commented 4 years ago

I now have Ant Design working with react-app-rewired and customize-cra as per their setup instructions:

Only the following two lines are used in App.js to show the Date Picker:

import {DatePicker} from 'antd'
<DatePicker />

This means that Ant Design's automatic style imports are working.

The config-overrides.js looks like this:

const {override, fixBabelImports} = require('customize-cra');

module.exports = override(
    fixBabelImports('import', {
        libraryName: 'antd',
        libraryDirectory: 'es',
        style: 'css'
    })
);

You can test this out on the following branch: https://github.com/react-workspaces/react-workspaces-playground/tree/ant-design-compat

Here is a screenshot of the Data Picker popped open in the Playground.

CleanShot 2019-12-25 at 21 10 36@2x
F1LT3R commented 4 years ago

@fgiarritiello, @Remimstr, @mandri222, @abrkn - I have a PR for you: https://github.com/react-workspaces/react-workspaces-playground/pull/21