Code Monkey home page Code Monkey logo

Comments (19)

mischnic avatar mischnic commented on May 17, 2024 7

Building the browser wasm build with yarn wasm-browser:build and then running this with deno run --allow-read ...

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.

from lightningcss.

mischnic avatar mischnic commented on May 17, 2024 1

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

from lightningcss.

lucacasonato avatar lucacasonato commented on May 17, 2024 1

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

from lightningcss.

devongovett avatar devongovett commented on May 17, 2024 1

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?

from lightningcss.

devongovett avatar devongovett commented on May 17, 2024

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.

from lightningcss.

joelmoss avatar joelmoss commented on May 17, 2024

... which is behind an environment variable, so that's weird.

Yeah I noticed that too 🤷‍♂️

See https://deno.land/[email protected]/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?

from lightningcss.

devongovett avatar devongovett commented on May 17, 2024

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?

from lightningcss.

joelmoss avatar joelmoss commented on May 17, 2024

No, Deno modules are imported remotely via a url, either from deno.land hosting service or a CDN.

from lightningcss.

lucacasonato avatar lucacasonato commented on May 17, 2024

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.

from lightningcss.

lucacasonato avatar lucacasonato commented on May 17, 2024

A @parcel/css-wasm would probably be most ideal.

from lightningcss.

devongovett avatar devongovett commented on May 17, 2024

Another possibility is to include wasm in the main package, and the "browser" field or package.json#exports. That way, it will just automatically use wasm in browsers. But not sure sure if that will work for deno.

from lightningcss.

devongovett avatar devongovett commented on May 17, 2024

Just published v1.0.2 which includes a build for wasm under the @parcel/css-wasm package. See the readme for details on how to use it.

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.

from lightningcss.

joelmoss avatar joelmoss commented on May 17, 2024

Awesome, thx!

A native Deno build would be great. However, a CLI would be even better for my use case

from lightningcss.

lucacasonato avatar lucacasonato commented on May 17, 2024

@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).

from lightningcss.

devongovett avatar devongovett commented on May 17, 2024

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 yarn wasm-browser:build-release in the repo, and run the below script, you can see for yourself. You'll need to copy bootstrap-4.css from somewhere (e.g. here).

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();

from lightningcss.

lucacasonato avatar lucacasonato commented on May 17, 2024

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();
}
default: 27ms
default: 24ms
default: 31ms
default: 35ms
default: 28ms
default: 33ms
default: 27ms
default: 21ms
default: 18ms
default: 9ms
default: 8ms
default: 8ms
default: 9ms
default: 8ms
default: 8ms
default: 9ms
default: 8ms
default: 8ms
default: 8ms
default: 9ms

PS: the async function run isn't necessary in Deno, we have top-level-await :-)

from lightningcss.

lucacasonato avatar lucacasonato commented on May 17, 2024

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`);

from lightningcss.

devongovett avatar devongovett commented on May 17, 2024

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.

PS: the async function run isn't necessary in Deno, we have top-level-await :-)

Yeah.. I got some warning from typescript.

from lightningcss.

lucacasonato avatar lucacasonato commented on May 17, 2024

So v8 cannot cache the compiled WASM somehow?

It can, but Deno does not currently support persisting that cache across runs. I don't think Chrome does either.

from lightningcss.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.