-
-
Save Spikef/bdf8c5faf9cef9fb94765627e211e4f7 to your computer and use it in GitHub Desktop.
支持webpack别名的模块路径解析。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const path = require('path'); | |
const route = {}; | |
const NODE_MODULES = 'node_modules'; | |
const REGEXP_RELATIVE = /^\.{0,2}\/?/; | |
const coreModules = new Set(Object.keys(process.versions)); | |
class Resolver { | |
constructor(module, { alias, extensions }) { | |
if (route[module]) return route[module]; | |
route[module] = this; | |
this.cache = {}; | |
if (!fs.existsSync(module)) { | |
throw new Error(`Module not exist: [${module}]`); | |
} | |
this.alias = alias || {}; | |
this.extensions = extensions || ['.js']; | |
this.module = module; | |
this.context = fs.statSync(module).isDirectory() ? module : path.dirname(module); | |
} | |
resolve(request) { | |
if (coreModules.has(request)) return request; | |
if (this.cache[request]) return this.cache[request]; | |
let filename; | |
if (REGEXP_RELATIVE.test(request)) { | |
const realPath = path.resolve(this.context, request); | |
filename = this.resolveAsFile(realPath) || this.resolveAsDirectory(realPath); | |
} | |
if (!filename) filename = this.resolveAlias(request); | |
if (!filename) filename = this.resolveNodeModules(request); | |
if (!filename) throw new Error(`Can not find module '${request}' from '${this.module}'`); | |
filename = path.resolve(filename); | |
this.cache[request] = filename; | |
return filename; | |
} | |
resolveIndex(x) { | |
let y; | |
let stat; | |
for (let i = 0; i < this.extensions.length; i++) { | |
y = `${x}/index${this.extensions[i]}`; | |
if (fs.existsSync(y)) { | |
stat = fs.statSync(y); | |
if (stat && stat.isFile()) return y; | |
} | |
} | |
} | |
resolveAsFile(x) { | |
let y; | |
let stat; | |
if (fs.existsSync(x)) { | |
stat = fs.statSync(x); | |
if (stat && stat.isFile()) return x; | |
} | |
for (let i = 0; i < this.extensions.length; i++) { | |
y = `${x}${this.extensions[i]}`; | |
if (fs.existsSync(y)) { | |
stat = fs.statSync(y); | |
if (stat && stat.isFile()) return y; | |
} | |
} | |
} | |
resolveAsDirectory(x) { | |
const y = `${x}/package.json`; | |
if (fs.existsSync(y)) { | |
const stat = fs.statSync(y); | |
if (stat && stat.isFile()) { | |
try { | |
const pkg = JSON.parse(fs.readFileSync(y, 'utf8')); | |
if (!pkg.main) return this.resolveIndex(x); | |
const m = path.resolve(x, pkg.main); | |
return this.resolveAsFile(m) || this.resolveIndex(m); | |
} catch (e) { | |
return this.resolveIndex(x); | |
} | |
} | |
} | |
return this.resolveIndex(x); | |
} | |
resolveAlias(x) { | |
let filename; | |
const paths = this.aliasPaths(x); | |
for (let i = 0; i < paths.length; i++) { | |
const path = paths[i]; | |
filename = this.resolveAsFile(path); | |
if (filename) return filename; | |
filename = this.resolveAsDirectory(path); | |
if (filename) return filename; | |
} | |
} | |
resolveNodeModules(x) { | |
let filename; | |
const dirs = this.nodeModulesPaths(); | |
for (let i = 0; i < dirs.length; i++) { | |
const dir = dirs[i]; | |
filename = this.resolveAsFile(path.join(dir, x)); | |
if (filename) return filename; | |
filename = this.resolveAsDirectory(path.join(dir, x)); | |
if (filename) return filename; | |
} | |
} | |
nodeModulesPaths() { | |
const dirs = []; | |
const parts = this.context.split(/[\\/]+/); | |
if (parts[0] === '') parts[0] = '/'; | |
for (let i = parts.length - 1; i > 0; i--) { | |
if (parts[i] !== NODE_MODULES) { | |
const dir = path.join.apply(path, [...parts.slice(0, i + 1), NODE_MODULES]); | |
dirs.push(dir); | |
} | |
} | |
return dirs; | |
} | |
aliasPaths(x) { | |
const paths = []; | |
Object.keys(this.alias).forEach(key => { | |
const value = this.alias[key]; | |
if (x.startsWith(key)) { | |
paths.push(x.replace(key, value)); | |
} | |
}); | |
return paths; | |
} | |
} | |
module.exports = Resolver; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment