UNPKG

worker-injector-generator-plugin

Version:

A very simple webpack plugin to generate injection code for workers that share common code with the main web build.

86 lines (75 loc) 3.48 kB
// Making it be ES5, no need for fancy typescript // we just use a function /** * Options include * @param options.name the name of the generated file * @param options.publicPath (optional) a public path to use, otherwise output.publicPath will be used * @param options.importScripts the scripts to import as an array of string * @param options.isAsync whether to use async code execution, not good for debugging */ function WorkerInjectorGeneratorPlugin(options) { this.options = options; } function getActualPathToIncludeCode(pathToInclude, hash) { // for that we are mapping var actualPathToInclude = pathToInclude; // and we need to make sure there is no trailing slash because we already // have it in the publicPathToUse if (actualPathToInclude[0] === "/") { actualPathToInclude = actualPathToInclude.substr(1); } // we replace the [hash] with the hash that is generated by the compiler actualPathToInclude = actualPathToInclude.replace(/\[hash\]/g, hash); // now we return that and join it with commas return "base+" + JSON.stringify(actualPathToInclude); } // this is where the magic happens WorkerInjectorGeneratorPlugin.prototype.apply = function (compiler) { // we extract the info from the options var name = this.options.name; var publicPathByOptions = this.options.publicPath; var pathsToInclude = this.options.importScripts; var isAsync = this.options.isAsync; // now we call tapAsync compiler.hooks.emit.tapAsync(this.constructor.name, function (compilation, callback) { // we get the compiler info via the outputOptions such as the public path var publicPathByCompilation = compilation.outputOptions.publicPath; // now we go in order of priority var publicPathToUse = publicPathByOptions || publicPathByCompilation || "/"; // we need to add the slash if it's not there if (publicPathToUse[publicPathToUse.length - 1] !== "/") { publicPathToUse += "/"; } // we get the hash that is used for this compilation step var hash = compilation.hash; // now we generate the file content, pretty standard, first build the base url that will be // the protocol + hostname + port (if available) var fileContent = 'var base=location.protocol+"//"+location.host+' + JSON.stringify(publicPathToUse) + ';window=self;'; if (isAsync) { fileContent += 'function h(r){return r.text()};function e(m){Function(m)()};' // now we add the window self line and the import scripts line fileContent += pathsToInclude.map(function (pathToInclude) { return 'fetch(' + getActualPathToIncludeCode(pathToInclude, hash) + ').then(h).then(e)' }).join(";") + ";"; } else { // now we add the window self line and the import scripts line fileContent += 'self.importScripts(' + pathsToInclude.map(function (pathToInclude) { return getActualPathToIncludeCode(pathToInclude, hash); }).join(",") + ");"; } // now we need the actual name, with the hash as well var actualName = name.replace(/\[hash\]/g, hash); // and generate a buffer from the content to feed the compilation steps var Buf = Buffer.from(fileContent, 'utf8'); compilation.assets[actualName] = { source: function () { return Buf }, size: function () { return Buffer.byteLength(fileContent) } } // and we are done callback(); }); } // export it :D module.exports = WorkerInjectorGeneratorPlugin;