Farm: Fast vite compatible build tool written in Rust
farmfe.org
farmfe.org
Vite:
2166 modules transformed.
built in 28.21s
Farm: [ Farm ] Build completed in 13350ms FULL EXTREME! Resources emitted to ./dist.
[ Farm ] Public directory resources copied successfully.
So that is 28.21s vs. 13.35s, or a 53% decrease in build times. This is certainly neat, but I'm not sure whether it is worth the dependency on a new player.Another important callout is how in Vite, native ESM modules are used in dev which makes it very slow for large apps with thousands of modules. So cold start of dev can be important too.
In practice HMR is mostly what you need and Vite has it covered. But slow tends to accumulate slow.
I wouldn’t say it’s too many modules. We heavily use code splitting, so most of the time, users will fetch only a few of these, and pages load quickly. Plus, there’s some dependencies we cannot get rid of that are quite heavy.
From my personal experience though, it’s nothing unusual really.
The only way out for us will be to get rid of vuetify components, one at a time, and introduce Tailwind with a prefix, until we can finally remove that mess.
The biggest recommendation I have is to stay away as far as you can from that library. I think that has been the worst technical decision I ever made at my job.
This is my experience with Vue overall, not just it's shitty ecosystem and libraries.
The JS ecosystem (speaking as an omnivore using many languages) suffers two big problems:
1. Tooling is too fragmented and complex and poorly designed. This includes even the standard tools and formats like npm and package.json.
2. There’s a weak culture of API stability. Leave a project for 3 months and there are new config files, plugin formats, etc.
It’s improving slowly through standardization with things like ES modules. But it’s still a Wild West.
but that's all that younger devs know. specially people from boot camps or the CS to startup pipeline.
I tried running a Python project and the necessary apt-get pulled 2 GB of dependencies and conflicted with some of software I use, that's before running the pip install... Good old NPM.
Go stands out as being fast, small and very limited dep bloat, thanks to a comprehensive standard library. And very minimal config files. By that standard npm is a shit show.
:p
But really, you can just use skip it all and write your own code. People would scoff now, but that’s what we did. Well, maybe with prototype and/or jQuery.
I’d like to switch to something like esbuild but it uses a lot of features like aliases so would take some work to translate and the lib is being moved away from anyway. If I can drop something in that speeds it up I’m all for it
JS is interpreted and JITed. The whole point of using it is having a very fast feedback loop.
The tradeoff should be: faster at dev, slower at runtime. There’s something fundamentally wrong if that premise is broken.
Actually it’s insane that we need build steps with any noticeable delay during dev time at all.
After that we can start laying off the devs and firing our biggest customers. The features they use are taking up too much code!
What's the risk of downloading what's supposed to be a release binary of this off GitHub, where the release binary includes something nefarious not found in the open codebase, that steals your company's source code when you use it to compile?
In today's geopolitical climate, how does anyone trust non-Western projects?
There is also Vite, of course , which is already quite fast and very popular.
What's the differentiator between those?
Bun + Biome covers everything you need for a TS project (Biome lints and formats).
--
* : I guess it is not written in Rust but still in the same category of tools.
--
If there was a bundler written in Rust I might have chosen that, as despite not having anything against Go, the momentum seems to be strongly shifting to Rust (and even in the little Go I did, I already feel the pain of its error handling), and Rust definitely gives you better tools to write reliably applications.
If you need an hmr script you can use the one I wrote for my webframework: https://github.com/spirobel/mininext
(my goal with mininext is to provide index.php like productivity but with all of npm and typescript at your fingertips)
mininext has a clean package.json
It is just 3 files of modest size that are understandable in an afternoon.
You can also copy and paste and vendor the hmr part.
Someone even forked mininext to create micronext.
My goal is to compete with php. So I added some quality of life features. But if people want to go turbo minimalistic I can respect that.
I just wouldn't add a dependency for hmr when it is so easy to do with a small snippet.
mininext is a neat idea and I plan to read through the code (do you have a preferred 'small snippet' for hrm? I'd be interested to read that too) but I was talking more generally in my last comment.
I like to keep it simple. Right now bun just rebuilds everything and it is so fast that I don't recognize it.
If it ever becomes a problem I will optimize it.
The standardDevReloader is a snippet to tell the browser to refresh the page after a rebuild happened.
If you setup a fresh project with the barebones quickstart template with: bun create spirobel/aldi yournewproject
you will see a dev.ts in the project folder. compared to the start.ts (which is used to run the prod version) it will setup this snippet, so it is included in every html page that is served.
There are still issues (like aborting a fetch, and TS5 style decorators).
But it’s fast and I have all tests run on every save, which are near instant.
It's probably more holistic/batteries included than Farm, from a cursory glance. Rsbuild also aims to be a Vite alternative, but leans more into the webpack philosophy (and ecosystem) than Rollup's
https://github.com/farm-fe/performance-compare?tab=readme-ov...
The production build metric here would be ESBuild + a small amount of overhead from vite. (The HMR/dev build side of things is handled by Rollup instead with Vite)
IMO, Vite (ESBuild/Rollup) are fast enough. Farm will need to get some time being used + abused by OTHER people's real projects before I'll be considering it in order to save what seems like maybe 2 minutes a day.
That’s completely backwards. Vite only uses rollup for production, which is why production build is slower. https://vitejs.dev/guide/why.html#why-not-bundle-with-esbuil... The plan is to replace both esbuild and rollup with Rust-based rolldown (fast, and supports rollup’s plugin architecture) eventually. See https://www.youtube.com/watch?v=hrdwQHoAp0M.
Back in the day is was cute that you could import GLSL fragments directly into your JS code. Now, not so much.
I guess it doesn't support HMR? I guess I just persist the frontend state of my app so I only need livereload...
Just seems like so much wasted time and effort on marginal things. Just use ESBuild and start building something!
[1]: https://rolldown.rs/
They probably took the idea from https://esbuild.github.io
I made the exact same point two years ago when Turbopack came up with a similar benchmark: https://github.com/yyx990803/vite-vs-next-turbo-hmr/discussi...
The point is if we want to compare bundler performance, we should keep all the non-architectural variables consistent across all implementations. Otherwise we are not comparing apples to apples.
PR submitted to update the benchmark: https://github.com/farm-fe/performance-compare/pull/11
Without wanting to make this specifically anti-chinese, I really wonder whether that makes it better or worse than only having the Discord link.
I find Discord as a community platform already quite questionable. Now add to that the simple fact of fragmenting your community into two... I'm not convinced.
Are any large projects using it? Corporation sponsors?
I stopped at "create" - I rather "install and convert" in a branch to try stuff out.
I'm sorry, but WebGL probably shouldnt be a requirement for your front page to display any content at all. I disable it for privacy hardening and switch browsers to opt-in. Additionally, low-power clients may struggle with rendering and sink battery in mobile devices.
The docs work fine, if anyone else runs into this and wants to read about the project.
On the contrary, it's on the Farm team to fix. It seems their front page has only one error boundary, which is why the chart component crashing takes the whole page down. This is fixed by simply wrapping the chart component in its own error boundary. That way React doesn't unmount practically the whole page when that component throws an error.
But anyway, the chart looks like regular DOM to me. The canvas is actually in the top navbar, but I don't see anything drawn on it.
I've never used Vue so I have no idea how error handling works there, but React also offers programmatic ways to recover from errors (e.g. error boundaries can retry rendering the failed component with different state or props). Doesn't sound strange to me.
What specific optimizations do these tools offer that others can't, and why can't the slower tools simply adopt these optimizations in future updates?
Is this a result of a lack of consensus within the community, leading to the creation of new forked tools, or is there a larger strategic context that I'm missing?
The performance gains in the recent past have mostly been due to moving away from single-threaded JavaScript to multi-threaded compiled languages. This requires a complete rewrite, so existing tools rarely take this step. We see this optimization in Farm alongside "partial bundling," which strikes a performance-optimal balance between full bundling (Webpack) and no bundling (Vite) in development.
Vite abstracts over a preconfigured set of "lower-level" frontend build tools consisting of a mixture of older single-threaded JavaScript tools and newer multi-threaded compiled language tools. Vite can adopt the partial bundling of Farm, but dispensing with its remaining JavaScript tools is a major breaking update.
I struggled with the ordering since each section is somewhat mutually dependent; this is arranged more like a thematic history than a chronological one.
Tree-shaking naturally fits under bundling, and I'm afraid that explaining it earlier will make tree-shaking's explanation itself contextless since without bundling there is nothing to tree shake.
I can hyperlink those references to the tree-shaking section tomorrow so that there is an action for the confused.
Not to take away from the excellent writing in your original essay!
Thanks for the response and more importantly the article! It covered exactly all the points that were opaque to me about frontend build processes. I've also forwarded it to a couple of other backend devs that I know.
Dead code elimination in its traditional form also runs during code minification, which is a separate build step from bundler tree shaking. Having separate terms avoids ambiguity.
A practical example would be that tree-shaking wouldn't remove the variable b in "export function foo(x) { let b = 10; let a = 20; return x + a; }" but if this export isn't imported anywhere, then it would remove the whole function definition. Uglify.js, which does dead code elimination would remove the unused b variable.
This is overly simplistic. Parcel had far better performance than Webpack before they added native code or threading.
Webpack remained slow because it didn’t have a good public/private interface for its plugins, so the changes that could be made were limited.
> Vite can adopt the partial bundling of Farm, but dispensing with its remaining JavaScript tools is a major breaking update.
Turbopack and Parcel both have excellent performance without any compromises to their bundling strategy. Vite skipping this likely just simplifies it’s architecture. Bundling creates an opportunity to be slow, but it doesn’t necessitate it.
However, vite currently consists out of a different build tool for prod and dev (rollup and esbuild). And they're working on replacing both with the new rust based 'rolldown'
I've just watched some videos on this but it's still nebulous to me. It has something to do with hydration, and bundling only components used in the app, but making it compatible with ES modules while also allowing for hot reloading of your app during development, ... or something like that.
I'd like to do more web dev but I find it very difficult to get started in the space as someone with 20 years dev experience in backend and data.
I was looking at using Rust for some static analysis of JavaScript files recently. My impression is that despite there being multiple parsers written in Rust -- the ones in swc, rslint and maybe others -- they are not as production ready as something like acorn, in terms of passing test262, features, documentation, and simply the amount of example code out there. There are bugs like https://github.com/swc-project/swc/issues/2038 that haven't been fixed after a few years. (I am aware that swc is "production-ready" in the sense that it is already used by Next.js, but that's not a high bar if you look at all the fallbacks and limitations)
These projects also seem to be very broad but don't have enough developers to support them. They are aiming to provide an "all-in-one" solution with the parser, transpiler, bundler etc all in one place. Which means they have perhaps too much work to do. While in the current JavaScript ecosystem, there are many projects for each part of the toolchain, the unexpected upside is that there are many people working on one thing to make it really good. Just look at webpack. It's not the best thing out there, but the sheer amount of features and the support for almost every use case is amazing. For parsers, acorn is very good, because the author can focus on the parser instead of also working on the bundler.
As an end user, I would much rather see effort concentrated to make the toolchain really good to make it more production ready, rather than seeing another tool popping up.
I tried all those examples on the swc playground[0] and all of them pass, so the issue seems to be fixed, but maybe they forgot to close it. By the way, swc, oxc, and biome all pass test262.
[0]: https://swc.rs/playground (version 1.6.5)
Which could be outdated as well.
But if that's true, it's the problem isn't it? If some of the most important information about a critical part of the toolchain isn't up-to-date, how can I have confidence in this?
(Also for my specific use case, I need to set an ecmascript version, something that is common in JS based parsers, but it's not available in swc ecma parser. At least I didn't find it.)
For context, I contributed to acorn to fix an issue I found while using it in one of my projects. But that happened because I extensively used acorn in the first place. I don't quite have the confidence to adopt these Rust based tools yet.
They seem to re-use quite a lot. I don’t think any of them, besides ESBuild, roll their own transpiler. For example, Farm uses SWC:
https://github.com/farm-fe/farm/blob/main/crates/toolkit/Car...
There is also vite which doesn't bundle for dev environment, but serves individual modules separately and is fast.
Why webpack is bloated you ask? Well, because there isn't single javascript, but a mixed bag of esm, commonjs, vue, ts, css, scss and whatnot used in a combination with one another (you can have a vue file which contains ts script and scss styles and a vue file with javascript which imports ts file and css modules). Webpack tries to solve all that, plus caching and developer webserver, but relies on plugins to do a lot of stuff. So yeah, dutch tape, a lot of.
Then somebody decides it's enough and tries to rewrite the whole thing is rust because it's faster and implements 80% of their own needs on day 1, but gets burned by the long tail of annoying issues.
Since it's not a product in itself, somebody has to sponsor it or make in-house thing and opensource. In-house mainters could move to a next bigcorp and the new shiny thing will not go forward with original vision and same enthousiasm.
So yeah, welcome to frontend. It's like linked lists, buffers or unicode in C, but with a complexity or a distributed org and trying to be as cool as erlang at the same time.
Rust and Ruby too, to a lesser extent. But you don't see this nearly as much in Python or C++ or Go IMO. (I can name Guido van Rossum and Herb Sutter. But who wrote pytest for example? If it were Javascript and I used it I'm sure I'd know. And fwiw I've worked professionally with python for years and not really JS much at all, but I'd recognise more JS names and hear about people far more for JS than python.)
Similar to RSC rediscovering JSP, ASP.NET, PHP,...
They have a WeChat group, and a QQ address. So I’m going to assume they are based in China.
This Wikipedia article https://en.wikipedia.org/wiki/Incorporation_(business) has a list of abbreviations used for incorporated businesses.
For example in Norway we use “AS” (Aksjeselskap).
In Germany GmbH (“Gesellschaft mit beschränkter Haftung”, limited liability company), and AG ("Aktiengesellschaft", business association with shares), are the most similar to the corporations in the US.
In the UK they have a bunch of different ones.
China uses WFOE (or WOFE), to refer to a Wholly Foreign Owned Enterprise (WFOE). This is the most popular form of business entity for foreign investors wanting to set up a company in China; it is a limited liability company. The article doesn’t mention what Chinese owned companies in China use as abbreviation.
In fact, on the whole list as far as I can see it seems that only three countries use the abbreviation “Inc”: USA, Canada, and the Philippines.
The article as a whole only mentions a few countries though, so I had a look elsewhere as well.
Another website talks specifically about Chinese company structures. https://learn.sayari.com/understanding-chinese-corporate-str...
> In China, the limited liability company (LLC; in Chinese, 有限责任公司 or 有限公司) structure is generally for smaller and less restricted companies. Chinese LLCs may not have more than 50 shareholders
> company limited by shares (股份有限公司 or 股份公司) structure is generally used by larger companies, including publicly traded companies (which must be companies limited by shares)
> One-Person Limited Liability Company (一人有限责任公司) This type of corporation has similar rights and responsibilities to a standard LLC, but may only be established by a natural person.
And quite a few different ones in addition to those, but none using “Inc” as abbreviation.
Back to the topic of countries where Inc is used.
1. United States: The most prominent user of "Inc." for incorporated entities.
2. Canada: "Inc." is commonly used alongside "Ltd." (Limited).
3. Philippines: Companies frequently use "Inc." to indicate incorporation.
4. Australia: Although "Pty Ltd" (Proprietary Limited) is more common, "Inc." can also be used for non-profit organizations.
5. New Zealand: Similar to Australia, "Inc." is used for non-profit entities.
6. Japan: The term "Kabushiki Kaisha" (K.K.) is the standard, but "Inc." is sometimes seen in international contexts.
7. South Korea: The term "주식회사" (Jusikhoesa) is typical, but "Inc." is occasionally used for international recognition.
8. Taiwan: Companies might use "Inc." in English contexts, though the local term is "有限公司" (Youxian Gongsi).
These countries utilize "Inc." to denote an incorporated company, often within international business contexts.
Anyway. If they really are an incorporated company I think it would be helpful to mention what country they are incorporated in, and provide some kind of registration number that you can use for looking up details about the company. And conversely, if they are not an actual incorporated business then don’t pretend to be.
Using Safari on iOS.
Maybe instead of using nodejs, use Go, Spring, Quarkus, Micronaut, ASP.NET, Axiom...