diff --git a/lib/manager/npm/resolve.js b/lib/manager/npm/resolve.js
new file mode 100644
index 0000000000000000000000000000000000000000..c4798d4154df6a2a888e3c8fc2fefd8e3ad4c05a
--- /dev/null
+++ b/lib/manager/npm/resolve.js
@@ -0,0 +1,110 @@
+const path = require('path');
+const upath = require('upath');
+const configParser = require('../../config');
+
+module.exports = {
+  resolvePackageFile,
+};
+
+async function resolvePackageFile(config, inputFile) {
+  const packageFile = configParser.mergeChildConfig(config.npm, inputFile);
+  logger.debug(
+    `Resolving packageFile ${JSON.stringify(packageFile.packageFile)}`
+  );
+  const pFileRaw = await platform.getFile(packageFile.packageFile);
+  if (!pFileRaw) {
+    logger.info(
+      { packageFile: packageFile.packageFile },
+      'Cannot find package.json'
+    );
+    config.errors.push({
+      depName: packageFile.packageFile,
+      message: 'Cannot find package.json',
+    });
+    return null;
+  }
+  try {
+    packageFile.content = JSON.parse(pFileRaw);
+  } catch (err) {
+    logger.info(
+      { packageFile: packageFile.packageFile },
+      'Cannot parse package.json'
+    );
+    if (config.repoIsOnboarded) {
+      const error = new Error('config-validation');
+      error.configFile = packageFile.packageFile;
+      error.validationError = 'Cannot parse package.json';
+      error.validationMessage =
+        'This package.json contains invalid JSON and cannot be parsed. Please fix it, or add it to your "ignorePaths" array in your renovate config so that Renovate can continue.';
+      throw error;
+    }
+    config.errors.push({
+      depName: packageFile.packageFile,
+      message:
+        "Cannot parse package.json (invalid JSON). Please fix the contents or add the file/path to the `ignorePaths` array in Renovate's config",
+    });
+    return null;
+  }
+  if (!config.ignoreNpmrcFile) {
+    packageFile.npmrc = await platform.getFile(
+      upath.join(path.dirname(packageFile.packageFile), '.npmrc')
+    );
+  }
+  if (packageFile.npmrc) {
+    logger.info({ packageFile: packageFile.packageFile }, 'Found .npmrc');
+    if (packageFile.npmrc.match(/\${NPM_TOKEN}/) && !config.global.exposeEnv) {
+      logger.info('Stripping NPM_TOKEN from .npmrc');
+      packageFile.npmrc = packageFile.npmrc
+        .replace(/(^|\n).*?\${NPM_TOKEN}.*?(\n|$)/g, '')
+        .trim();
+      if (packageFile.npmrc === '') {
+        logger.info('Removing empty .npmrc');
+        delete packageFile.npmrc;
+      }
+    }
+  } else {
+    delete packageFile.npmrc;
+  }
+  packageFile.yarnrc = await platform.getFile(
+    upath.join(path.dirname(packageFile.packageFile), '.yarnrc')
+  );
+  if (packageFile.yarnrc) {
+    logger.info({ packageFile: packageFile.packageFile }, 'Found .yarnrc');
+  } else {
+    delete packageFile.yarnrc;
+  }
+  // Detect if lock files are used
+  const yarnLockFileName = upath.join(
+    path.dirname(packageFile.packageFile),
+    'yarn.lock'
+  );
+  const fileList = await platform.getFileList();
+  if (fileList.includes(yarnLockFileName)) {
+    logger.debug({ packageFile: packageFile.packageFile }, 'Found yarn.lock');
+    packageFile.yarnLock = yarnLockFileName;
+  }
+  const packageLockFileName = upath.join(
+    path.dirname(packageFile.packageFile),
+    'package-lock.json'
+  );
+  if (fileList.includes(packageLockFileName)) {
+    logger.debug(
+      { packageFile: packageFile.packageFile },
+      'Found package-lock.json'
+    );
+    packageFile.packageLock = packageLockFileName;
+  }
+  const shrinkwrapFileName = upath.join(
+    path.dirname(packageFile.packageFile),
+    'shrinkwrap.yaml'
+  );
+  if (fileList.includes(shrinkwrapFileName)) {
+    logger.debug(
+      { packageFile: packageFile.packageFile },
+      'Found shrinkwrap.yaml'
+    );
+    packageFile.shrinkwrapYaml = shrinkwrapFileName;
+  }
+  packageFile.currentPackageJsonVersion = packageFile.content.version;
+  return packageFile;
+}
diff --git a/lib/manager/resolve.js b/lib/manager/resolve.js
index 9f23a0c0c11b5ecc2d0581983ad2d195115d302f..b4841ad82078a49659b7893094cee0115b85db51 100644
--- a/lib/manager/resolve.js
+++ b/lib/manager/resolve.js
@@ -1,5 +1,3 @@
-const path = require('path');
-const upath = require('upath');
 const minimatch = require('minimatch');
 
 const manager = require('./index');
@@ -7,6 +5,7 @@ const dockerResolve = require('../manager/docker/resolve');
 const meteorResolve = require('../manager/meteor/resolve');
 const nodeResolve = require('../manager/node/resolve');
 const bazelResolve = require('../manager/bazel/resolve');
+const npmResolve = require('../manager/npm/resolve');
 const { mergeChildConfig } = require('../config');
 const { checkMonorepos } = require('../manager/npm/monorepos');
 
@@ -22,7 +21,6 @@ async function resolvePackageFiles(config) {
       ? config.packageFiles
       : await manager.detectPackageFiles(config);
   logger.debug({ allPackageFiles }, 'allPackageFiles');
-  const fileList = await platform.getFileList();
   const managerFileMappings = {
     '.travis.yml': 'node',
     Dockerfile: 'docker',
@@ -30,7 +28,7 @@ async function resolvePackageFiles(config) {
     'package.js': 'meteor',
     'package.json': 'npm',
   };
-  async function resolvePackageFile(p) {
+  function resolvePackageFile(p) {
     const packageFile = typeof p === 'string' ? { packageFile: p } : p;
     const fileName = packageFile.packageFile.split('/').pop();
     packageFile.manager = packageFile.manager || managerFileMappings[fileName];
@@ -44,108 +42,7 @@ async function resolvePackageFiles(config) {
       throw error;
     }
     if (packageFile.manager === 'npm') {
-      logger.debug(`Resolving packageFile ${JSON.stringify(packageFile)}`);
-      const pFileRaw = await platform.getFile(packageFile.packageFile);
-      if (!pFileRaw) {
-        logger.info(
-          { packageFile: packageFile.packageFile },
-          'Cannot find package.json'
-        );
-        config.errors.push({
-          depName: packageFile.packageFile,
-          message: 'Cannot find package.json',
-        });
-        return null;
-      }
-      try {
-        packageFile.content = JSON.parse(pFileRaw);
-      } catch (err) {
-        logger.info(
-          { packageFile: packageFile.packageFile },
-          'Cannot parse package.json'
-        );
-        if (config.repoIsOnboarded) {
-          const error = new Error('config-validation');
-          error.configFile = packageFile.packageFile;
-          error.validationError = 'Cannot parse package.json';
-          error.validationMessage =
-            'This package.json contains invalid JSON and cannot be parsed. Please fix it, or add it to your "ignorePaths" array in your renovate config so that Renovate can continue.';
-          throw error;
-        }
-        config.errors.push({
-          depName: packageFile.packageFile,
-          message:
-            "Cannot parse package.json (invalid JSON). Please fix the contents or add the file/path to the `ignorePaths` array in Renovate's config",
-        });
-        return null;
-      }
-      if (!config.ignoreNpmrcFile) {
-        packageFile.npmrc = await platform.getFile(
-          upath.join(path.dirname(packageFile.packageFile), '.npmrc')
-        );
-      }
-      if (packageFile.npmrc) {
-        logger.info({ packageFile: packageFile.packageFile }, 'Found .npmrc');
-        if (
-          packageFile.npmrc.match(/\${NPM_TOKEN}/) &&
-          !config.global.exposeEnv
-        ) {
-          logger.info('Stripping NPM_TOKEN from .npmrc');
-          packageFile.npmrc = packageFile.npmrc
-            .replace(/(^|\n).*?\${NPM_TOKEN}.*?(\n|$)/g, '')
-            .trim();
-          if (packageFile.npmrc === '') {
-            logger.info('Removing empty .npmrc');
-            delete packageFile.npmrc;
-          }
-        }
-      } else {
-        delete packageFile.npmrc;
-      }
-      packageFile.yarnrc = await platform.getFile(
-        upath.join(path.dirname(packageFile.packageFile), '.yarnrc')
-      );
-      if (packageFile.yarnrc) {
-        logger.info({ packageFile: packageFile.packageFile }, 'Found .yarnrc');
-      } else {
-        delete packageFile.yarnrc;
-      }
-      // Detect if lock files are used
-      const yarnLockFileName = upath.join(
-        path.dirname(packageFile.packageFile),
-        'yarn.lock'
-      );
-      if (fileList.includes(yarnLockFileName)) {
-        logger.debug(
-          { packageFile: packageFile.packageFile },
-          'Found yarn.lock'
-        );
-        packageFile.yarnLock = yarnLockFileName;
-      }
-      const packageLockFileName = upath.join(
-        path.dirname(packageFile.packageFile),
-        'package-lock.json'
-      );
-      if (fileList.includes(packageLockFileName)) {
-        logger.debug(
-          { packageFile: packageFile.packageFile },
-          'Found package-lock.json'
-        );
-        packageFile.packageLock = packageLockFileName;
-      }
-      const shrinkwrapFileName = upath.join(
-        path.dirname(packageFile.packageFile),
-        'shrinkwrap.yaml'
-      );
-      if (fileList.includes(shrinkwrapFileName)) {
-        logger.debug(
-          { packageFile: packageFile.packageFile },
-          'Found shrinkwrap.yaml'
-        );
-        packageFile.shrinkwrapYaml = shrinkwrapFileName;
-      }
-      packageFile.currentPackageJsonVersion = packageFile.content.version;
-      return mergeChildConfig(config.npm, packageFile);
+      return npmResolve.resolvePackageFile(config, packageFile);
     } else if (packageFile.manager === 'meteor') {
       return meteorResolve.resolvePackageFile(config, packageFile);
     } else if (packageFile.manager === 'docker') {