function getProdModules(externalModules, packagePath, nodeModulesRelativeDir, dependencyGraph, forceExcludes) {
  const packageJsonPath = path.join(process.cwd(), packagePath);
  const packageJson = require(packageJsonPath);
  const prodModules = [];

  // only process the module stated in dependencies section
  if (!packageJson.dependencies) {
    return [];
  }

  // Get versions of all transient modules
  _.forEach(externalModules, module => {
    let moduleVersion = packageJson.dependencies[module.external];

    if (moduleVersion) {
      prodModules.push(`${module.external}@${moduleVersion}`);

      let nodeModulesBase = path.join(path.dirname(path.join(process.cwd(), packagePath)), 'node_modules');

      if (nodeModulesRelativeDir) {
        const customNodeModulesDir = path.join(process.cwd(), nodeModulesRelativeDir, 'node_modules');

        if (fse.pathExistsSync(customNodeModulesDir)) {
          nodeModulesBase = customNodeModulesDir;
        } else {
          if (this.log) {
            this.log.warning(`${customNodeModulesDir} dose not exist. Please check nodeModulesRelativeDir setting`);
          } else {
            this.serverless.cli.log(
              `WARNING: ${customNodeModulesDir} dose not exist. Please check nodeModulesRelativeDir setting`
            );
          }
        }
      }

      // Check if the module has any peer dependencies and include them too
      try {
        const modulePackagePath = path.join(nodeModulesBase, module.external, 'package.json');

        const peerDependencies = require(modulePackagePath).peerDependencies;
        if (!_.isEmpty(peerDependencies)) {
          if (this.log) {
            this.log.verbose(`Adding explicit peers for dependency ${module.external}`);
          } else {
            this.options.verbose && this.serverless.cli.log(`Adding explicit peers for dependency ${module.external}`);
          }

          const peerDependenciesMeta = require(modulePackagePath).peerDependenciesMeta;

          if (!_.isEmpty(peerDependenciesMeta)) {
            _.forEach(peerDependencies, (value, key) => {
              if (peerDependenciesMeta[key] && peerDependenciesMeta[key].optional === true) {
                if (this.log) {
                  this.log.verbose(
                    `Skipping peers dependency ${key} for dependency ${module.external} because it's optional`
                  );
                } else {
                  this.options.verbose &&
                    this.serverless.cli.log(
                      `Skipping peers dependency ${key} for dependency ${module.external} because it's optional`
                    );
                }
                _.unset(peerDependencies, key);
              }
            });
          }

          if (!_.isEmpty(peerDependencies)) {
            const peerModules = getProdModules.call(
              this,
              _.map(peerDependencies, (value, key) => ({ external: key })),
              packagePath,
              nodeModulesRelativeDir,
              dependencyGraph,
              forceExcludes
            );
            Array.prototype.push.apply(prodModules, peerModules);
          }
        }
      } catch (e) {
        if (this.log) {
          this.log.warning(
            `Could not check for peer dependencies of ${module.external}. Set nodeModulesRelativeDir if node_modules is in different directory.`
          );
        } else {
          this.serverless.cli.log(
            `WARNING: Could not check for peer dependencies of ${module.external}. Set nodeModulesRelativeDir if node_modules is in different directory.`
          );
        }
      }
    } else {
      if (!packageJson.devDependencies || !packageJson.devDependencies[module.external]) {
        // Add transient dependencies if they appear not in the service's dev dependencies
        const originInfo = _.get(dependencyGraph, 'dependencies', {})[module.origin] || {};
        moduleVersion = _.get(_.get(originInfo, 'dependencies', {})[module.external], 'version');
        if (!moduleVersion) {
          // eslint-disable-next-line lodash/path-style
          moduleVersion = _.get(dependencyGraph, ['dependencies', module.external, 'version']);
        }
        if (!moduleVersion) {
          if (this.log) {
            this.log.warning(`Could not determine version of module ${module.external}`);
          } else {
            this.serverless.cli.log(`WARNING: Could not determine version of module ${module.external}`);
          }
        }
        prodModules.push(moduleVersion ? `${module.external}@${moduleVersion}` : module.external);
      } else if (
        packageJson.devDependencies &&
        packageJson.devDependencies[module.external] &&
        !_.includes(forceExcludes, module.external)
      ) {
        // To minimize the chance of breaking setups we whitelist packages available on AWS here. These are due to the previously missing check
        // most likely set in devDependencies and should not lead to an error now.
        const ignoredDevDependencies = ['aws-sdk'];

        if (!_.includes(ignoredDevDependencies, module.external)) {
          // Runtime dependency found in devDependencies but not forcefully excluded
          if (this.log) {
            this.log.error(
              `Runtime dependency '${module.external}' found in devDependencies. Move it to dependencies or use forceExclude to explicitly exclude it.`
            );
          } else {
            this.serverless.cli.log(
              `ERROR: Runtime dependency '${module.external}' found in devDependencies. Move it to dependencies or use forceExclude to explicitly exclude it.`
            );
          }
          throw new this.serverless.classes.Error(`Serverless-webpack dependency error: ${module.external}.`);
        }
        if (this.log) {
          this.log.verbose(
            `Runtime dependency '${module.external}' found in devDependencies. It has been excluded automatically.`
          );
        } else {
          this.options.verbose &&
            this.serverless.cli.log(
              `INFO: Runtime dependency '${module.external}' found in devDependencies. It has been excluded automatically.`
            );
        }
      }
    }
  });

  return prodModules;
}
Resolve the needed versions of production dependencies for external modules.
@this - The active plugin instance