You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
6.9 KiB
168 lines
6.9 KiB
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
|
|
|
var path = _interopDefault(require('path'));
|
|
var loaderUtils = _interopDefault(require('loader-utils'));
|
|
var NodeTargetPlugin = _interopDefault(require('webpack/lib/node/NodeTargetPlugin'));
|
|
var SingleEntryPlugin = _interopDefault(require('webpack/lib/SingleEntryPlugin'));
|
|
var WebWorkerTemplatePlugin = _interopDefault(require('webpack/lib/webworker/WebWorkerTemplatePlugin'));
|
|
|
|
function loader() {}
|
|
var CACHE = {};
|
|
var tapName = 'workerize-loader';
|
|
|
|
function compilationHook(compiler, handler) {
|
|
if (compiler.hooks) {
|
|
return compiler.hooks.compilation.tap(tapName, handler);
|
|
}
|
|
|
|
return compiler.plugin('compilation', handler);
|
|
}
|
|
|
|
function parseHook(data, handler) {
|
|
if (data.normalModuleFactory.hooks) {
|
|
return data.normalModuleFactory.hooks.parser.for('javascript/auto').tap(tapName, handler);
|
|
}
|
|
|
|
return data.normalModuleFactory.plugin('parser', handler);
|
|
}
|
|
|
|
function exportDeclarationHook(parser, handler) {
|
|
if (parser.hooks) {
|
|
return parser.hooks.exportDeclaration.tap(tapName, handler);
|
|
}
|
|
|
|
return parser.plugin('export declaration', handler);
|
|
}
|
|
|
|
loader.pitch = function (request) {
|
|
var _this = this;
|
|
|
|
this.cacheable(false);
|
|
var options = loaderUtils.getOptions(this) || {};
|
|
var cb = this.async();
|
|
var compilerOptions = this._compiler.options || {};
|
|
var filename = (options.name || '[fullhash]') + '.worker.js';
|
|
var worker = {};
|
|
worker.options = {
|
|
filename: filename,
|
|
chunkFilename: filename,
|
|
publicPath: options.publicPath || compilerOptions.output.publicPath,
|
|
globalObject: 'self'
|
|
};
|
|
|
|
if (compilerOptions.output && compilerOptions.output.globalObject === 'window') {
|
|
console.warn('Warning (workerize-loader): output.globalObject is set to "window". It should be set to "self" or "this" to support HMR in Workers.');
|
|
}
|
|
|
|
worker.compiler = this._compilation.createChildCompiler("worker " + request, worker.options);
|
|
new WebWorkerTemplatePlugin(worker.options).apply(worker.compiler);
|
|
|
|
if (this.target !== 'webworker' && this.target !== 'web') {
|
|
new NodeTargetPlugin().apply(worker.compiler);
|
|
} // webpack >= v4 supports webassembly
|
|
|
|
|
|
var wasmPluginPath = null;
|
|
|
|
try {
|
|
wasmPluginPath = require.resolve('webpack/lib/web/FetchCompileWasmTemplatePlugin');
|
|
} catch (_err) {// webpack <= v3, skipping
|
|
}
|
|
|
|
if (wasmPluginPath) {
|
|
// eslint-disable-next-line global-require
|
|
var FetchCompileWasmTemplatePlugin = require(wasmPluginPath);
|
|
|
|
new FetchCompileWasmTemplatePlugin({
|
|
mangleImports: this._compiler.options.optimization.mangleWasmImports
|
|
}).apply(worker.compiler);
|
|
}
|
|
|
|
var bundleName = path.parse(this.resourcePath).name;
|
|
new SingleEntryPlugin(this.context, "!!" + path.resolve(__dirname, 'rpc-worker-loader.js') + "!" + request, bundleName).apply(worker.compiler);
|
|
compilationHook(worker.compiler, function (compilation, data) {
|
|
parseHook(data, function (parser, options) {
|
|
exportDeclarationHook(parser, function (expr) {
|
|
var decl = expr.declaration || expr;
|
|
var _parser$state = parser.state,
|
|
compilation = _parser$state.compilation,
|
|
current = _parser$state.current;
|
|
var entryModule = compilation.entries instanceof Map ? compilation.moduleGraph.getModule(compilation.entries.get(bundleName).dependencies[0]) : compilation.entries[0]; // only process entry exports
|
|
|
|
if (current.resource !== entryModule.resource) return;
|
|
var key = current.nameForCondition();
|
|
var exports = CACHE[key] || (CACHE[key] = {});
|
|
|
|
if (decl.id) {
|
|
exports[decl.id.name] = true;
|
|
} else if (decl.declarations) {
|
|
for (var i = 0; i < decl.declarations.length; i++) {
|
|
exports[decl.declarations[i].id.name] = true;
|
|
}
|
|
} else {
|
|
console.warn('[workerize] unknown export declaration: ', expr);
|
|
} // This is for Webpack 5: mark the exports as used so it does not get tree-shaken away on production build
|
|
|
|
|
|
if (compilation.moduleGraph) {
|
|
var _require = require('webpack/lib/util/runtime'),
|
|
getEntryRuntime = _require.getEntryRuntime;
|
|
|
|
var _require2 = require('webpack'),
|
|
UsageState = _require2.UsageState;
|
|
|
|
var runtime = getEntryRuntime(compilation, bundleName);
|
|
|
|
for (var _i = 0, _Object$keys = Object.keys(exports); _i < _Object$keys.length; _i++) {
|
|
var exportName = _Object$keys[_i];
|
|
var exportInfo = compilation.moduleGraph.getExportInfo(entryModule, exportName);
|
|
exportInfo.setUsed(UsageState.Used, runtime);
|
|
exportInfo.canMangleUse = false;
|
|
exportInfo.canMangleProvide = false;
|
|
}
|
|
|
|
compilation.moduleGraph.addExtraReason(entryModule, 'used by workerize-loader');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
worker.compiler.runAsChild(function (err, entries, compilation) {
|
|
if (err) return cb(err);
|
|
|
|
if (entries[0]) {
|
|
worker.file = Array.from(entries[0].files)[0];
|
|
var entryModules = compilation.chunkGraph && compilation.chunkGraph.getChunkEntryModulesIterable ? Array.from(compilation.chunkGraph.getChunkEntryModulesIterable(entries[0])) : null;
|
|
var entryModule = entryModules && entryModules.length > 0 ? entryModules[0] : entries[0].entryModule;
|
|
var key = entryModule.nameForCondition();
|
|
var contents = compilation.assets[worker.file].source();
|
|
var exports = Object.keys(CACHE[key] || {}); // console.log('Workerized exports: ', exports.join(', '));
|
|
|
|
if (options.inline) {
|
|
worker.url = "URL.createObjectURL(new Blob([" + JSON.stringify(contents) + "]))";
|
|
} else if (options.publicPath) {
|
|
worker.url = "" + JSON.stringify(options.publicPath + worker.file);
|
|
} else {
|
|
worker.url = "__webpack_public_path__ + " + JSON.stringify(worker.file);
|
|
}
|
|
|
|
if (options.fallback === false) {
|
|
delete _this._compilation.assets[worker.file];
|
|
}
|
|
|
|
var workerUrl = worker.url;
|
|
|
|
if (options.import) {
|
|
workerUrl = "\"data:,importScripts('\"+new URL(" + workerUrl + ",location.origin)+\"')\"";
|
|
} // workerUrl will be URL.revokeObjectURL() to avoid memory leaks on browsers
|
|
// https://github.com/webpack-contrib/worker-loader/issues/208
|
|
|
|
|
|
return cb(null, "\n\t\t\t\tvar addMethods = require(" + loaderUtils.stringifyRequest(_this, path.resolve(__dirname, 'rpc-wrapper.js')) + ")\n\t\t\t\tvar methods = " + JSON.stringify(exports) + "\n\t\t\t\tmodule.exports = function() {\n\t\t\t\t\tvar w = new Worker(" + workerUrl + ", { name: " + JSON.stringify(filename) + " })\n\t\t\t\t\tURL.revokeObjectURL(" + workerUrl + ");\n\t\t\t\t\taddMethods(w, methods)\n\t\t\t\t\t" + (options.ready ? 'w.ready = new Promise(function(r) { w.addEventListener("ready", function(){ r(w) }) })' : '') + "\n\t\t\t\t\treturn w\n\t\t\t\t}\n\t\t\t");
|
|
}
|
|
|
|
return cb(null, null);
|
|
});
|
|
};
|
|
|
|
module.exports = loader;
|
|
//# sourceMappingURL=index.js.map
|
|
|