UNPKG

babel-plugin-define-variables

Version:

一个类似 webpack.DefinePlugin 的 Babel 插件,用于在编译时定义全局变量和常量

104 lines (95 loc) 3.45 kB
const hash = require('hash-sum'); const { getConstCache, var2Expression, expr2str, getPackage, mergeObject, hasOwnProp } = require('./utils'); function createHash(filename, pkg) { if (pkg) filename = `${pkg.name}!${filename}`; return `${hash(filename.replace(/\\/g, '/'))}`; } module.exports = function ({ types: t }) { const options = { builtIns: { filename: true, filehash: true, dirname: true, now: true, timestamp: true, packagename: true, packageversion: true } }; function IdentifierVisitor(path, { opts, cache }) { let parent = path.parent; if (!parent) return; if (['FunctionDeclaration', 'ClassMethod', 'ObjectMethod'].includes(parent.type)) return; if (parent.type === 'ObjectProperty' && parent.key === path.node) return; if (parent.type === 'VariableDeclarator' && parent.id === path.node) return; let identifier = expr2str(path.node); if (parent.type === 'MemberExpression') { let parentPath = path.parentPath; while (parentPath && parentPath.node.type === 'MemberExpression' && path.node === parentPath.node.property) { identifier = `${expr2str(parentPath.node.object)}.${identifier}`; path = parentPath; parentPath = parentPath.parentPath; } } else if (parent.type === 'CallExpression' && expr2str(parent.callee) === identifier) { if (identifier !== '__packageversion__' || !parent.arguments.length || !t.isStringLiteral(parent.arguments[0])) return; path = path.parentPath; let packageName = expr2str(path.node.arguments[0]); let packagePath = packageName && require.resolve(packageName); let pkg = getPackage(packagePath); path.replaceWith(t.stringLiteral(pkg ? pkg.version : '')); return; } const defines = (opts && opts.defines) || {}; if (options.builtIns.filename && identifier === '__filename__') { path.replaceWith(t.stringLiteral(cache.filename)); } else if (options.builtIns.dirname && identifier === '__dirname__') { path.replaceWith(t.stringLiteral(cache.dirname)); } else if (options.builtIns.now && identifier === '__now__') { path.replaceWith(t.stringLiteral(cache.now)); } else if (options.builtIns.timestamp && identifier === '__timestamp__') { path.replaceWith(t.numericLiteral(Date.now())); } else if (options.builtIns.filehash && identifier === '__filehash__') { path.replaceWith(t.stringLiteral(createHash(cache.filename, cache.pkg))); } else if (hasOwnProp(defines, identifier)) { path.replaceWith(var2Expression(defines[identifier])); } else if (cache.pkg) { if (options.builtIns.packagename && identifier === '__packagename__') { path.replaceWith(t.stringLiteral(cache.pkg.name)); } else if (options.builtIns.packageversion && identifier === '__packageversion__') { path.replaceWith(t.stringLiteral(cache.pkg.version)); } } } return { visitor: { Program: { enter(path, state) { const { file: { opts: { filename } }, opts, } = state; const cache = getConstCache(filename); mergeObject(options, opts); path.traverse({ Identifier: IdentifierVisitor }, { cache, opts }); }, }, } }; };