es-dev-server
Version:
Development server for modern web apps
132 lines • 5.39 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.injectPolyfillsLoader = void 0;
const tslib_1 = require("tslib");
const dom5_fork_1 = require("@open-wc/building-utils/dom5-fork");
const building_utils_1 = require("@open-wc/building-utils");
const parse5_1 = require("parse5");
const deepmerge_1 = tslib_1.__importDefault(require("deepmerge"));
const polyfills_loader_1 = require("polyfills-loader");
const systemjs_transform_resolver_1 = tslib_1.__importDefault(require("../browser-scripts/systemjs-transform-resolver"));
const constants_1 = require("../constants");
const utils_1 = require("./utils");
const allPolyfills = {
coreJs: true,
regeneratorRuntime: true,
fetch: true,
abortController: true,
webcomponents: true,
};
const allPolyfillsWithSystemjs = {
...allPolyfills,
custom: [
{
name: 'systemjs',
path: require.resolve('systemjs/dist/system.min.js'),
initializer: systemjs_transform_resolver_1.default,
},
],
};
/**
* In max compatibility mode, we need to load the regenerator runtime on all browsers since
* we're always compiling to es5.
*/
const maxPolyfills = {
...allPolyfillsWithSystemjs,
regeneratorRuntime: 'always',
};
function getPolyfillsConfig(cfg) {
switch (cfg.compatibilityMode) {
case constants_1.compatibilityModes.MAX:
return maxPolyfills;
case constants_1.compatibilityModes.MIN:
return allPolyfills;
case constants_1.compatibilityModes.AUTO:
case constants_1.compatibilityModes.ALWAYS:
if (cfg.compatibilityMode === constants_1.compatibilityModes.AUTO && cfg.uaCompat.modern) {
return {};
}
if (cfg.uaCompat.supportsEsm) {
return allPolyfills;
}
return allPolyfillsWithSystemjs;
default:
return {};
}
}
function findScripts(cfg, documentAst) {
var _a;
const scriptNodes = building_utils_1.findJsScripts(documentAst, (_a = cfg.polyfillsLoaderConfig) === null || _a === void 0 ? void 0 : _a.exclude);
const files = [];
const inlineScripts = [];
const inlineScriptNodes = [];
scriptNodes.forEach((scriptNode, i) => {
const type = polyfills_loader_1.getScriptFileType(scriptNode);
let src = dom5_fork_1.getAttribute(scriptNode, 'src');
if (!src) {
src = `inline-script-${i}.js?source=${encodeURIComponent(cfg.indexUrl)}`;
inlineScripts.push({
path: src,
type,
content: dom5_fork_1.getTextContent(scriptNode),
});
inlineScriptNodes.push(scriptNode);
}
files.push({
type,
path: src,
});
});
return { files, inlineScripts, scriptNodes, inlineScriptNodes };
}
function hasPolyfills(polyfills) {
if (!polyfills) {
return false;
}
const { hash, custom, ...rest } = polyfills;
return (custom && custom.length > 0) || Object.values(rest).some(v => v !== false);
}
/**
* transforms index.html, extracting any modules and import maps and adds them back
* with the appropriate polyfills, shims and a script loader so that they can be loaded
* at the right time
*/
async function injectPolyfillsLoader(cfg) {
const polyfillModules = ([constants_1.compatibilityModes.AUTO, constants_1.compatibilityModes.ALWAYS].includes(cfg.compatibilityMode) &&
!cfg.uaCompat.supportsEsm) ||
cfg.compatibilityMode === constants_1.compatibilityModes.MAX;
const documentAst = parse5_1.parse(cfg.htmlString);
const { files, inlineScripts, scriptNodes } = findScripts(cfg, documentAst);
const polyfillsConfig = getPolyfillsConfig(cfg);
const polyfillsLoaderConfig = deepmerge_1.default({
modern: {
files: files.map(f => ({
...f,
type: f.type === polyfills_loader_1.fileTypes.MODULE && polyfillModules ? polyfills_loader_1.fileTypes.SYSTEMJS : f.type,
})),
},
polyfills: polyfillsConfig,
preload: false,
}, cfg.polyfillsLoaderConfig || {});
if (!hasPolyfills(polyfillsLoaderConfig.polyfills) && !polyfillModules) {
// no polyfils module polyfills, so we don't need to inject a loader
return { indexHTML: cfg.htmlString, inlineScripts: [], polyfills: [] };
}
// we will inject a loader, so we need to remove the inline script nodes as the loader
// will include them as virtual modules
for (const scriptNode of scriptNodes) {
// remove script from document
dom5_fork_1.remove(scriptNode);
}
utils_1.logDebug('[polyfills-loader] config', polyfillsLoaderConfig);
const result = polyfills_loader_1.injectPolyfillsLoader(parse5_1.serialize(documentAst), polyfillsLoaderConfig);
utils_1.logDebug('[polyfills-loader] generated polyfills: ', result.polyfillFiles.map(p => ({ ...p, content: '[stripped]' })));
utils_1.logDebug('Inline scripts generated by polyfills-loader', inlineScripts.map(p => ({ ...p, content: '[stripped]' })));
return {
indexHTML: result.htmlString,
inlineScripts,
polyfills: result.polyfillFiles,
};
}
exports.injectPolyfillsLoader = injectPolyfillsLoader;
//# sourceMappingURL=inject-polyfills-loader.js.map