Open ins429 opened 6 years ago
@ins429 as of CRA 2.0 you can add a rule to module.rules which might achieve what you're talking about, I've been working on a simular project here
I don't think it was left out or removed intentionally. @Timer do you see any reason not to resolve .wasm
?
I dunno, are we supporting wasm yet? We need tests before we turn it on.
It seems work for me to simply add wasm
to resolve.extensions
in webpack config, and exclude it from fallback.
PR here: https://github.com/facebook/create-react-app/pull/5924
CI tests fail at fixtures/typescript-advanced/index.test.js
(link). Not quite sure where the problem is. Try to fix it later
Not finished. Please see discussions below
@pd4d10 It doesn't seem that just adding wasm
to resolve.extensions works.
I've been trying to implement this in #6049 but am having some issues.
It seems that wasm modules need to be imported asynchronously. This makes sense because the recommended way to load a WASM module is async (WebAssembly.instantiateStreaming).
I'm not sure how to make a jest transformer which requires being imported with an async import()
. Any ideas? Jest also doesn't seem to be using my transformer with an async import.
The second argument to WebAssembly.instantiateStreaming
is an imports object. Where should this come from? All examples I've seen of using WebAssembly and webpack either use it explicitly (handle loading in application) or don't use it at all.
I'm kinda confused about the interface which should be exposed. When you do
import * as wasm from './add.wasm';
What wasm
be? The exports from ./add.wasm
? A function which takes importObjects
and returns an instance like wasm-loader? Should this import
be an import()
?
Hmm, it seems WASM will have some kind of esmodules support in the future, but it doesn’t yet. https://github.com/WebAssembly/proposals/issues/12
For now we should probably just use wasm-loader. What do you think @iansu ? Should we wait for esmodules + wasm or use wasm loader now with some kind of experimental wasm extension (‘.wasm.expirmental’)?
Yeah, it's weird. I got wasm support working in dev and build though react-app-rewired with this change:
module.exports = function override(config, env) {
config.resolve.extensions.push(".wasm");
config.module.rules.forEach(rule => {
(rule.oneOf || []).forEach(oneOf => {
if (oneOf.loader && oneOf.loader.indexOf("file-loader") >= 0) {
// Make file-loader ignore WASM files
oneOf.exclude.push(/\.wasm$/);
}
});
});
return config;
};
But then importing is really strange. You need to use the async import syntax at some point, and it won't work if you don't. But where you import is kind of up to you, as long as the wasm file is a transitive dependency of your async imported code. At that point, the imported wasm file acts as a WebAssembly.Instance that's been instantiated with the exports of the module it was imported in.
This was all pretty unintuitive to me, but maybe I just expected less magic?
The code I was trying to run was rust built with wasm-pack, so even though I don't understand why it works it seems like webpack and wasm-pack both agree on the es modules format at least. The trouble with using wasm-loader is that it would break code that expects it to work this way. There aren't a lot of wasm packages on npm, but they've got to standardize on an expected loader at some point.
I honestly am not an expert here, but it seems like the ecosystem is moving quick, so committing to a specific wasm loader now might be premature? Even though I really want this!
It's tricky using Wasm in Webpack, @surma from Google created an interesting example: https://gist.github.com/surma/b2705b6cca29357ebea1c9e6e15684cc
I managed to get it working, but I ejected
CRA
I'm going to fork react-scripts
and add support to my own project as well.
Is it interesting for Create React App project? I can make a Pull Request.
@shayc You can hold off on making a PR; I really think we should wait for some stabilization in the library ecosystem since by and large people won't be writing their own wasm, they'll be importing it from npm. Today the rust toolchain makes code that's pretty webpack friendly, but I think that go and llvm emit wasm directly and expect you to call WebAssembly.instantiateStreaming
. You can handle that today in CRA by putting your wasm in public
and fetching it, which is why I care more about importing from external packages.
I might be wrong though! I'm going to take some time this weekend to do a survey of the current state of things.
Ok, I did some reading and my opinion is pretty much the same; hold off for a while until this stabilizes more. The most relevant info I could find is the WASM ES module proposal and it's only stage 2. Until then, users can use the imperative js apis with their wasm files saved in public
.
Any updates on this?
See #7911.
Looks like ejecting is the only way to use wasm with cra. Thanks.
Is there no way of making it work by overriding config in config-overrides?
From what I have seen in other discussions, it seems like the create-react-app philosophy is to ignore the fact that it uses webpack internally - in other words, webpack features should not be relied upon. However, webpack includes a match for .wasm
in defaultRules
which does not magically work for all .wasm
files.
For example, when using a .wasm
file created with Emscripten (https://github.com/webpack/webpack/issues/7352) in a create-react-app project, we get the error:
Failed to compile.
./src/sagas/mpy-cross.wasm
Module parse failed: magic header not detected
File was processed with these loaders:
* ./node_modules/file-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
Error: magic header not detected
So it would be nice if create-create-react app could disable this default rule in webpack so users can handle .wasm
files however they like without webpack interfering.
As a workaround, I changed the file extension of the .wasm
file to .emcwasm
so that webpack just treated it like a normal binary file instead of trying to load it as a JavaScript module. (And had to configure the web server to serve .emcwasm
files with the application/wasm
MIME type.)
As a workaround, I changed the file extension of the
.wasm
file to.emcwasm
so that webpack just treated it like a normal binary file instead of trying to load it as a JavaScript module.
@dlech what would people do without people like you ;) thank you!
Regarding the application for react-app-rewired, since the oneOf rules now have multiple loaders, this seems to work better to exclude wasm from the file loader.
config.module.rules.forEach(rule => {
(rule.oneOf || []).forEach(oneOf => {
(oneOf.use || []).forEach(use => {
if (use.loader && use.loader.indexOf("file-loader") >= 0) {
// Make file-loader ignore WASM files
if (oneOf.exclude)
oneOf.exclude.push(/\.wasm$/);
else
oneOf.exclude = [/\.wasm$/];
}
});
});
});
I was curious if there was any reason
.wasm
extension was left out fromresolve.extensions
list?Webpack also default to include
.wasm
.It'd be nice to start using/experimenting wasm from create-react-app!