Last active
March 7, 2020 02:55
-
-
Save songlairui/287eaac29cda65cd5f1f7471b6661503 to your computer and use it in GitHub Desktop.
madge 识别 vue 单文件组件. 支持 alias 需添加 filing-cabinet 参数
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 precinct = require('precinct') | |
const compiler = require('vue-template-compiler') | |
const fs = require('fs') | |
const path = require('path') | |
const cabinet = require('filing-cabinet') | |
const debug = require('debug')('vue-madge polyfill'); | |
// 修饰 precinct.paperwork, 令之遇到vue文件, 去除template部分, 当作js文件处理 | |
function decoratePrecinct() { | |
const old = precinct.paperwork | |
if (!old._old) { | |
precinct.paperwork = function (filename, options) { | |
var ext = path.extname(filename); | |
let newOptions = options | |
if (newOptions.fileSystem && newOptions.fileSystem._vue) { | |
console.info('遭到了沿用') | |
delete newOptions.fileSystem | |
} | |
let newFilename = filename | |
if (ext === '.vue') { | |
newFilename = filename.replace(/\.vue$/, '.jsx') // 替换为 jsx 结尾 | |
newOptions = { | |
...options, fileSystem: { | |
readFileSync() { | |
const originStr = fs.readFileSync(filename, 'utf8'); | |
delete newOptions.fileSystem | |
return compiler.parseComponent(originStr, { pad: 'line' }).script.content | |
} | |
} | |
} | |
newOptions.fileSystem._vue = true | |
} | |
return old.call(this, newFilename, newOptions) | |
} | |
precinct.paperwork._old = old | |
} | |
} | |
// 配置 filing-cabiet 的Lookup, 让其能够取得带alias的vue路径如 '@/src/something.vue' | |
function configCabiet() { | |
let webpackResolve; | |
const isRelative = require('is-relative-path'); | |
// copy from cabiet | |
function stripLoader(dependency) { | |
const exclamationLocation = dependency.indexOf('!'); | |
if (exclamationLocation === -1) { return dependency; } | |
return dependency.slice(exclamationLocation + 1); | |
} | |
// copy from cabiet | |
function resolveWebpackPath({ dependency, filename, directory, webpackConfig }) { | |
if (!webpackResolve) { | |
webpackResolve = require('enhanced-resolve'); | |
} | |
webpackConfig = path.resolve(webpackConfig); | |
let loadedConfig; | |
try { | |
loadedConfig = require(webpackConfig); | |
if (typeof loadedConfig === 'function') { | |
loadedConfig = loadedConfig(); | |
} | |
} catch (e) { | |
debug('error loading the webpack config at ' + webpackConfig); | |
debug(e.message); | |
debug(e.stack); | |
return ''; | |
} | |
const resolveConfig = Object.assign({}, loadedConfig.resolve); | |
if (!resolveConfig.modules && (resolveConfig.root || resolveConfig.modulesDirectories)) { | |
resolveConfig.modules = []; | |
if (resolveConfig.root) { | |
resolveConfig.modules = resolveConfig.modules.concat(resolveConfig.root); | |
} | |
if (resolveConfig.modulesDirectories) { | |
resolveConfig.modules = resolveConfig.modules.concat(resolveConfig.modulesDirectories); | |
} | |
} | |
try { | |
const resolver = webpackResolve.create.sync(resolveConfig); | |
dependency = stripLoader(dependency); | |
const lookupPath = isRelative(dependency) ? path.dirname(filename) : directory; | |
return resolver(lookupPath, dependency); | |
} catch (e) { | |
debug('error when resolving ' + dependency); | |
debug(e.message); | |
debug(e.stack); | |
return ''; | |
} | |
} | |
// copy and modify from jsLookup in cabiet | |
function vueLookup({ dependency, filename, directory, config, webpackConfig, configPath, nodeModulesConfig, ast }) { | |
const type = cabinet._getJSType({ | |
config: config, | |
webpackConfig: webpackConfig, | |
filename: filename, | |
ast: ast | |
}); | |
switch (type) { | |
case 'webpack': | |
debug('using webpack resolver for es6'); | |
return resolveWebpackPath({ dependency, filename, directory, webpackConfig }); | |
case 'amd': | |
case 'commonjs': | |
case 'es6': | |
default: | |
throw new Error('only webpack ') | |
} | |
} | |
cabinet.register('.vue', vueLookup) | |
} | |
decoratePrecinct() | |
configCabiet() |
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
// polyfill for this version of node-precinct | |
// polyfill for madge to parse vue files (with <template/> <script/> dropped) | |
// https://github.com/dependents/node-precinct/blob/860d577c2f444de6f6f731d879907c41958eea8a/index.js | |
const precinct = require('precinct') | |
const compiler = require('vue-template-compiler') | |
const fs = require('fs') | |
const path = require('path') | |
function decorate() { | |
const old = precinct.paperwork | |
if (!old._old) { | |
precinct.paperwork = function(filename, options) { | |
var ext = path.extname(filename) | |
let newOptions = options | |
let newFilename = filename | |
if (ext === '.vue') { | |
newFilename = filename.replace(/\.vue$/, '.jsx') // 替换为 jsx 结尾 | |
newOptions = { | |
...options, | |
fileSystem: { | |
readFileSync() { | |
const originStr = fs.readFileSync(filename, 'utf8') | |
return compiler.parseComponent(originStr, { pad: 'line' }).script | |
.content | |
} | |
} | |
} | |
} | |
return old.call(this, newFilename, newOptions) | |
} | |
precinct.paperwork._old = old | |
} | |
} | |
decorate() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment