14

I use webpack in my react project.

I want check file in 'foo/myfile' and if that file exist import in my component, or load from 'bar/myfile'. for example:

let myModule;
if(webpackCheckFileExist('foo/myfile.jsx')){
  myModule = require('foo/myfile.jsx');
} else {
  myModule = require('bar/myfile.jsx');
}

I try:

if(__webpack_modules__[require.resolveWeak("foo/myfile.jsx")]) {
  // do something when mod1 is available
}

but if file dosnt exist - i catch webpack error

nDiviD
  • 444
  • 1
  • 4
  • 11
  • I write small webpack loader for this: https://www.npmjs.com/package/theme-customize-loader. – nDiviD May 07 '18 at 09:09

4 Answers4

5

You can use require.context and a regular expression to match files in the current folder, see the code below.

const requireCustomFile = require.context(
    './', false, /custom.js$/
)

requireCustomFile.keys().forEach(fileName => {
    requireCustomFile(fileName);
})
2

This should help you. It just uses fs package of node.

var fs = require('fs');

if (fs.existsSync(path)) {
    // Do something
}
Mihir
  • 3,812
  • 3
  • 25
  • 29
  • 1
    Thanks for ur answer. I don't use node from backend. I need build bundle.js for production. I want check file before use code – nDiviD Dec 07 '16 at 10:27
  • 1
    @nDiviD You don't necessarily have to use node at the back end. But your webpack runs on node, I hope you know that. You may have used `path` package in your webpack. I think `fs` can also be used! Correct me if I'm wrong. – Mihir Dec 07 '16 at 10:36
  • Yes, you are right, webpack runs on node, but webpack ignored that part of code and just puts in bundle.js. Code try detect file after complete compile. I want use in bundle.js only one of two files. – nDiviD Dec 08 '16 at 08:02
  • 1
    At least care to mention why you downvoted my answer. – Mihir Sep 18 '17 at 05:23
  • `fs.exists` is [deprecated](https://stackoverflow.com/a/59792927/104380) (long time before this answer was written apparently) – vsync Aug 23 '21 at 13:50
1

First of all: Use that method if you doesn`t want create one more chunk. For example: for use different preview files in you package in different projects and want have fallback without include to main package`s chunk. For other cases create additional chunk is better way.

Checking file for exist - not best idea. Config file such better because:

  1. manipulate structure without remove files;
  2. easy detect changes;

For include to bundle only useful files I write theme-customize-loader. It`s webpack loader.

  1. Add package $ npm install theme-customize-loader --save-dev
  2. Add config file in your app

    const data = {
      MyModule: {
        Single : 'App/components/single/Single.jsx',
        Preview: 'my-theme/Preview',
      },
      OtherModule: {
        Preview: false,
      },
    };
    
    module.exports = data;
    

    Value can be path to file or false for fallback file.

  3. Add to webpack configuration to rules section

    {
      enforce: 'pre',
      test   : /\.jsx$/,
      exclude: /node_modules/,
      use    : [{ loader: 'theme-customize-loader', options: { config: customizeConfig } }],
    },
    

    don`t forget import config file: const customizeConfig = require('./App/configs/customize');

  4. Use in file. Important: In one string

    let loadComponent;
    /* customize path: "MyModule.Preview" var: "loadComponent" name: "my-chunk-name" origin: "../components/OriginPreview.jsx" */
    

More info you can find here: https://www.npmjs.com/package/theme-customize-loader

nDiviD
  • 444
  • 1
  • 4
  • 11
0

A potential solution to your problem is to take advantage of the way that module resolution works.... No custom loader required!

If you leave off the extension and there is a file with the matching name then the file will be used, if the file is missing then it will check for a folder with the matching name and look for an index.js file in the folder. I have only tested this for typescript projects, and using import but it should work the same.
(see: https://webpack.js.org/concepts/module-resolution/#module-paths)

You could have something like this:

some-file.js:

const myModule = require('./foo/myfile');
// ...

foo/myfile/index.ts: (note the .. below is necessary)

module.exports = require('../bar/myfile.jsx')

Now, if foo/myfile.jsx doesn't exist then it would use the foo/myfile/index.js file which re-exports from the bar/myfile.jsx.

But, if foo/myfile.jsx exists then it would use that file. Problem solved!

Mark Whitfeld
  • 6,500
  • 4
  • 36
  • 32