From c2b768c453f281a988c71a829e7a71bb106302fa Mon Sep 17 00:00:00 2001 From: Mike Welsh Date: Fri, 15 Jan 2021 14:25:47 -0800 Subject: [PATCH] web: Fallback to instantiate with improper MIME type Use --target web in wasm-bindgen and file-loader for WASM files, allowing wasm-bindgen's built-in fallback from WebAssembly.instantiateStreaming to instantiate. file-loader spits out the WASM file directly in the output folder, and imports will resolve to the URL, so that we can load the file directly, avoiding webpack's built-in wasm loaders. This allows Ruffle to function on web servers even if they serve WASM files with the incorrect MIME type, fixing one of our biggest support requests (#400, #1458). There is some performance impact on loading with the fallback, but this is preferable to not working at all. --- web/packages/core/package.json | 2 +- web/packages/core/src/load-ruffle.ts | 14 ++++++++++---- web/packages/demo/package.json | 1 + web/packages/demo/webpack.config.js | 7 ++++--- web/packages/extension/package.json | 1 + web/packages/extension/webpack.config.js | 11 ++++++++--- web/packages/selfhosted/package.json | 7 ++++--- web/packages/selfhosted/webpack.config.js | 11 ++++++++--- 8 files changed, 37 insertions(+), 17 deletions(-) diff --git a/web/packages/core/package.json b/web/packages/core/package.json index 026195efcaf6..a066e9713723 100644 --- a/web/packages/core/package.json +++ b/web/packages/core/package.json @@ -11,7 +11,7 @@ "scripts": { "build": "npm run build:cargo && npm run build:wasm-bindgen && npm run build:wasm-opt && npm run build:ts", "build:cargo": "cargo build --release --target wasm32-unknown-unknown", - "build:wasm-bindgen": "wasm-bindgen ../../../target/wasm32-unknown-unknown/release/ruffle_web.wasm --out-dir ./pkg --out-name ruffle_web", + "build:wasm-bindgen": "wasm-bindgen ../../../target/wasm32-unknown-unknown/release/ruffle_web.wasm --target web --out-dir ./pkg --out-name ruffle_web", "build:wasm-opt": "wasm-opt ./pkg/ruffle_web_bg.wasm -O -g --output ./pkg/ruffle_web_bg.opt.wasm && move-file ./pkg/ruffle_web_bg.opt.wasm ./pkg/ruffle_web_bg.wasm || npm run build:wasm-opt-note", "build:wasm-opt-note": "echo 'NOTE: Since wasm-opt could not be found (or it failed), the resulting module might not perform that well, but it should still work.'", "build:ts": "tsc -d && node tools/set_version.js", diff --git a/web/packages/core/src/load-ruffle.ts b/web/packages/core/src/load-ruffle.ts index 0ff4eccb87a2..ceb5bf31342e 100644 --- a/web/packages/core/src/load-ruffle.ts +++ b/web/packages/core/src/load-ruffle.ts @@ -4,8 +4,7 @@ * Conditional ruffle loader */ -import { Ruffle } from "../pkg/ruffle_web"; - +import init, { Ruffle } from "../pkg/ruffle_web"; import { setPolyfillsOnLoad } from "./js-polyfills"; /** @@ -37,8 +36,15 @@ async function fetchRuffle(): Promise<{ new (...args: any[]): Ruffle }> { // We currently assume that if we are not executing inside the extension, // then we can use webpack to get Ruffle. - const module = await import("../pkg/ruffle_web"); - return module.Ruffle; + + // wasm files are set to use file-loader, + // so this package will resolve to the URL of the wasm file. + const ruffleWasm = await import( + /* webpackMode: "eager" */ + "../pkg/ruffle_web_bg.wasm" + ); + await init(ruffleWasm.default); + return Ruffle; } let lastLoaded: Promise<{ new (...args: any[]): Ruffle }> | null = null; diff --git a/web/packages/demo/package.json b/web/packages/demo/package.json index d85380445ae0..c83e69ecac17 100644 --- a/web/packages/demo/package.json +++ b/web/packages/demo/package.json @@ -13,6 +13,7 @@ }, "devDependencies": { "css-loader": "^5.0.1", + "file-loader": "^6.2.0", "style-loader": "^2.0.0", "webpack-cli": "^4.0.0" } diff --git a/web/packages/demo/webpack.config.js b/web/packages/demo/webpack.config.js index 138883976157..732cdc06d985 100644 --- a/web/packages/demo/webpack.config.js +++ b/web/packages/demo/webpack.config.js @@ -20,9 +20,6 @@ module.exports = (env, argv) => { filename: "index.js", }, mode: mode, - experiments: { - syncWebAssembly: true, - }, devtool: "source-map", plugins: [ new CleanWebpackPlugin(), @@ -47,6 +44,10 @@ module.exports = (env, argv) => { test: /\.css$/i, use: ["style-loader", "css-loader"], }, + { + test: /\.wasm$/i, + use: ["file-loader"], + }, ], }, }; diff --git a/web/packages/extension/package.json b/web/packages/extension/package.json index 9bf236565a1f..8047303d6dbd 100644 --- a/web/packages/extension/package.json +++ b/web/packages/extension/package.json @@ -11,6 +11,7 @@ "ruffle-core": "^0.1.0" }, "devDependencies": { + "file-loader": "^6.2.0", "webpack": "^5.1.3" } } diff --git a/web/packages/extension/webpack.config.js b/web/packages/extension/webpack.config.js index e788aa8e9c14..05632f3707ff 100644 --- a/web/packages/extension/webpack.config.js +++ b/web/packages/extension/webpack.config.js @@ -13,6 +13,14 @@ module.exports = (env, argv) => { console.log(`Building ${mode}...`); return { + module: { + rules: [ + { + test: /\.wasm$/i, + use: ["file-loader"], + }, + ], + }, entry: { ruffle: path.resolve(__dirname, "js/index.js"), main: path.resolve(__dirname, "js/main.js"), @@ -26,9 +34,6 @@ module.exports = (env, argv) => { chunkFilename: "core.ruffle.js", }, mode: mode, - experiments: { - syncWebAssembly: true, - }, plugins: [ new CleanWebpackPlugin(), new CopyPlugin({ diff --git a/web/packages/selfhosted/package.json b/web/packages/selfhosted/package.json index 390718d3d9ef..b15558607b18 100644 --- a/web/packages/selfhosted/package.json +++ b/web/packages/selfhosted/package.json @@ -19,9 +19,10 @@ "ruffle-core": "^0.1.0" }, "devDependencies": { - "webpack-cli": "^4.0.0", - "webpack-dev-server": "^3.11.0", "@wdio/cli": "^6.1.12", - "webpack": "^5.1.3" + "file-loader": "^6.2.0", + "webpack": "^5.1.3", + "webpack-cli": "^4.0.0", + "webpack-dev-server": "^3.11.0" } } diff --git a/web/packages/selfhosted/webpack.config.js b/web/packages/selfhosted/webpack.config.js index c687f4425615..c8c7db6b6ad8 100644 --- a/web/packages/selfhosted/webpack.config.js +++ b/web/packages/selfhosted/webpack.config.js @@ -21,9 +21,6 @@ module.exports = (env, argv) => { chunkFilename: "core.ruffle.[contenthash].js", }, mode: mode, - experiments: { - syncWebAssembly: true, - }, devtool: "source-map", plugins: [ new CleanWebpackPlugin(), @@ -31,5 +28,13 @@ module.exports = (env, argv) => { patterns: [{ from: "LICENSE*" }, { from: "README.md" }], }), ], + module: { + rules: [ + { + test: /\.wasm$/i, + use: ["file-loader"], + }, + ], + }, }; };