@regru/webpack-babel-multi-target-plugin
Version:
A Webpack plugin that works with Babel to allow deployment of ES2015 builds targeted to modern browsers, with an ES5 fallback for legacy browsers.
128 lines • 6.29 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const path_1 = require("path");
const webpack_sources_1 = require("webpack-sources");
const babel_multi_target_options_1 = require("../babel.multi.target.options");
const plugin_name_1 = require("../plugin.name");
const safari_nomodule_fix_dependency_1 = require("./safari.nomodule.fix.dependency");
class SafariNoModuleFixPlugin {
constructor(mode) {
this.mode = mode;
}
apply(compiler) {
compiler.hooks.afterPlugins.tap(plugin_name_1.PLUGIN_NAME, () => {
if (this.mode === babel_multi_target_options_1.SafariNoModuleFix.external) {
this.initExternal(compiler);
}
this.initHtmlUpdate(compiler);
return compiler;
});
}
initExternal(compiler) {
// set up the dependency to be handled by the NormalModuleFactory
// compiler.hooks.compilation.tap(
// this.constructor.name,
// (compilation: Compilation, { normalModuleFactory }: { normalModuleFactory: NormalModuleFactory }) => {
// (compilation.dependencyFactories as Map<any, any>).set(
// SafariNoModuleFixDependency,
// normalModuleFactory
// );
// }
// );
//
// // add the nomodule fix file as an additional entry so that it gets put into its own file
// compiler.hooks.make.tapPromise(PLUGIN_NAME, (compilation: Compilation) => {
// const dep = new SafariNoModuleFixDependency();
// return new Promise((resolve, reject) => compilation.addEntry(dep.context, dep, dep.filename, (err: Error) => {
// if (err) {
// return reject();
// }
// resolve();
// }));
// });
/**
* add the nomodule fix script as an additionalAsset
* This has the benefit of avoiding the webpack bootstrap boilerplate getting added, which would be completely
* useless and wasted bytes since it's not going to be loading any other dependencies. However, it also means skipping
* the rest of the JS infrastructure, so no loaders or uglificiation :(
*
* TODO: maybe it's possible to conditionally mess with the mainTemplate so that it can be loaded like a real entry, but skip all the boilerplate
*/
compiler.hooks.compilation.tap(plugin_name_1.PLUGIN_NAME, (compilation) => {
if (!compilation.name) {
return;
}
compilation.hooks.additionalAssets.tapPromise(plugin_name_1.PLUGIN_NAME, () => __awaiter(this, void 0, void 0, function* () {
compilation.assets[safari_nomodule_fix_dependency_1.SafariNoModuleFixDependency.filename] = new webpack_sources_1.RawSource(fs_1.readFileSync(safari_nomodule_fix_dependency_1.SafariNoModuleFixDependency.path, 'utf-8'));
return;
}));
const htmlWebpackPlugin = compiler.options.plugins
// instanceof can act wonky since we don't actually keep our own dependency on html-webpack-plugin
// should we?
.find(plugin => plugin.constructor.name === 'HtmlWebpackPlugin');
if (!htmlWebpackPlugin) {
return;
}
});
}
initHtmlUpdate(compiler) {
const htmlWebpackPlugin = compiler.options.plugins
// instanceof can act wonky since we don't actually keep our own dependency on html-webpack-plugin
// should we?
.find(plugin => plugin.constructor.name === 'HtmlWebpackPlugin');
if (!htmlWebpackPlugin) {
return;
}
compiler.hooks.compilation.tap(plugin_name_1.PLUGIN_NAME, (compilation) => {
if (compilation.name) {
return;
}
compilation.hooks.htmlWebpackPluginAlterAssetTags.tapPromise(`${plugin_name_1.PLUGIN_NAME} add safari nomodule fix tags`, (htmlPluginData) => __awaiter(this, void 0, void 0, function* () {
htmlPluginData.head.unshift(this.createSafariNoModuleFixTag());
return htmlPluginData;
}));
});
}
createSafariNoModuleFixTag() {
// TODO: minify the nomodule fix js
const tag = {
tagName: 'script',
closeTag: true,
attributes: {
nomodule: true,
type: 'application/javascript',
},
};
if (this.mode === babel_multi_target_options_1.SafariNoModuleFix.external) {
tag.attributes.src = '/' + safari_nomodule_fix_dependency_1.SafariNoModuleFixDependency.filename;
return tag;
}
const fixContent = fs_1.readFileSync(path_1.resolve(__dirname, 'safari.nomodule.fix.js'));
if (this.mode === true || this.mode === babel_multi_target_options_1.SafariNoModuleFix.inline) {
tag.innerHTML = fixContent
.toString('utf-8');
return tag;
}
tag.attributes.src = 'data:application/javascript';
const isBase64 = this.mode === babel_multi_target_options_1.SafariNoModuleFix.inlineDataBase64;
if (isBase64) {
tag.attributes.src += `;base64,${fixContent.toString('base64')}`;
return tag;
}
tag.attributes.src += ',' + encodeURIComponent(fixContent.toString('utf-8')
.replace(/\n/g, '')
.replace(/\s{2,}/g, ' '));
return tag;
}
}
exports.SafariNoModuleFixPlugin = SafariNoModuleFixPlugin;
//# sourceMappingURL=safari.nomodule.fix.plugin.js.map