FetchCompileWasmPlugin.js 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { WEBASSEMBLY_MODULE_TYPE_SYNC } = require("../ModuleTypeConstants");
  7. const RuntimeGlobals = require("../RuntimeGlobals");
  8. const WasmChunkLoadingRuntimeModule = require("../wasm-sync/WasmChunkLoadingRuntimeModule");
  9. /** @typedef {import("../Chunk")} Chunk */
  10. /** @typedef {import("../Compiler")} Compiler */
  11. /**
  12. * Options that influence how synchronous WebAssembly modules are emitted for
  13. * the fetch-based wasm loading runtime.
  14. * @typedef {object} FetchCompileWasmPluginOptions
  15. * @property {boolean=} mangleImports mangle imports
  16. */
  17. const PLUGIN_NAME = "FetchCompileWasmPlugin";
  18. /**
  19. * Enables synchronous WebAssembly chunk loading that fetches `.wasm` files and
  20. * compiles them in browser-like environments.
  21. */
  22. class FetchCompileWasmPlugin {
  23. /**
  24. * Stores options that affect generated synchronous WebAssembly runtime code.
  25. * @param {FetchCompileWasmPluginOptions=} options options
  26. */
  27. constructor(options = {}) {
  28. /** @type {FetchCompileWasmPluginOptions} */
  29. this.options = options;
  30. }
  31. /**
  32. * Registers compilation hooks that attach the fetch-based synchronous wasm
  33. * runtime module to chunks containing sync WebAssembly modules.
  34. * @param {Compiler} compiler the compiler instance
  35. * @returns {void}
  36. */
  37. apply(compiler) {
  38. compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
  39. const globalWasmLoading = compilation.outputOptions.wasmLoading;
  40. /**
  41. * Determines whether the chunk should load synchronous WebAssembly
  42. * binaries through the `fetch` backend.
  43. * @param {Chunk} chunk chunk
  44. * @returns {boolean} true, if wasm loading is enabled for the chunk
  45. */
  46. const isEnabledForChunk = (chunk) => {
  47. const options = chunk.getEntryOptions();
  48. const wasmLoading =
  49. options && options.wasmLoading !== undefined
  50. ? options.wasmLoading
  51. : globalWasmLoading;
  52. return wasmLoading === "fetch";
  53. };
  54. /**
  55. * Generates the runtime expression that downloads the emitted wasm
  56. * binary for a module.
  57. * @param {string} path path to the wasm file
  58. * @returns {string} code to load the wasm file
  59. */
  60. const generateLoadBinaryCode = (path) =>
  61. `fetch(${RuntimeGlobals.publicPath} + ${path})`;
  62. compilation.hooks.runtimeRequirementInTree
  63. .for(RuntimeGlobals.ensureChunkHandlers)
  64. .tap(PLUGIN_NAME, (chunk, set, { chunkGraph }) => {
  65. if (!isEnabledForChunk(chunk)) return;
  66. if (
  67. !chunkGraph.hasModuleInGraph(
  68. chunk,
  69. (m) => m.type === WEBASSEMBLY_MODULE_TYPE_SYNC
  70. )
  71. ) {
  72. return;
  73. }
  74. set.add(RuntimeGlobals.moduleCache);
  75. set.add(RuntimeGlobals.publicPath);
  76. compilation.addRuntimeModule(
  77. chunk,
  78. new WasmChunkLoadingRuntimeModule({
  79. generateLoadBinaryCode,
  80. supportsStreaming: true,
  81. mangleImports: this.options.mangleImports,
  82. runtimeRequirements: set
  83. })
  84. );
  85. });
  86. });
  87. }
  88. }
  89. module.exports = FetchCompileWasmPlugin;