Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a loader results in Webpack "Invalid configuration object" error in some cases #486

Open
ajani2001 opened this issue Jan 9, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@ajani2001
Copy link

I want to add html-loader and I do it according to the recipe:

import {CracoConfig} from "@craco/types";
import {addBeforeLoader, loaderByName} from "@craco/craco";

const config: CracoConfig = {
    webpack: {
        configure: (webpackConfig) => {
            webpackConfig.resolve!.extensions!.push('.html');

            const htmlLoader = {
                loader: require.resolve('html-loader'),
                test: /\.html$/,
                exclude: /node_modules/,
            };

            addBeforeLoader(webpackConfig, loaderByName('file-loader'), htmlLoader);

            return webpackConfig;
        },
    }
};

export default config;

But my application even doesn`t starts:

Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
 - configuration.module.rules[1] should be one of these:
   ["..." | object { assert?, compiler?, dependency?, descriptionData?, enforce?, exclude?, generator?, include?, issuer?, issuerLayer?, layer?, loader?, mimetype?, oneOf?, options?, parser?, realResource?, resolve?, resource?, resourceFragment?, resourceQuery?, rules?, scheme?, sideEffects?, test?, type?, use? }, ...]
   -> A rule.
   Details:
    * configuration.module.rules[1].oneOf[2].use[1] has an unknown property 'test'. These properties are valid:
      object { ident?, loader?, options? }
    * configuration.module.rules[1].oneOf[2].use[1] has an unknown property 'exclude'. These properties are valid:
      object { ident?, loader?, options? }

It can be reproduced on a blank app just created by create-react-app (with typescript in my case).

"@craco/craco": "^7.0.0",
"@craco/types": "^7.0.0",
"react-scripts": "5.0.1",
"typescript": "^4.9.4"

I suppose, this is a rare bug, that emerge, when a target loader for addBeforeLoader`s matcher becomes a RuleSetUseItem located in the 'use' array. New loader argument for addBeforeLoader has the type of RuleSetRule, thus, a RuleSetRule is inserted in the 'use' array and breaks the consistency.

The root of problem might me in this cast:

loader = getLoaderRecursively(rule.use as RuleSetRule[], matcher);

@ajani2001 ajani2001 added the bug Something isn't working label Jan 9, 2023
@tylandercasper
Copy link

did you ever find a fix for this? I was a little suprised that copying and pasting the provided code doesn't work.

@alfonsoar
Copy link

I was able to work around this issue by using a diffrent loader as the starting point, doing this seems to place the loader in the correct place of the webpack config.

const txtLoader = {
  test: /\.txt$/i,
  use: 'raw-loader',
};

addAfterLoader(webpackConfig, loaderByName('source-map-loader'), txtLoader);

@lotorvik
Copy link

lotorvik commented Mar 8, 2023

Have anyone found a fix for this? I have same issue just with ejs-loader instead of html-loader.

@ajani2001
Copy link
Author

ajani2001 commented Mar 8, 2023

Have anyone found a fix for this? I have same issue just with ejs-loader instead of html-loader.

I just inspected the stricture of my existing loader rules via console.dir and inserted the new loader manually in the right place. This is a temporary fix and it might be broken if you change the version of create-react-app or other packages.

This is the corresponding fragment of my config:
(ofc you shouldn't remove resolve-url-loader, this is for my project)

configure: (webpackConfig) => {
    const htmlLoader = {
        test: /\.html$/,
        loader: require.resolve('html-loader'),
        exclude: [/node_modules/, /public/],
        options: { minimize: true, sources: false },
    };

    // FIXME AFTER THE ISSUE IS FIXED
    // https://github.com/dilanx/craco/issues/486
    (webpackConfig.module.rules[0] as any).oneOf.splice(0, 0, htmlLoader);
    removeLoaders(webpackConfig, loaderByName('resolve-url-loader'));

    return webpackConfig;
}

@dotamir
Copy link

dotamir commented Jun 13, 2023

I could fix this issue by adding the loader before another loader instead of file-loader|raw-loader like babel-loader. It seems that issue is adding before or after file-loader and raw-loader but adding before/after babel-loader working well.

configure: (webpackConfig) => {
    webpackConfig.resolve.extensions.push('.graphql', '.gql');

    const graphqlLoader = {
      test: /\.(graphql|gql)$/,
      exclude: /node_modules/,
      loader: require.resolve('graphql-tag/loader'),
    }

    addBeforeLoader(webpackConfig, loaderByName('babel-loader'), graphqlLoader);

    return webpackConfig;
}

@AlexanderBaumgertner
Copy link

@dotamir your solution works for men thank you!

@imdanteking
Copy link

@dotamir Thank you! It works!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

7 participants