fusion-cli/build/loaders/worker-loader.js (91 lines of code) (raw):
/** Copyright (c) 2018 Uber Technologies, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
/* eslint-env node */
const path = require('path');
const loaderUtils = require('loader-utils');
const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
const WebWorkerTemplatePlugin = require('webpack/lib/webworker/WebWorkerTemplatePlugin');
class WorkerLoaderError extends Error {
constructor(err) {
super(err);
this.name = err.name || 'Loader Error';
this.message = `${err.name}\n\n${err.message}\n`;
/* $FlowFixMe */
this.stack = false;
}
}
const getWorker = (file, content, options) => {
const publicPath = options.publicPath
? JSON.stringify(options.publicPath)
: '__webpack_public_path__';
const publicWorkerPath = `${publicPath} + ${JSON.stringify(file)}`;
if (options.inline) {
const InlineWorkerPath = JSON.stringify(
`!!${path.join(__dirname, 'InlineWorker.js')}`
);
const fallbackWorkerPath =
options.fallback === false ? 'null' : publicWorkerPath;
return `require(${InlineWorkerPath})(${JSON.stringify(
content
)}, ${fallbackWorkerPath})`;
}
return `${publicWorkerPath}`;
};
module.exports = function loader() {};
module.exports.pitch = function(request /* : any*/) {
const options = loaderUtils.getOptions(this) || {};
if (!this.webpack) {
throw new WorkerLoaderError({
name: 'Worker Loader',
message: 'This loader is only usable with webpack',
});
}
this.cacheable(false);
const cb = this.async();
const filename = loaderUtils.interpolateName(
this,
options.name || '[hash].worker.js',
{
context: options.context || this.rootContext || this.options.context,
regExp: options.regExp,
}
);
const worker = {};
worker.options = {
filename,
chunkFilename: `[id].${filename}`,
globalObject: 'self',
namedChunkFilename: null,
};
worker.compiler = this._compilation.createChildCompiler(
'worker',
worker.options
);
new WebWorkerTemplatePlugin(worker.options).apply(worker.compiler);
new SingleEntryPlugin(this.context, `!!${request}`, 'main').apply(
worker.compiler
);
const subCache = `subcache ${__dirname} ${request}`;
worker.compilation = compilation => {
if (compilation.cache) {
if (!compilation.cache[subCache]) {
compilation.cache[subCache] = {};
}
compilation.cache = compilation.cache[subCache];
}
};
const plugin = {name: 'WorkerLoader'};
worker.compiler.hooks.compilation.tap(plugin, worker.compilation);
worker.compiler.runAsChild((err, entries, compilation) => {
if (err) return cb(err);
if (entries[0]) {
worker.file = entries[0].files[0];
worker.factory = getWorker(
worker.file,
compilation.assets[worker.file].source(),
options
);
if (options.fallback === false) {
delete this._compilation.assets[worker.file];
}
return cb(null, `module.exports = ${worker.factory};\n`);
}
return cb(null, null);
});
};