Comments (19)
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.
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.
@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.
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.
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.
... 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.
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.
No, Deno modules are imported remotely via a url, either from deno.land hosting service or a CDN.
from lightningcss.
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.
A @parcel/css-wasm
would probably be most ideal.
from lightningcss.
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.
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.
Awesome, thx!
A native Deno build would be great. However, a CLI would be even better for my use case
from lightningcss.
@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.
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.
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.
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.
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.
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)
- Alias another CSS module file to avoid repeating (long) filepaths HOT 2
- CLI error `This: command not found`
- How to implement the use of mixins in the Vite + Vanilla project?
- Don't split unsupported selectors
- Warning when `:is()` contains pseudo-elements
- Allow `composes` inside `@layer`?
- [Bug] grid-template identifiers do not get transformed (with CSS modules) when var() is used HOT 3
- Using `rgb(var(--foo from '...'))` gives unexpected results (in CSS modules with `dashedIdents`)
- Overriding a CSS variable with CSS modules and `dashedIdents`
- /* ERROR: Unexpected token Semicolon */ (IE hacks 5-7) HOT 2
- Can media queries use custom units? HOT 1
- Importing radix colors breaks build HOT 2
- 🤔disable property sorting HOT 1
- Invalid minify result of `background-position: center bottom 1px`
- light-dark() is always being replaced HOT 5
- Declaration blocks for unrecognized pseudo-elements are not merged HOT 2
- :is() with a [] selector causes removal of is:() HOT 1
- How to recover substituted variables? HOT 2
- Nesting selector always inserted
- Support for anchor positioning HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from lightningcss.