0

I'm trying to host a static website using AWS S3. The website contains, among other things, some WebAssembly code for a simple client-side game.

But when I try to import my WebAssembly from a JavaScript file, I get the following error:

Loading module from “http:/[REDACTED].s3-website-us-east-1.amazonaws.com/pkg/my_wasm_bg.wasm” was blocked because of a disallowed MIME type (“binary/octet-stream”).

I Googled this, and my understanding of the problem is that S3 sets the X-Content-Type-Options: nosniff header on its internal HTTP requests, so that my JS can't import any files whose type is not a JavaScript MIME type. Since binary/octet-stream is not a JavaScript MIME type, the import request is blocked.

How can I overcome this problem, and get my JS file to successfully import my WebAssembly within AWS S3?

Asker
  • 1,299
  • 2
  • 14
  • 31
  • How are you importing your wasm file. Please post the code. – Alan Dec 16 '22 at 07:34
  • @Alan Here is the exact line that raises the error: `import * as wasm from './my_experimental_website_bg.wasm';`. – Asker Dec 16 '22 at 07:39
  • Have you tried setting the mime type to `application/wasm`? – sytech Dec 16 '22 at 07:40
  • @sytech How would I do that? – Asker Dec 16 '22 at 07:41
  • @sytech Okay, I learned that the way to do this is to view the object in the AWS Console and, under Properties -> Metadata, you can set the object's Content-Type to `application/wasm`. But doing this still didn't solve my problem. – Asker Dec 16 '22 at 08:59
  • Namely, the error is the same as before, only now the disallowed MIME type is "`application/wasm`" instead of "`binary/octet-stream`". – Asker Dec 16 '22 at 09:03
  • That is not one of the Javascript MIME types, have you tried `application/javascript` ? – Anon Coward Dec 16 '22 at 16:09
  • @AnonCoward I did, but got an error starting with `Illegal character: U[...]`. After reading [this answer](https://stackoverflow.com/questions/58364162/loading-module-was-blocked-because-of-a-disallowed-mime-type-application-wasm) I think the problem may be that WASM is not fully supported by AWS and must be imported through circuitous means. Will keep trying! – Asker Dec 16 '22 at 20:33
  • (BTW, the same code compiles just fine on my local computer, so I know it must be something about the interaction between the environment and the code, rather than just a bug in the code per se.) – Asker Dec 16 '22 at 20:35
  • Javascript doesn't compile. – Alan Dec 24 '22 at 06:22
  • @Alan No, Alan, but wasm does. You see, I'm using `webpack-dev-server` to bundle my wasm with Javascript, and the bundling process is a form of compilation, which is why the command line output I get when I *compile* my project using `webpack-dev-server` is `Compiling [x]...` and `Compiling [y]...` I thank you for your helpful input so far in this thread. – Asker Dec 24 '22 at 06:55
  • 1
    Right. So you are running a dev server that is using webpack, which is a bundler and bundles your assets together, and serves them including your wasm files. That bundler is handling the import statement dynamic binding on your behalf. So the difference isn't due to mimetypes or mime sniffing. It's that you are using a webserver that handles bundling and serving all in one. You'd run into the same issue using NGINX etc. So, prior to putting your code on S3, you're missing the transpiling and bundling part. Typically it should create a `dist` directory, which you then copy to S3. – Alan Dec 26 '22 at 05:14
  • 1
    Your webpack.config.js should output to a dist directory, and the resultant JS file should not have any import statements. – Alan Dec 26 '22 at 05:21
  • @Alan Thanks, this solved the problem. Turns out I was omitting the actual bundling step of `webpack`, and instead trying to serve my files as-is, which led to the import problems. If you post this as an answer I'd be glad to accept it. – Asker Dec 26 '22 at 07:20

1 Answers1

0

Configure your webpack.config.js to output javascript that targets your environment. The config file should be set to output to a dist directory, which you then copy to S3 as part of your deploy.

It's likely you just need to run a discrete build step, as that step is often preconfigured as part of boilerplate such as create-react-application.

In more detail:

ES6 import statements inside the browser (at time of writing) can only natively support importing other module files (e.g. javascript files that export files) at runtime, and can only be called from other modules.

For ease of development, tools such as Babel (transpiler) and Webpack (bundler) support using ES6 style imports for other files such as images, css, and in your case wasm.

In your specific dev environment under the hood of your webserver those tools are running and creating valid javascript for your desired supported web browsers.

That step is being done typically after you make a change to one of your source files. To server your application outside your current dev environment via S3, you need to add a build step that transpiles and bundles your source into a set of static files, which will then can be served from S3.

As an aside, the X-Content-Type-Options: nosniff instructs the browser to accept the supplied content-type value, rather than trying to determine it based on file headers.

Alan
  • 45,915
  • 17
  • 113
  • 134