Created
September 8, 2020 10:27
-
-
Save songlairui/b8e75401e8c1cc9473d8f072e47ab7d1 to your computer and use it in GitHub Desktop.
require 项目中 route 获取去除 component 的内容
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
/* eslint-disable node/no-deprecated-api */ | |
const fs = require('fs') | |
const t = require('@babel/types') | |
const parser = require('@babel/parser') | |
const generator = require('@babel/generator').default | |
const traverse = require('@babel/traverse').default | |
/** | |
* 将 es6 的 routes 转为 cjs 用于 node 脚本直接使用 | |
* 清楚了 components 的引用 | |
* @param {*} targetFileRaw | |
* 默认保留 字段 | |
*/ | |
function transformRouteJs(targetFileRaw, KEPT_PROP = ['name', 'path', 'children']) { | |
const ast = parser.parse(targetFileRaw, { ast: true, sourceType: 'module' }) | |
const exportVars = [] | |
let hasDefault = false | |
traverse(ast, { | |
ExportNamedDeclaration(nodePath) { | |
const declaration = nodePath.node.declaration | |
nodePath.replaceWith(declaration) | |
const varName = declaration.declarations | |
.map(({ id: { start, end } }) => targetFileRaw.slice(start, end)) | |
.join('') | |
exportVars.push(varName) | |
}, | |
ExportDefaultDeclaration(nodePath) { | |
hasDefault = true | |
const declaration = nodePath.node.declaration | |
// nodePath. | |
nodePath.insertBefore( | |
t.variableDeclaration('const', [ | |
t.variableDeclarator(t.identifier('__default'), declaration), | |
]) | |
) | |
nodePath.replaceWith( | |
t.expressionStatement( | |
t.assignmentExpression( | |
'=', | |
t.memberExpression(t.identifier('module'), t.identifier('exports')), | |
t.identifier('__default') | |
) | |
) | |
) | |
}, | |
ImportDeclaration(nodePath) { | |
if (nodePath.node.source.value.startsWith('@')) { | |
nodePath.remove() | |
return | |
} | |
const specifiersRaw = nodePath.node.specifiers | |
.map(({ start, end }) => { | |
return targetFileRaw.slice(start, end) | |
}) | |
.join('') | |
nodePath.replaceWith( | |
t.variableDeclaration('const', [ | |
t.variableDeclarator( | |
t.identifier(specifiersRaw), | |
t.callExpression(t.identifier('require'), [nodePath.node.source]) | |
), | |
]) | |
) | |
}, | |
Property(nodePath) { | |
if (!KEPT_PROP.includes(nodePath.node.key.name)) { | |
nodePath.remove() | |
} | |
}, | |
}) | |
return `${generator(ast).code}\ | |
${ | |
exportVars.length > 0 | |
? hasDefault | |
? `\ | |
Object.assign(__default, { ${exportVars.join(', ')} }) | |
` | |
: `\ | |
module.exports = { ${exportVars.join(', ')} }` | |
: '' | |
} | |
` | |
} | |
const defaultJsLoader = require.extensions['.js'] | |
const hackRequire = function() { | |
require.extensions['.js'] = function(module, filename) { | |
const originCode = fs.readFileSync(filename).toString() | |
try { | |
defaultJsLoader(module, filename) | |
} catch (err) { | |
// console.info('尝试转换 es6', err.message) | |
delete require.cache[filename] | |
const transformedCode = transformRouteJs(originCode) | |
module._compile(transformedCode, filename) | |
} | |
} | |
} | |
const restoreRequire = function() { | |
require.extensions['.js'] = defaultJsLoader | |
} | |
const requireWithAutoHack = function(filename) { | |
hackRequire() | |
const result = require(filename) | |
restoreRequire() | |
return result | |
} | |
module.exports = { | |
defaultJsLoader, | |
transformRouteJs, | |
hackRequire, | |
restoreRequire, | |
requireWithAutoHack, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment