reactjsckeditor5craco

Error occurs in Iconview in ckeditor craco settings


I am setting up craco to use CKEditor in CRA. I keep getting an error in Iconview. Modifying the regex didn't change anything.

This setting file worked normally when used in other existing projects, but errors continue to occur in new projects. I would like to know what is causing this error.

craco.config.js

const CKEditorWebpackPlugin = require("@ckeditor/ckeditor5-dev-webpack-plugin");
const { styles } = require("@ckeditor/ckeditor5-dev-utils");

module.exports = {
  webpack: {
    configure: (config, { env, paths }) => {
      config.plugins.push(
        new CKEditorWebpackPlugin({
          language: "ko",
          addMainLanguageTranslationsToAllAssets: true,
        })
      );

      const regExpThemeIconSvg =
        /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/;
      const regExpThemeCss = /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/;
      const cssRegex = /\.css$/;
      const cssModuleRegex = /\.module\.css$/;
      config.module.rules.push(
        { test: regExpThemeIconSvg, use: ["raw-loader"] },
        {
          test: regExpThemeCss,
          use: [
            {
              loader: "style-loader",
              //   options: { injectType: "singletonStyleTag" }
            },
            {
              loader: "postcss-loader",
              options: styles.getPostCssConfig({
                themeImporter: {
                  themePath: require.resolve("@ckeditor/ckeditor5-theme-lark"),
                },
                minify: true,
              }),
            },
          ],
        }
      );

      config.module.rules.forEach((rule) => {
        if (rule.oneOf) {
          rule.oneOf.forEach((subRule) => {
            if (String(subRule.test) === String(cssRegex)) {
              subRule.exclude = [cssModuleRegex, regExpThemeCss];
            }

            if (String(subRule.test) === String(cssModuleRegex)) {
              subRule.exclude = [regExpThemeCss];
            }

            if (
              String(subRule.loader).includes("file-loader") &&
              Array.isArray(subRule.exclude)
            ) {
              subRule.exclude.push(regExpThemeIconSvg, regExpThemeCss);
            }
          });
        }
      });

      return config;
    },
  },
};

error log

react_devtools_backend.js:3973 TypeError: Cannot read properties of null (reading 'getAttribute')
    at IconView._updateXMLContent (iconview.js:100:1)
    at IconView.render (iconview.js:76:1)
    at IconView.<anonymous> (observablemixin.js:258:1)
    at IconView.fire (emittermixin.js:200:1)
    at IconView.<computed> [as render] (observablemixin.js:262:1)
    at ViewCollection._renderViewIntoCollectionParent (viewcollection.js:204:1)
    at ViewCollection.<anonymous> (viewcollection.js:65:1)
    at ViewCollection.fire (emittermixin.js:200:1)
    at ViewCollection.addMany (collection.js:220:1)
    at ViewCollection.add (collection.js:185:1) {phase: 'initialization', willEditorRestart: false}

Solution

  • I had the same issue as you, and it took me quite a while to understand what was happening. In my case, and probably yours it's related with react-scripts package version. Recent react-script version > 4.0.3, will throw this error. You can either downgrade your package, or use this "plugin" that I had created:

    GIST: https://gist.github.com/william-takayama/6b2a7e4b0b9497e59fa4ba60bed2e6d0

    const { styles } = require("@ckeditor/ckeditor5-dev-utils")
    
    const getLoaderByRegex = (loaders, regex) => loaders.find(
      item => !Array.isArray(item.test) && (String(item.test) === String(regex))
    )
    
    const cssRegex = /\.css$/
    const cssModuleRegex = /\.module\.css$/
    const CKEditorRegExp = {
      cssExp: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/,
      svgExp: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
    }
    
    const CKEditor5WebpackConfigPlugin = {
      overrideWebpackConfig: ({ webpackConfig, options = {} }) => {
        // Extract the oneOf array from the relevant webpack.module.rules object
        const { oneOf } = webpackConfig.module.rules.find(rule => rule.oneOf)
      
        // Add the SVG and CSS loaders to the oneOf array in the first position. 
        // As oneOf array uses the first loader that matches the value of test, we need to ensure that
        // SVGs and CSS files from ckeditor5 folder inside node_module, are using the correct loaders 
        // provided on documentation: https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/alternative-setups/integrating-from-source.html#webpack-configuration
        oneOf.unshift(
          {
            // ASSET-MODULES replaces raw-loader - https://webpack.js.org/guides/asset-modules/
            test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
            type: 'asset/source',
          },
          {
            test: CKEditorRegExp.cssExp,
            use: [
              {
                loader: "style-loader",
                options: {
                  injectType: "singletonStyleTag"
                }
              },
              'css-loader',
              {
                loader: "postcss-loader",
                options: {
                  postcssOptions: styles.getPostCssConfig({
                    themeImporter: {
                      themePath: require.resolve("@ckeditor/ckeditor5-theme-lark")
                    },
                    minify: true
                  })
                }
              }
            ]
          }
        )
      
        // Make sure cssRegex doesn't use loader for CKEditor5
        getLoaderByRegex(oneOf, cssRegex).exclude = [cssModuleRegex, CKEditorRegExp.cssExp]
        // Make sure cssModuleRegex doesn't use loader for CKEditor5
        getLoaderByRegex(oneOf, cssModuleRegex).exclude = [CKEditorRegExp.cssExp]
      
        return webpackConfig
      }
    }
    
    module.exports = { CKEditor5WebpackConfigPlugin }
    
    // usage -> craco.config.js -> 
    /*
    module.exports = {
      plugins: [{
        plugin: CKEditor5WebpackConfigPlugin,
      }],
    }
    */