arackaf / customize-cra

Override webpack configurations for create-react-app 2.0
MIT License
2.78k stars 268 forks source link

πŸ“ŒπŸ“Œ Breaking change: `css-loader@^3.0.0` (+`addLessLoader`) #253

Open Anish-Agnihotri opened 4 years ago

Anish-Agnihotri commented 4 years ago

As part of our 1.0 release, we need to support css-loader@^3.0.0 which was added to create-react-app in #7876.

Across various issues (#231, #242, #243), the new css-loader configuration format (a switch from a boolean to options for lessOptions) has caused errors during the run and build process of customize-cra.

With version 1.0, we have introduced a fix for this, although it is a breaking change, and will require maintainers to alter their customizers configurations.

In particular, configuration options for the addLessLoader customizer will now be nested in a lessOptions object, as so:

Before:

addLessLoader({
  javascriptEnabled: true,
  modifyVars: { '@primary-color': '#A80000' },
}),

Now:

addLessLoader({
  lessOptions: {
    javascriptEnabled: true,
    modifyVars: { '@primary-color': '#A80000' },
  },
}),

For additional information, please see the revised docs.

If you run into issues migrating to the 1.0 release, please report the issue, and fall-back to the 0.9.1 release until I can diagnose and help you resolve your issue.

mjfwebb commented 4 years ago

I updated to 1.0 and changed included lessOptions: { as advised. This caused all .less files to stop loading. I removed the nested lessOptions: { object and it works fine.

My package-lock.json currently shows I am indeed on 1.0.0:

"customize-cra": {
  "version": "1.0.0",
  "resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz",
  "integrity": "sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==",
  "requires": {
    "lodash.flow": "^3.5.0"
  }
},

And inside the node_modules/customize-cra package.json:

{
  "_from": "customize-cra@latest",
  "_id": "customize-cra@1.0.0",

Any suggestions?

Anish-Agnihotri commented 4 years ago

@mjfwebb Thanks for reporting thisβ€”that is odd, but I will take a look at it tonight and get back to you.

Please use without the nested lessOptions for the time being so that you can continue to use your .less files.

iwan-uschka commented 4 years ago

I ran into the same issue as @mjfwebb after updating customize-cra from version 0.8.0 to 1.0.0 and updating lessOptions like described in https://github.com/arackaf/customize-cra/issues/253#issue-626797945:

alidationError: Invalid options object. Less Loader has been initialized using an options object that does not match the API schema.
 - options has an unknown property 'javascriptEnabled'. These properties are valid:
   object { lessOptions?, prependData?, appendData?, sourceMap?, implementation? }

After upgrading my less-loader from version 5.0.0 to 6.1.0 the changes mentioned in https://github.com/arackaf/customize-cra/issues/253#issue-626797945 were necessary to be implemented and everything worked again.

I am using

...
"customize-cra": "^1.0.0",
"less": "^3.11.3",
"less-loader": "^6.1.0",
"react-app-rewired": "^2.1.6",
"react-scripts": "^3.4.1",
...

so i updated lessOptions in my config-overrides.js.

mjfwebb commented 4 years ago

Just wanted to confirm that my previous experience of it failing was due to my still using less-loader version 5.0.0, just as @iwan-uschka described.

After upgrading less-loader to the latest version (7.0.1 as of writing this), I was required to add lessOptions: { as originally posted.

I suggest specifically mentioning this as a caveat or gotcha.

lamdoann commented 3 years ago

How can I resolve background-image: url('public/assets/01.png') on the less files?

iwan-uschka commented 3 years ago

Hi @lamdoann, i just gave it a try at put an image at /public/images/test.png. I was able to reference it in a less file like

background: url(/images/test.png);

The background image was loaded correctly in the browser. In dev tools i can see, that the url has been adjusted:

background: url(../../../images/test.png);

Hope this helps.

lamdoann commented 3 years ago

Hi @iwan-uschka, thanks for your reply. I got this error when loading images from public folder. Module not found: You attempted to import ../public/assets/hand-map-02.png which falls outside of the project src/ directory. Relative imports outside of src/ are not supported.

iwan-uschka commented 3 years ago

@lamdoann Can you please share some code? How does your less file look like? How do you reference the image? I guess your image is located in /public/images/ right?

lamdoann commented 3 years ago

Yes, I put images in /public/assets folder. I cannot access /public/assets folder on less files. It works when I put assets in /src.

iwan-uschka commented 3 years ago

Well, like i said, it would help if you can show some code. You haven't said anything yet about how you reference your assets inside your less files.

I am using craco to customise create-react-app. The interesting part of my .cracorc.js looks like this:

const CracoLessPlugin = require('craco-less');

module.exports = function ({ env }) {
  return {
    style: {
      css: {
        loaderOptions: {
          url: false,
        },
      },
    },
    plugins: [
      {
        plugin: CracoLessPlugin,
        options: {
          lessLoaderOptions: {
            lessOptions: {
              javascriptEnabled: true,
            },
          },
        },
      }
    ]
  };
};

By setting css loader option url to false i am able to reference assets normally in my css (which means i can reference them normally in my less or scss files) and these assets won't be part of the bundle. This way you can reference files outside of the src directory. At least that is how I understood it :) A discussion about this issue is going on at https://github.com/facebook/create-react-app/issues/9870.

Maybe you can add some configuration into your config-overrides.js like describe in https://github.com/arackaf/customize-cra/blob/master/api.md#addlessloaderloaderoptions:

const { override, addLessLoader } = require("customize-cra");

module.exports = override(
  addLessLoader({
    cssLoaderOptions: {
      url: false
    }
  })
);

I couldn't find any dedicated documentation about customizing css loader options outside less loader scope.

lamdoann commented 3 years ago

Here is my config-overrides.js ` const { override, addLessLoader } = require('customize-cra');

module.exports = override( addLessLoader({ lessOptions: { javascriptEnabled: true, cssLoaderOptions: { url: false } }, }) ); `

And my index.less .bg { width: 100%; height: 400px; background-image: url('/public/assets/hand-map-02.png'); }

iwan-uschka commented 3 years ago

Thx! I guess this doesn't work :) If that's the case we have to wait for others to help out. Sorry..

iwan-uschka commented 3 years ago

Ah, please have a look again.

Yours

const { override, addLessLoader } = require("customize-cra");

module.exports = override(
  addLessLoader({
    lessOptions: {
      javascriptEnabled: true,
      cssLoaderOptions: {
        url: false
      },
    },
  })
);

is not correct. There is no lessOptions or javascriptEnabled available in customize-cra, as far as i can see (please tell me if i missed it). cssLoaderOptions should be used as a root property of addLessLoader. Maybe this works:

const { override, addLessLoader } = require("customize-cra");

module.exports = override(
  addLessLoader({
    cssLoaderOptions: {
      url: false
    },
  })
);
lamdoann commented 3 years ago

@iwan-uschka for new version, you can see the first comment of this topic. It will be like this: addLessLoader({ lessOptions: { javascriptEnabled: true, modifyVars: { '@primary-color': '#A80000' }, }, }),

lamdoann commented 3 years ago

I found the way to fix it. I overrided ModuleScopePlugin plugin. It worked. Thanks for your support @iwan-uschka

iwan-uschka commented 3 years ago

Oooops, i haven't even read the beginning of this block 😬 You're absolutely right about the new version, sorry. Glad you made it πŸ‘ Please paste your solution here. It might help others. Cheers

packetstracer commented 3 years ago

I've been trying to set up Ant Design with Create React App and Customize CRA but I'm getting an error when loading Less files.

TypeError: this.getOptions is not a function

My setup:

When running yarn start, I get the following error:

Failed to compile.

./src/entities/scratchpad/theme/antd/custom-theme.less (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-8-1!./node_modules/postcss-loader/src??postcss!./node_modules/resolve-url-loader??ref--5-oneOf-8-3!./node_modules/less-loader/dist/cjs.js??ref--5-oneOf-8-4!./src/entities/scratchpad/theme/antd/custom-theme.less)
TypeError: this.getOptions is not a function

I have Tailwind installed and running so I guess that de postcss-loader is not the problem. I've read that the problem maybe with less-loader version, but cannot get ant version of it working.

Anyone knows why may be this happening and how to solve it?

packetstracer commented 3 years ago

Finaly got it working downgrading less loader to version 7.

Package.json "less-loader": "^7.1.1"

ConfigOverrides.dev.js

    config = override(
      fixBabelImports('import', {
        libraryName: 'antd',
        libraryDirectory: 'es',
        style: true,
      }),
      addLessLoader({
        lessOptions: {
          javascriptEnabled: true,
          modifyVars: { '@primary-color': '#13c2c2' },
        },
      }),
      addPostcssPlugins([require('tailwindcss')])
    )(config)

NOTE: that for Tailwind to load correctly I had to set the addPostcssPlugins([require('tailwindcss')]) invocation line after the addLessLoader() one.

Hope this helps to anyone.

minhthangtkqn commented 2 years ago

Finaly got it working downgrading less loader to version 7.

Package.json "less-loader": "^7.1.1"

ConfigOverrides.dev.js

    config = override(
      fixBabelImports('import', {
        libraryName: 'antd',
        libraryDirectory: 'es',
        style: true,
      }),
      addLessLoader({
        lessOptions: {
          javascriptEnabled: true,
          modifyVars: { '@primary-color': '#13c2c2' },
        },
      }),
      addPostcssPlugins([require('tailwindcss')])
    )(config)

NOTE: that for Tailwind to load correctly I had to set the addPostcssPlugins([require('tailwindcss')]) invocation line after the addLessLoader() one.

Hope this helps anyone.

Hi @packetstracer, I do my own similar to you. But I encountered a problem: Before this, I use all SCSS (also import antd & tailwind using SCSS), so the order of compiled CSS same with scss importing order Now, to config antd color variable, I import antd LESS & config LESS loader same as you, I also use less-loader version 7 ("less-loader": "^7.3.0"). In the compiled CSS, antd CSS appears at a different position in the file & causes much change on the UI because of CSS priority changes. Any suggestion for my case? Thanks for reading this.

AndrewEastwood commented 2 years ago

this config is working good too:

$ nvm current
v14.19.1

package.json

    "less": "^4.1.3",
    "less-loader": "^11.0.0",
    "customize-cra": "^1.0.0",
    "react-scripts": "^5.0.1",
    "react": "^18.2.0",
    "react-app-rewired": "^2.2.1",
//config-overrides.js
const {
  override,
  addWebpackModuleRule,
} = require("customize-cra");

module.exports = {
  webpack: override(
    addWebpackModuleRule({
      test: [/\.css$/, /\.less$/],
      use: ['style-loader', 'css-loader', 'postcss-loader', {
        loader: 'less-loader',
        options: {
          lessOptions: {
            strictMath: false,
            noIeCompat: true,
            modifyVars: {
              "primary-color": "#fcbf2c", // for example, you use Ant Design to change theme color.
            },
            javascriptEnabled: true,
          }
        }
      }]
    }),
  ),
};