Nx: styled-components required dep after upgrading to nx 9.2.2

Created on 10 Apr 2020  路  10Comments  路  Source: nrwl/nx

Expected Behavior

I can run the nx build command without npm installing styled-components package.

Current Behavior

What is the current behavior?
After upgrading from nx 9.0.0 to nx 9.2.2, I can't build my react app. I get the following msg

ERROR in ./app/App.jsx
Module not found: Error: Can't resolve 'styled-components' in 'foo/apps/bar/src/app'

We use emotion and never relied on styled-components.

When I npm installed styled-components, then the build command works again.

Steps to Reproduce

Please provide detailed steps for reproducing the issue.

update to 9.2.2 and run nx build <appname>

repro needed react

Most helpful comment

This will be patched in the next version. Moving beyond that, I think we should actually generate the .babelrc for each project so overriding options is more straighforward.

All 10 comments

i think this might be related to this PR https://github.com/nrwl/nx/pull/2605

We have found a related issue where #2605 definitely adds a regression to our app. Our app no longer detects emotion and tries to use styled-components instead. We've been able to work around this issue by removing the plugins added here (https://github.com/nrwl/nx/commit/5cdf372#diff-e48573255298e2cfadc0bc36491a5ed2R11) from our custom webpack config.

I ran into this issue, too, and also had to use a custom webpack config to remove the plugins. In my app, I noticed that styled-components code was actually making it into the bundled output, even though I only use emotion.

@epikhighs Sorry about the breakage. This will be fixed in a patch release soon!

@epikhighs @brianmcd Do you happen to have a repo I can check out?

I've tried reproducing it here but the build didn't fail for me: https://github.com/jaysoo/emotion-test-922

I don't have a public repo i can share @jaysoo , but for my project, we are modifying babel-loader in our custom webpack config. So maybe the ordering of the babel plugins or babel presets maybe changes things? I noticed in your sample repo, you do not have a custom webpack config.

```
// in our custom webpack file
const { updateBabelOptions } = require('@nrwl/react/src/utils/babel-utils');

// Add React-specific configuration
function getWebpackConfig(config) {
const idx = config.module.rules.findIndex(r => r.loader === 'babel-loader');
const babelRuleOptions = config.module.rules[idx].options;
babelRuleOptions.presets.push('@emotion/babel-preset-css-prop');
babelRuleOptions.plugins.push(['import', {libraryName: 'antd'}]); // babel-plugin-import

updateBabelOptions(babelRuleOptions);

// remove problematic plugins manually
babelRuleOptions.plugins = babelRuleOptions.plugins.filter(x => {
if (typeof x === 'string' && x.indexOf('babel-plugin-emotion') >= 0) {
return false;
} else if (Array.isArray(x) && x[0].indexOf('babel-plugin-styled-components') >= 0) {
return false;
}
return true;
});
...
}```

@jaysoo - Thanks for looking into this.

Here's a repo: https://github.com/brianmcd/nx-emotion-bug. I generated the project with the latest Nx and made the changes in app.tsx.

I think using emotion's css prop instead of its styled API is triggering the behavior (https://emotion.sh/docs/css-prop#jsx-pragma).

Trying to build the project as-is results in: Module not found: Error: Can't resolve 'styled-components'. If you actually install styled-components in that repo, you'll see this in the bundled output, even though the code isn't using styled-components:

/* harmony import */ var styled_components__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! styled-components */ "../../../node_modules/styled-components/dist/styled-components.browser.esm.js");

In my real project, I spliced out babel-plugin-styled-components and it fixed it for me:

function removeStyledComponentsPlugin(nxConfig) {
  const options = getBabelLoaderOptions(nxConfig);
  const idx = options.plugins.findIndex((p) => {
    return Array.isArray(p) && p[0].includes('babel-plugin-styled-components');
  });
  if (idx === -1) {
    throw new Error();
  }
  options.plugins.splice(idx, 1);
}

function getBabelLoaderOptions(config) {
  const idx = config.module.rules.findIndex((r) => r.loader === 'babel-loader');
  if (idx === -1) {
    throw new Error();
  }
  return config.module.rules[idx].options;
}

@brianmcd Thanks! I guess my tests didn't have use the right API to cause breakages. I'm going to look at adding in the styled-component and emotion specific plugins (for SSR) only if they are used.

This will be patched in the next version. Moving beyond that, I think we should actually generate the .babelrc for each project so overriding options is more straighforward.

Thanks a ton, @jaysoo!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

olakara picture olakara  路  3Comments

SWGeekPD picture SWGeekPD  路  3Comments

zpydee picture zpydee  路  3Comments

zachnewburgh picture zachnewburgh  路  3Comments

joelmuskwe picture joelmuskwe  路  3Comments