UNPKG

@loadable/babel-plugin

Version:
171 lines (136 loc) 5.99 kB
"use strict"; exports.__esModule = true; exports.default = chunkNameProperty; var _vm = _interopRequireDefault(require("vm")); var _util = require("../util"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const JS_PATH_REGEXP = /^[./]+|(\.js$)/g; const MATCH_LEFT_HYPHENS_REPLACE_REGEX = /^-/g; // https://github.com/webpack/webpack/blob/master/lib/Template.js const WEBPACK_CHUNK_NAME_REGEXP = /webpackChunkName/; const WEBPACK_PATH_NAME_NORMALIZE_REPLACE_REGEX = /[^a-zA-Z0-9_!§$()=\-^°]+/g; const WEBPACK_MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g; function readWebpackCommentValues(str) { try { const values = _vm.default.runInNewContext(`(function(){return {${str}};})()`); return values; } catch (e) { throw Error(`compilation error while processing: /*${str}*/: ${e.message}`); } } function writeWebpackCommentValues(values) { try { const str = Object.keys(values).map(key => `${key}: ${JSON.stringify(values[key])}`).join(', '); return ` ${str} `; } catch (e) { throw Error(`compilation error while processing: /*${values}*/: ${e.message}`); } } function getChunkNameComment(importArg) { if (!importArg.has('leadingComments')) return null; return importArg.get('leadingComments').find(comment => comment.node.value.match(WEBPACK_CHUNK_NAME_REGEXP)); } function getRawChunkNameFromCommments(importArg) { const chunkNameComment = getChunkNameComment(importArg); if (!chunkNameComment) return null; return readWebpackCommentValues(chunkNameComment.node.value); } function moduleToChunk(str) { if (typeof str !== 'string') return ''; return str.replace(JS_PATH_REGEXP, '').replace(WEBPACK_PATH_NAME_NORMALIZE_REPLACE_REGEX, '-').replace(WEBPACK_MATCH_PADDED_HYPHENS_REPLACE_REGEX, ''); } function replaceQuasi(str, stripLeftHyphen) { if (!str) return ''; const result = str.replace(WEBPACK_PATH_NAME_NORMALIZE_REPLACE_REGEX, '-'); if (!stripLeftHyphen) return result; return result.replace(MATCH_LEFT_HYPHENS_REPLACE_REGEX, ''); } function chunkNameProperty({ types: t }) { function transformQuasi(quasi, first, single) { return t.templateElement({ raw: single ? moduleToChunk(quasi.value.raw) : replaceQuasi(quasi.value.raw, first), cooked: single ? moduleToChunk(quasi.value.cooked) : replaceQuasi(quasi.value.cooked, first) }, quasi.tail); } function sanitizeChunkNameTemplateLiteral(node) { return t.callExpression(t.memberExpression(node, t.identifier('replace')), [t.regExpLiteral(WEBPACK_PATH_NAME_NORMALIZE_REPLACE_REGEX.source, 'g'), t.stringLiteral('-')]); } function combineExpressions(node) { const { expressions } = node; const { length } = expressions; if (length === 1) { return expressions[0]; } return expressions.slice(1).reduce((r, p) => t.binaryExpression('+', r, p), expressions[0]); } function generateChunkNameNode(callPath, prefix) { const importArg = (0, _util.getImportArg)(callPath); if (importArg.isTemplateLiteral()) { return prefix ? t.binaryExpression('+', t.stringLiteral(prefix), sanitizeChunkNameTemplateLiteral(combineExpressions(importArg.node))) : t.templateLiteral(importArg.node.quasis.map((quasi, index) => transformQuasi(quasi, index === 0, importArg.node.quasis.length === 1)), importArg.node.expressions); } return t.stringLiteral(moduleToChunk(importArg.node.value)); } function getExistingChunkNameComment(callPath) { const importArg = (0, _util.getImportArg)(callPath); const values = getRawChunkNameFromCommments(importArg); return values; } function isAgressiveImport(callPath) { const importArg = (0, _util.getImportArg)(callPath); return importArg.isTemplateLiteral() && importArg.node.expressions.length > 0; } function addOrReplaceChunkNameComment(callPath, values) { const importArg = (0, _util.getImportArg)(callPath); const chunkNameComment = getChunkNameComment(importArg); if (chunkNameComment) { chunkNameComment.remove(); } importArg.addComment('leading', writeWebpackCommentValues(values)); } function chunkNameFromTemplateLiteral(node) { const [q1] = node.quasis; const v1 = q1 ? q1.value.cooked : ''; if (!node.expressions.length) return v1; return `${v1}[request]`; } function getChunkNamePrefix(chunkName) { if (typeof chunkName !== 'string') return ''; const match = chunkName.match(/(.+?)\[(request|index)\]$/); return match ? match[1] : ''; } function replaceChunkName(callPath) { const agressiveImport = isAgressiveImport(callPath); const values = getExistingChunkNameComment(callPath); let { webpackChunkName } = values || {}; if (!agressiveImport && values) { addOrReplaceChunkNameComment(callPath, values); return t.stringLiteral(webpackChunkName); } let chunkNameNode = generateChunkNameNode(callPath, getChunkNamePrefix(webpackChunkName)); if (t.isTemplateLiteral(chunkNameNode)) { webpackChunkName = chunkNameFromTemplateLiteral(chunkNameNode); chunkNameNode = sanitizeChunkNameTemplateLiteral(chunkNameNode); } else if (t.isStringLiteral(chunkNameNode)) { webpackChunkName = chunkNameNode.value; } addOrReplaceChunkNameComment(callPath, _extends({}, values, { webpackChunkName })); return chunkNameNode; } return ({ callPath, funcPath }) => { const chunkName = replaceChunkName(callPath); return t.objectMethod('method', t.identifier('chunkName'), funcPath.node.params, t.blockStatement([t.returnStatement(chunkName)])); }; }