React-app-rewired: can i use this package to remove some plugin ?

Created on 8 Apr 2018  路  9Comments  路  Source: timarney/react-app-rewired

For example, i want to remove the ModuleScopePlugin.. Is there anyway to do this by override without eject ? 馃あ

All 9 comments

I think it's possible.

The default react-scripts config has the module defined in config.resolve.plugins. At present, it's the only plugin being defined in there, so a quick-and-dirty removal would be to set:

config.resolve.plugins = [];

A better removal would be to filter that specific plugin out of the config.resolve.plugins array, so that if they add another plugin in the future you don't clobber the new plugin too. Looking at what is able to be seen in the plugin data, I _think_ the following would filter just that plugin out. A console.log of the plugin information shows something like:

{
  "appSrc": "/home/username/project/src",
  "allowedFiles": {}
}

so a filter could be written to search for the presence of those two fields, and only retain plugins that are missing one or the other of those two fields:

config.resolve.plugins = config.resolve.plugins.filter(
  (plugin) => !plugin.appSrc || !plugin.allowedFiles
);

You _may_ alternatively be able to inject some filenames into the allowedFiles array rather than having to remove the plugin entirely. For example, to add a file 'logo.png' from an 'assets' directory you could try:

const moduleScopePlugin = config.resolve.plugins.find(
  (plugin) => plugin.appSrc && plugin.allowedFiles
);
if (moduleScopePlugin) {
  // Add our extra file path(s). Each file needs to be individually added to the
  // allowedFiles property (globs will not work).
  moduleScopePlugin.allowedFiles.push(path.join(__dirname, 'assets', 'logo.png'));
}

Note that I haven't tested the effects from injecting the path into the ModuleScopePlugin myself, so I can't confirm absolutely that injecting a filename will work. It looks like it _should_ work, but if you have a lot of files you want to add you're probably better off simply filtering out the plugin instead.

If injecting paths does work, you may be able to automatically generate a list of files to include using require.context:

const moduleScopePlugin = config.resolve.plugins.find(
  (plugin) => plugin.appSrc && plugin.allowedFiles
);
if (moduleScopePlugin) {
  // require.context takes 3 parameters:
  //    * directory name
  //    * a boolean for whether to look in subdirectories too (set true = look in subdirectories)
  //    * a RegExp to match filenames to include.
  // So to add all png files in the assets directory:
  const files = require.context('assets', true, /\.png$/);
  files.keys().forEach(
    (filename) => moduleScopePlugin.allowedFiles.push(
      // Using normalize to rid of the './' at the beginning of the filename if present
      path.normalize(path.join(__directory, filename))
    )
  );
}

Yep, I used to fix a problem with UglifyJsPlugin.

I found a script that gets you filter plugins out:

//configure-overrides.js
const filterPlugins = (config, filter) =>
    config.plugins.filter(p => filter[getFunctionName(p)] !== false);

const getFunctionName = obj => {
    const funcNameRegex = /(function (.{1,})\(|class (.{1,}))/;
    const results = funcNameRegex.exec(obj.constructor.toString());
    return results && results.length > 1 ? /\w+ (\w+)/.exec(results[1])[1] : '';
};

module.exports = (config, env) => {
 config.plugins = filterPlugins(config, {
    ModuleScopePlugin: false, // I swapped your plugin with mine(UglifyJsPlugin)
 });
 return config;
};

Original

thanks!

@dawnmist

Thanks for the thorough explanation of your ideas!
Injecting filenames to the allowedFiles works when add to it (it's a Set internally)

const moduleScopePlugin = config.resolve.plugins.find(
  (plugin) => plugin.appSrc && plugin.allowedFiles
);

if (moduleScopePlugin) {
  moduleScopePlugin.allowedFiles.add(path.join(__dirname, 'assets', 'logo.png'));
}

Just wanted to let you and everyone else that might be intererested know!

does anybody know how to get this capabilty to work with CRA 2.x
When trying the above approach, the plugins.find does not seem to be able to find the plugin

@vladp - The basic method I used to work out the original version was:

  1. Look at the webpack.config file in react-scripts to see what is being initialized there.
  2. Use console.log in my config-overrides.js file to output the generated config so that I could see what the fields were on the plugins to determine what fields to look for in order to find the plugin I wanted to modify.

So - it looks like it should still be under config.resolve.plugins, but is now the second plugin (so you wouldn't want to use the quick-and-dirty approach of just emptying the array anymore).

Doing the above shows that the field names have changed. It now shows up as:

{
  "appSrcs": [  "/home/username/project/src"  ],
  "allowedFiles": {}
}

So instead of searching for an appSrc field, search for an appSrcs field (together with the existing allowedFiles field).

That makes the search function:

const moduleScopePlugin = config.resolve.plugins.find(
  (plugin) => plugin.appSrcs && plugin.allowedFiles
);

Thank you. Yes, had to change appSrc to appSrcs.
I also moved to use functions of customize-cra.

const {
    override,

    removeModuleScopePlugin,
    addWebpackAlias,
    addWebpackResolve,
    useEslintRc,
    useBabelRc,
    addBabelPreset,
    addBabelPlugin,
    enableEslintTypescript,
    babelInclude,
    addBundleVisualizer,
} = require("customize-cra");

module.exports = {
webpack: function(baseConfig, env) {
 const config = Object.assign({}, baseConfig);
removeModuleScopePlugin()(config);
..
}
...
}

In case someone wonders how to do this in 2020

const moduleScopePlugin = config.resolve.plugins.find(
  (plugin) => plugin.appSrcs && plugin.allowedFiles,
);
moduleScopePlugin.allowedFiles = moduleScopePlugin.allowedFiles.add(
  path.resolve(fs.realpathSync(process.cwd()), 'dev.config.js'),
);
Was this page helpful?
0 / 5 - 0 ratings