Search code examples
javascriptamazon-web-servicesamazon-s3importwebassembly

AWS S3 is not letting my JS files import WebAssembly code


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?


Solution

  • 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.