babel-plugin-webpack-alias-7
Version:
Babel 7 plugin for webpack aliases
175 lines (123 loc) • 6.15 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _helperPluginUtils = require("@babel/helper-plugin-utils");
var _core = require("@babel/core");
var _path = require("path");
var _fs = _interopRequireDefault(require("fs"));
var _lodash = _interopRequireDefault(require("lodash.isempty"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
const PLUGIN_KEY = 'webpack alias';
const REQUIRE = 'require';
const DEFAULT_CONFIG_NAMES = ['webpack.config.js', 'webpack.config.babel.js'];
let configPath;
let webpackConfig;
let aliasConfig = {};
let aliases;
const fileExists = path => {
try {
return !_fs.default.accessSync(path, _fs.default.F_OK);
} catch (e) {
return false;
}
};
const getConfigPath = configPaths => {
let conf = null; // Try all config paths and return for the first found one
configPaths.some(configPath => {
const resolvedConfigPath = (0, _path.resolve)(process.cwd(), configPath);
if (resolvedConfigPath && fileExists(resolvedConfigPath)) {
conf = resolvedConfigPath;
}
return conf;
});
return conf;
};
var _default = (0, _helperPluginUtils.declare)(api => {
api.assertVersion(7);
return {
name: 'webpack alias',
pre(state) {
const plugins = state.opts.plugins;
const plugin = plugins.find(plugin => plugin.key === PLUGIN_KEY);
const config = plugin.options.config;
const configPaths = config ? [config].concat(DEFAULT_CONFIG_NAMES) : DEFAULT_CONFIG_NAMES; // Get webpack config
configPath = getConfigPath(configPaths); // If the config comes back as null, we didn't find it, so throw an exception.
if (!configPath) {
throw new Error(`Cannot find any of these configuration files: ${configPaths.join(', ')}`);
} // Require the config
webpackConfig = require(configPath);
if (Array.isArray(webpackConfig)) {
// Uses webpacks multi-compiler option
aliasConfig = webpackConfig.reduce((previous, current) => {
const next = Object.assign({}, previous);
if (current.resolve && current.resolve.alias) {
Object.assign(next, current.resolve.alias);
}
return next;
}, {});
} else if (!(0, _lodash.default)(webpackConfig.resolve)) {
aliasConfig = webpackConfig.resolve.alias;
} // Exit if there's no alias config
if ((0, _lodash.default)(aliasConfig)) {
throw new Error('The webpack config file does not contain an alias configuration');
}
aliases = Object.keys(aliasConfig);
},
visitor: {
CallExpression(path, state) {
const nodeArguments = path.node.arguments;
const _state$filename = state.filename,
filename = _state$filename === void 0 ? '' : _state$filename; // Prevent @babel/register from running babel to run on the webpack config
if (filename === (0, _path.resolve)(configPath)) {
return;
} // If not a require statement do nothing
if (!_core.types.isIdentifier(path.node.callee, {
name: REQUIRE
})) {
return;
} // Make sure required value is a string
if (nodeArguments.length === 0 || !_core.types.isStringLiteral(nodeArguments[0])) {
return;
} // Get the path of the StringLiteral
const _nodeArguments = _slicedToArray(nodeArguments, 1),
filePath = _nodeArguments[0].value;
for (const alias of aliases) {
let aliasDestination = aliasConfig[alias];
const regex = new RegExp(`^${alias}(\/|$)`);
if (regex.test(filePath)) {
// notModuleRegExp from https://github.com/webpack/enhanced-resolve/blob/master/lib/Resolver.js
const notModuleRegExp = /^\.$|^\.[\\\/]|^\.\.$|^\.\.[\/\\]|^\/|^[A-Z]:[\\\/]/i;
const isModule = !notModuleRegExp.test(aliasDestination);
if (isModule) {
path.node.arguments = [_core.types.StringLiteral(aliasDestination)];
return;
} // If the filepath is not absolute, make it absolute
if (!(0, _path.isAbsolute)(aliasDestination)) {
aliasDestination = (0, _path.join)(process.cwd(), aliasDestination);
}
let relativeFilePath = (0, _path.relative)((0, _path.dirname)(filename), aliasDestination); // In case the file path is the root of the alias, need to put a dot to avoid having an absolute path
if (relativeFilePath.length === 0) {
relativeFilePath = '.';
}
let requiredFilePath = filePath.replace(alias, relativeFilePath); // If the file is requiring the current directory which is the alias, add an extra slash
if (requiredFilePath === '.') {
requiredFilePath = './';
} // In the case of a file requiring a child directory of the current directory, we need to add a dot slash
if (['.', '/'].indexOf(requiredFilePath[0]) === -1) {
requiredFilePath = `./${requiredFilePath}`;
} // TODO: should honor enforceExtension and then use extensionConf to make sure extension
path.node.arguments = [_core.types.StringLiteral(requiredFilePath)];
return;
}
}
}
}
};
});
exports.default = _default;