Skip to content

Instantly share code, notes, and snippets.

@songlairui
Created September 8, 2020 10:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save songlairui/b8e75401e8c1cc9473d8f072e47ab7d1 to your computer and use it in GitHub Desktop.
Save songlairui/b8e75401e8c1cc9473d8f072e47ab7d1 to your computer and use it in GitHub Desktop.
require 项目中 route 获取去除 component 的内容
/* 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