module.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. const Module = require('module')
  2. const path = require('path')
  3. const semver = require('semver')
  4. // https://github.com/benmosher/eslint-plugin-import/pull/1591
  5. // https://github.com/benmosher/eslint-plugin-import/pull/1602
  6. // Polyfill Node's `Module.createRequireFromPath` if not present (added in Node v10.12.0)
  7. // Use `Module.createRequire` if available (added in Node v12.2.0)
  8. const createRequire = Module.createRequire || Module.createRequireFromPath || function (filename) {
  9. const mod = new Module(filename, null)
  10. mod.filename = filename
  11. mod.paths = Module._nodeModulePaths(path.dirname(filename))
  12. mod._compile(`module.exports = require;`, filename)
  13. return mod.exports
  14. }
  15. function resolveFallback (request, options) {
  16. const isMain = false
  17. const fakeParent = new Module('', null)
  18. const paths = []
  19. for (let i = 0; i < options.paths.length; i++) {
  20. const p = options.paths[i]
  21. fakeParent.paths = Module._nodeModulePaths(p)
  22. const lookupPaths = Module._resolveLookupPaths(request, fakeParent, true)
  23. if (!paths.includes(p)) paths.push(p)
  24. for (let j = 0; j < lookupPaths.length; j++) {
  25. if (!paths.includes(lookupPaths[j])) paths.push(lookupPaths[j])
  26. }
  27. }
  28. const filename = Module._findPath(request, paths, isMain)
  29. if (!filename) {
  30. const err = new Error(`Cannot find module '${request}'`)
  31. err.code = 'MODULE_NOT_FOUND'
  32. throw err
  33. }
  34. return filename
  35. }
  36. const resolve = semver.satisfies(process.version, '>=10.0.0')
  37. ? require.resolve
  38. : resolveFallback
  39. exports.resolveModule = function (request, context) {
  40. let resolvedPath
  41. try {
  42. try {
  43. resolvedPath = createRequire(path.resolve(context, 'package.json')).resolve(request)
  44. } catch (e) {
  45. resolvedPath = resolve(request, { paths: [context] })
  46. }
  47. } catch (e) {}
  48. return resolvedPath
  49. }
  50. exports.loadModule = function (request, context, force = false) {
  51. // createRequire doesn't work with jest mock modules
  52. // (which we used in migrator for inquirer, and in tests for cli-service)
  53. // TODO: it's supported in Jest 25
  54. if (process.env.VUE_CLI_TEST && (request.endsWith('migrator') || context === '/')) {
  55. return require(request)
  56. }
  57. try {
  58. return createRequire(path.resolve(context, 'package.json'))(request)
  59. } catch (e) {
  60. const resolvedPath = exports.resolveModule(request, context)
  61. if (resolvedPath) {
  62. if (force) {
  63. clearRequireCache(resolvedPath)
  64. }
  65. return require(resolvedPath)
  66. }
  67. }
  68. }
  69. exports.clearModule = function (request, context) {
  70. const resolvedPath = exports.resolveModule(request, context)
  71. if (resolvedPath) {
  72. clearRequireCache(resolvedPath)
  73. }
  74. }
  75. function clearRequireCache (id, map = new Map()) {
  76. const module = require.cache[id]
  77. if (module) {
  78. map.set(id, true)
  79. // Clear children modules
  80. module.children.forEach(child => {
  81. if (!map.get(child.id)) clearRequireCache(child.id, map)
  82. })
  83. delete require.cache[id]
  84. }
  85. }