0

I'm currently building a modularized npm package that provides some basic functionalities and some more functionalities when installing an optional additional module. This is to allow users to install only what they need.

For example, when a user uses the useProxy() (hook) function, he/she needs to install an additional module (listed as peerDependency). Since the useProxy() function is not the main use case (muc), most people don't need this functionality and thus the module required by it ('@agile-ts/proxytree'). -> If I want to perform some behavior when module X is available, otherwise fallback to Y.

To solve this problem, I made the from the useProxy() required module optional (peerDependency) and created an internal function called optionalRequire():

// In the '@agile-ts/core' package

export function optionalRequire<PackageType = any>(
  moduleName: string,
  error = true
): PackageType | null {
  let requiredPackage = null;
  try {
    // console.log('Debug', moduleName, error);
    requiredPackage = require(moduleName);
    // console.log('Debug', requiredPackage);
  } catch (e) {
    // console.log('Debug', e);
    if (error) LogCodeManager.log('20:03:02', [moduleName]);
  }
  return requiredPackage;
}

optionalRequire() simply retrieves a module/package without throwing an error when it couldn't be found. Thus, I can silently check whether an optional package is installed or not.

const proxyPackage = optionalRequire('@agile-ts/core');

if (proxyPackage != null) 
// do x
else
// do y

Problem

However, when I import the main module ('@agile-ts/core') [with the optional dependency ('@agile-ts/proxytree')] into a React project and install the optional dependency ('@agile-ts/proxytree'). The optionalRequire() method can't retrieve the '@agile-ts/proxytree' module, although it is 100% installed. Probably because the require() called by the optionalRequire() is in another scope.

Thus, I tried to install the required module ('@agile-ts/proxytree') globally, but the optionalRequire() method still couldn't retrieve it. But why?

In the below code snippet, I placed the normal require() and the optionalRequre() next to each other. The normal require() could retrieve the searched module, but the optionalRequire() couldn't. (see console image below)

// Another project importing the '@agile-ts/core' package

import {optionalRequire} from '@agile-ts/core';

console.log('Debug: Proxy Tree');
const proxyTreeOptionalRequire = optionalRequire('@agile-ts/proxytree');
const proxyTreeRequire = require('@agile-ts/proxytree');
console.log(proxyTreeOptionalRequire, proxyTreeRequire);

enter image description here

Question

Is there a way to silently (not throwing an error when a module couldn't be retrieved) require an optional package in a npm package?

Edit

https://github.com/react-native-community/discussions-and-proposals/issues/120

BennoDev
  • 587
  • 1
  • 4
  • 11

0 Answers0