-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deno support? #32
Comments
I haven't used deno, so I'm not really sure how it works. But looks like it gets here: https://github.com/parcel-bundler/parcel-css/blob/master/native.js#L17, which is behind an environment variable, so that's weird. Anyway, I guess you'd need a WASM version to use in Deno, unless it has some way of building native modules. I don't think the WASM build is currently published to npm. |
Yeah I noticed that too 🤷♂️ See https://deno.land/manual@v1.17.2/webassembly/using_wasm for WASM, but I also noticed that Deno publishes a Rust crate. Not really familiar with Rust, but as both Deno and @parcel/css are written in rust, maybe there is some way for the two to work together? |
https://github.com/littledivy/deno_bindgen seems similar to wasm-bindgen which is already used for Wasm here: https://github.com/parcel-bundler/parcel-css/blob/cb2037ba1b054c0228e467360f2ffb41d0d4626d/node/src/lib.rs#L14-L37 |
Interesting. I wonder if we should split these into multiple packages though? If we had to compile the module for all architectures separately for both node and Deno the package size could get big. But I guess modules for Deno don't come from npm anyway? |
No, Deno modules are imported remotely via a url, either from deno.land hosting service or a CDN. |
Or just from raw.githubusercontent.com directly is also possible. @devongovett If you ship a WASM build meant for running in the browser, that would be the most ideal for Deno users. A browser WASM build using ESM will just work in Deno. WASM is a lot better for security compared to a dylib, as you don't need to open up the entire security sandbox to load a WASM file, unlike what you need to do with a dylib. |
A |
Another possibility is to include wasm in the main package, and the |
@devongovett That works too! If the code runs in a recent version of Chrome, and does not use the DOM, the chance it "just works" in Deno is very very high. |
Building the browser wasm build with import * as css from './node/pkg/parcel_css_node.js';
await css.default();
let {code, map} = css.transform({
filename: 'style.css',
code: new TextEncoder().encode('.foo { color: red }'),
minify: true,
});
console.log(new TextDecoder().decode(code)); works. |
I guess combined with #38 it should be a separate package so as not to make the package larger. I'd also be curious to know how much slower the WASM build in Deno is compared with native. Maybe we should have a Deno specific package as well? |
Just published v1.0.2 which includes a build for wasm under the Just for comparison, the WASM build minifies Bootstrap in ~24ms on my machine, vs ~4.6ms in Node with the native build. That's a pretty significant difference. We may still want to consider a native Deno FFI build in the future. |
Awesome, thx! A native Deno build would be great. However, a CLI would be even better for my use case |
@devongovett Awesome! How did you do the benchmarking? I'd like to try to give a shot at optimizing the WASM build. There are a few flags for rustc that can significantly speed up the resulting WASM (at the cost of some file size). |
Well I just realized one problem with the released version: I ran the dev build in CI rather than the release build. 🤦 Fixed that in 6587589. But when I did my testing locally, it was definitely on a release build so the number above is correct. But if you run import init, {transform} from './node/pkg/parcel_css_node.js';
async function run() {
await init();
let source = await Deno.readTextFile('./bootstrap-4.css');
let opts = {
filename: 'style.css',
code: new TextEncoder().encode(source),
minify: true,
};
console.time();
transform(opts);
console.timeEnd();
}
run(); |
V8 just needs a moment to optimize. After 10 runs I am down to 8ms - so in a long lived process like the watcher of a bundler, this should be just as fast as native: import init, { transform } from "./node/pkg/parcel_css_node.js";
await init();
let source = await Deno.readTextFile("./bootstrap-4.css");
let opts = {
filename: "style.css",
code: new TextEncoder().encode(source),
minify: true,
};
for (let i = 0; i < 20; i++) {
console.time();
transform(opts);
console.timeEnd();
}
PS: the |
If I just give V8 2 seconds idle time to optimize the WASM, the first run goes from 35ms on my machine to just 13ms. After running it a few more times it goes down to 7.9ms: import init, { transform } from "./node/pkg/parcel_css_node.js";
await init();
let source = await Deno.readTextFile("./bootstrap-4.css");
let opts = {
filename: "style.css",
code: new TextEncoder().encode(source),
minify: true,
};
// In this idle time, V8 will tier up the WASM using TurboFan.
await new Promise((resolve) => setTimeout(resolve, 2000));
const N = 10;
const start = performance.now();
for (let i = 0; i < N; i++) {
const start = performance.now();
transform(opts);
const end = performance.now();
console.log(`${i + 1}/${N} ${end - start}ms`);
}
const end = performance.now();
const duration = end - start;
console.log(`${duration}ms total`);
console.log(`avg ${duration / N}ms per transform`); |
Ah interesting. So v8 cannot cache the compiled WASM somehow? I did notice it got a little faster after more than one run of the command, but not that much.
Yeah.. I got some warning from typescript. |
It can, but Deno does not currently support persisting that cache across runs. I don't think Chrome does either. |
Are there any plans to support Deno? I've tried to import it, but get errors about missing ./pkg directory.
When importing from Skypack https://cdn.skypack.dev/@parcel/css...
The text was updated successfully, but these errors were encountered: