Closed daverickdunn closed 2 years ago
No idea I'm afraid, it sounds like this is an issue with either your deployment setup or your bundler configuration. Your bundler appears to be keeping the reference to the wasm file to load it at runtime (as it should) but if that error is appearing in the browser then it's preserving it with a file://
URL (which is very unusual) and either your browser or server configuration is refusing to allow the request to load this file.
For this to work in browsers, you need to:
brotli_wasm_bg.wasm
to find this)fetch()
the WASM in your browser to do this - it could be blocked by CSP, or CORS, or server configuration issues)It's hard to know every possible configuration I'm afraid! I suspect this isn't really an issue related to this project though - you'll have the same issue with any wasm-based library. If it helps, you can see the Webpack config (for Webpack v5) that this project uses during webpack browser testing here: https://github.com/httptoolkit/brotli-wasm/blob/2ecde28bc3d745b394b20308fe99bec6f9117b68/karma-webpack.conf.js#L26-L56
Hi, thanks for taking a look, that's understandable.
I tried a bunch of stuff to get it to bundle with my app but I couldn't figure out what was wrong. I don't really want to bloat with extra bundling config as I'd have to add extra packages etc. so I've switched to brotli-dec-wasm as that worked without any issues.
Thanks again.
brotli-dec-wasm
@daverickdunn , hi, does brotli-dec-wasm
work for you with angular? I tried and it shows the same error. Could you please share how you did that?
it shows the same error
As the error comes from the web variant (pkg.web
), it is because the code generated by wasm-pack uses new URL('index_bg.wasm', import.meta.url)
to determine to the URL to the WASM binary file so that in the browser it can fetch and load it.
The reason why it breaks in Angular may be that import.meta.url
is not an expected value.
I am not familiar with Angular so I am not so sure though.
If you are looking for a quick and easy solution, you can just serve the WASM file on your own (by making the bundler copy it to the output dir, or even manually) and pass the URL string to the init function (__wbg_init
in the generated code, pkg.web/brotli_wasm.js
).
In brotli-wasm
it only exports init().then(() => brotliWasm)
so it can be a little hard to figure out how.
In brotli-dec-wasm
I will soon release a new version so that you can do this:
import { init } from 'brotli-dec-wasm'
const wasmUrl = '...'
const brotli = await init(wasmUrl)
Or refer to the asset.md document.
PS: I am the author of brotli-dec-wasm
and also put effort into this package so that Brotli can be easier in JS.
And @pimterry , I are recently working on another kind of entry for the web environment of these packages with less "side-effects". It is in asset.js with another export in package.json, the document is at asset.md, and an example is available at example/webpack-asset. Do you think it is fine and can I open a PR for the new entry?
@rr923
Note that I'm encoding the brotli buffer as base64, you may have it encoded as something else.
import { Injectable } from '@angular/core';
import { catchError, map, ReplaySubject, throwError } from 'rxjs';
function Base64ToArrayBuffer(base64: string) {
const binary_string = atob(base64);
const len = binary_string.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes;
}
@Injectable({
providedIn: 'root'
})
export class BrotliService {
public brotli = new ReplaySubject<any>();
private decoder = new TextDecoder();
constructor() {
this.init();
}
private async init() {
const brotli = await import('brotli-dec-wasm');
this.brotli.next(brotli)
}
public decompress<T = any>(data: string) {
return this.brotli.pipe(
map(brotli => {
const buff_array = Base64ToArrayBuffer(data); // base64 string to buffer (compressed)
const decompressed = brotli.brotliDec(buff_array); // compressed buffer to uncompressed buffer
const decoded = this.decoder.decode(decompressed); // uncompressed buffer to utf-8 string
return JSON.parse(decoded) as T;
}),
catchError(error => {
console.error(error)
return throwError(() => new Error(error))
})
)
}
}
I'm trying to load this with an Angular app. TS is happy and the app compiles fine, but at runtime I'm getting an error:
zone.js:1518 Not allowed to load local resource: file:///C:/**/**/node_modules/brotli-wasm/pkg.web/brotli_wasm_bg.wasm
Importing as:
import brotliPromise from 'brotli-wasm';
Angular 13 Chrome 107