UNPKG

vite-plugin-dynamic-base

Version:

Resolve all resource files dynamic publicPath, like Webpack's __webpack_public_path__

153 lines 6.58 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformHtml = exports.transformLegacyHtml = exports.transformAsset = exports.transformChunk = void 0; const node_html_parser_1 = require("node-html-parser"); const utils_1 = require("./utils"); const ast_1 = require("./ast"); function transformChunk(codeStr, options) { return __awaiter(this, void 0, void 0, function* () { const { base, publicPath } = options; const [spanOffset, ast] = yield (0, ast_1.parseCode)(codeStr); const strings = (0, ast_1.collectMatchingStrings)(base, ast); if (strings.length === 0) { return codeStr; } const code = new ast_1.StringAsBytes(codeStr); let lastIdx = 0; let transformedCode = ""; for (const str of strings) { const prev = code.slice(lastIdx, str.span.start - spanOffset); let transformed; if (str.type === 'TemplateElement') { transformed = (0, utils_1.replaceInTemplateElement)(str, base, publicPath); } else if (str.type === 'StringLiteral') { transformed = (0, utils_1.replaceInStringLiteral)(str, base, publicPath); } lastIdx = str.span.end - spanOffset; transformedCode += prev + transformed; } transformedCode += code.slice(lastIdx); return transformedCode; }); } exports.transformChunk = transformChunk; function transformAsset(code, options) { const { assetsDir, base } = options; let content = (0, utils_1.replace)(`${base}${assetsDir}/`, '', code); content = (0, utils_1.replace)(base, '', content); return content; } exports.transformAsset = transformAsset; function transformLegacyHtml(code, options) { const { base, publicPath } = options; let content = (0, utils_1.replaceSrc)(publicPath, code); content = (0, utils_1.replace)(base, '/', content); content = (0, utils_1.replaceImport)(publicPath, content); const document = (0, node_html_parser_1.parse)(content, { comment: true }); const legacyPolyfill = document.getElementById('vite-legacy-polyfill'); if (legacyPolyfill) { legacyPolyfill.setAttribute('data-src', legacyPolyfill.getAttribute('src')); legacyPolyfill.removeAttribute('src'); legacyPolyfill.innerHTML = `!(function() { var e = document.createElement('script') e.src = ${publicPath} + document.getElementById('vite-legacy-polyfill').getAttribute('data-src'); e.onload = function() { System.import(${publicPath}+document.getElementById('vite-legacy-entry').getAttribute('data-src')) }; document.body.appendChild(e) })();`; } const legacyEntry = document.getElementById('vite-legacy-entry'); if (legacyEntry) { legacyEntry.innerHTML = ''; } content = document.outerHTML; return content; } exports.transformLegacyHtml = transformLegacyHtml; function generateInjectCode(preloads, targetPath, parentTagSelector, endTag) { return ` <script> (function(){ var preloads = ${JSON.stringify(preloads)}; function setAttribute(target, attrs) { for (var key in attrs) { target.setAttribute(key, attrs[key]); } return target; }; for(var i = 0; i < preloads.length; i++){ var item = preloads[i] var childNode = document.createElement(item.tagName); setAttribute(childNode, item.attrs) if(${targetPath}) { if(item.tagName == 'link') { setAttribute(childNode, { href: ${targetPath} + item.attrs.href }) } else if (item.tagName == 'script') { setAttribute(childNode, { src: ${targetPath} + item.attrs.src }) } } document.getElementsByTagName(${parentTagSelector})[0].appendChild(childNode); } })(); </script> ${endTag} `; } function transformHtml(html, options, transformIndexHtmlConfig) { const { base, publicPath } = options; const { publicPath: htmlPublicPath, insertBodyAfter } = transformIndexHtmlConfig || {}; const targetPath = htmlPublicPath || publicPath; const document = (0, node_html_parser_1.parse)(html, { comment: true }); const baseMarker = `${base}`; const assetsTags = document.querySelectorAll(`link[href^="${baseMarker}"],script[src^="${baseMarker}"]`); const preloads = assetsTags.map(o => { const result = { parentTagName: o.parentNode.rawTagName, tagName: o.rawTagName, attrs: Object.assign({}, o.attrs, o.attrs.src ? { src: o.attrs.src.replace(baseMarker, '/') } : { href: o.attrs.href.replace(baseMarker, '/') }) }; o.parentNode.removeChild(o); return result; }); let content = document.outerHTML; if (insertBodyAfter) { // 原逻辑:所有资源插入到 body 后 const endTag = '</body>'; const injectCode = generateInjectCode(preloads, targetPath, 'item.parentTagName', endTag); content = content.replace(endTag, injectCode); } else { // 新逻辑:根据 parentTagName 分组,在对应位置插入 const groupedPreloads = {}; preloads.forEach(item => { const parent = item.parentTagName; if (!groupedPreloads[parent]) { groupedPreloads[parent] = []; } groupedPreloads[parent].push(item); }); // 按照 head -> body 的顺序处理 const parentTags = ['head', 'body']; for (const parentTag of parentTags) { const items = groupedPreloads[parentTag]; if (!items || items.length === 0) continue; const endTag = `</${parentTag}>`; const injectCode = generateInjectCode(items, targetPath, `'${parentTag}'`, endTag); content = content.replace(endTag, injectCode); } } return content; } exports.transformHtml = transformHtml; //# sourceMappingURL=transform.js.map