Find all the dependencies without a `main` property or with a `binary` property or set by user and add them as webpack externals
function getExternals (api, pluginOptions) {
  const nodeModulesPath = pluginOptions.nodeModulesPath || './node_modules'
  let nodeModulesPaths = []
  if (Array.isArray(nodeModulesPath)) {
    // Set to user-defined array
    nodeModulesPaths = nodeModulesPath
  } else {
    // Add path to list
    nodeModulesPaths.push(nodeModulesPath)
  }
  const userExternals = pluginOptions.externals || []
  const userExternalsWhitelist = []
  userExternals.forEach((d, i) => {
    if (d.match(/^!/)) {
      userExternals.splice(i, 1)
      userExternalsWhitelist.push(d.replace(/^!/, ''))
    }
  })
  const { dependencies } = require(api.resolve('./package.json'))
  const externalsList = Object.keys(dependencies || {}).reduce(
    (depList, dep) => {
      // Return true if we want to add a dependency to externals
      try {
        let pgkString
        for (const path of nodeModulesPaths) {
          // Check if package.json exists
          if (fs.existsSync(api.resolve(`${path}/${dep}/package.json`))) {
            // If it does, read it and break
            pgkString = fs
              .readFileSync(api.resolve(`${path}/${dep}/package.json`))
              .toString()
            break
          }
        }
        if (!pgkString) {
          throw new Error(`Could not find a package.json for module ${dep}`)
        }
        const pkg = JSON.parse(pgkString)
        const name = userExternals.find(name =>
          new RegExp(`^${pkg.name}`).test(name)
        )
        const fields = ['main', 'module', 'jsnext:main', 'browser']
        if (
          // Not whitelisted
          userExternalsWhitelist.indexOf(dep) === -1 &&
          // Doesn't have main property
          (!fields.some(field => field in pkg) ||
            // Has binary property
            !!pkg.binary ||
            // Has gypfile property
            !!pkg.gypfile ||
            // Listed in user-defined externals list
            !!name)
        ) {
          // Use user-provided name if it exists, for subpaths
          depList.push(name || dep)
        }
      } catch (e) {
        console.log(e)
        depList.push(dep)
      }
      return depList
    },
    []
  )
  let externals = {}
  externalsList.forEach(d => {
    // Set external to be required during runtime
    externals[d] = `require("${d}")`
  })
  return externals
}