I hope you’re all recovering from your Halloween hangover the same way I am — by eating 14 fun size Butterfingers a day and crying to the “from the vault” tracks from Taylor’s version of 1989. Baby, was it over then, and is it over now?
Today’s issue: Celebrating almost 10 years of the JavaScript decorators proposal, seamlessly switching build systems, and fighting for my rights to join the local Rotary Club.
Welcome to #236.
Remix getting baptized into the church of Vite
On Halloween, Remix announced spooky experimental support for Vite as a potential alternative to their current esbuild-based compiler.
This got the #ViteHive hyped af, and it got us thinking about two questions: 1) Why would Remix do this? and 2) Why now? Let’s dig in.
Why do this?
Vite is fast and awesome (obviously). Early tests show it producing 10x faster HMR and 5x faster HDR for Remix projects, plus lots of other DX upgrades.
Vite plugins give Remix a ton of functionality for free. This allows Remix to focus solely on improving its core, without worrying about being a compiler or offering its own plugin system. In fact, Remix itself is now just a Vite plugin.
Vite should help facilitate Remix adoption. This move makes it easier for developers already using Vite to try out Remix. The Remix team has already successfully convinced many React Router users to adopt Remix, and this will help make that specific transition smoother than ever.
Why now? The Remix team couldn’t adopt Vite earlier because it didn’t initially come with stable SSR support, server-aware HMR, or support for non-Node runtimes like Deno and Cloudflare. So they built their own compiler on top of Rollup, which they later switched to esbuild in 2021.
Fast forward to early 2023, and the Remix team was working on compiler improvements to solve some bottlenecks. At this point, Vite now had support for almost all the functionality Remix needed, and Remix realized that improving their own compiler would require building a lot more functionality on top of esbuild — just to create what they called, “a worse version of Vite.”
So they did the smart thing and started working on a Vite plugin for Remix instead. The final piece will be adding Cloudflare support to Vite, and the Remix team is currently working with the Cloudflare core team to make that happen.
Bottom Line: For Remix, this seems like a no-brainer that offers a ton of benefit with very little, if any, downside. For Vite, this is another positive step towards its goal of becoming “the shared foundation for higher-level innovations in the web ecosystem.” Never bet against the #ViteHive.
Web scraping doesn't have to feel like manual labor anymore
Tired of getting blocked and rate limited when trying to scrape web data for a new project?
Time to try out Bright Data. Their headfull scraping browser gives you powerful unlocking tools like proxy rotation and cooling, CAPTCHA solving, browser fingerprinting, automatic retries, and more — so you can easily get the data you need.
This Fireship video demos how to use it in a Playwright project with ChatGPT to do some pretty advanced data gathering from Amazon. And it shows how you could easily apply this process to a wide variety of projects.
Try the scraping browser API for free — and see why companies like Microsoft and McDonald’s use Bright Data to get the data they care about.
Their guide on Detecting transitive access to sensitive Google Cloud resources shows how to detect users that can authenticate as the service account and gain access to all IAM permissions for that account.
class Person {
#name;
constructor(name) {
this.#name = name;
}
introduce() {
console.log(`Hello, my name is ${this.#name}.`);
}
}
class Student extends Person {
#grade;
constructor(name, grade) {
super(name);
this.#grade = grade;
}
introduce() {
console.log(
`Hello, my name is ${this.#name} and I am in grade ${this.#grade}.`
);
}
}
const student = new Student("John", 5);
student.introduce();
In other Shopify framework news, a new Hydrogen release just came out with Remix v2 support, better default caching, and codegen for TS and JS.
QA Wolf can get your web app to 80% test coverage in 4 months, without you ever needing to do e2e testing yourself 🤯. They build and maintain your test suite in Playwright, provide unlimited parallel test runs on their infra, and send human-verified bug reports directly to you. [sponsored]
Patrick Balestra, a staff engineer at the other “ify” (Spotify) wrote an article on the company’s engineering blog called Switching Build Systems, Seamlessly. “What, like it’s hard?”
Vladyslav Zubko wrote about the almost 10-year history of the JavaScript Decorators propsal and what the future looks like for finally getting them into the spec. Hey, it took me almost 10 years to get accepted into my local Rotary Club, but those old bastards finally caved.
Deno v1.38 features rustdoc-inspired updates to deno doc
, hot module replacement, and better Node compatibility.
Sébastien Noël created this visual guide to the most popular CSS selectors.
Jeff Sandberg wrote an article called CSS is fun again. You might not agree, but I’m not going to yuck Jeff’s yum.
Are you making the most of LLMs in your applications? Stay ahead of security risks with Snyk’s comprehensive guide covering the Top 10 threats associated with LLMs identified by OWASP. Gain actionable insights to protect your code and apps now. [sponsored]
Docusaurus 3.0 upgrades MDX from v1 to v3, adds support for ES Modules and TypeScript config files, and now enables you to build your static site in dev mode.
Marvin Hagemeister is back with part 8 of his series on Speeding up the JS Ecosystem, and this time he’s taking a look at what can be done to improve the Tailwind CSS architecture. It’s probably more applicable to your job than part 8 of The Land Before Time series, but it doesn’t feature Petrie’s wisdom about the negative effects of climate change. So keep that in mind.
Private fields are not inherited by subclasses. The #name
field is not accessible in the Student
class, so the introduce
method will throw an error. To fix this, you can add a getter method to the Person
class that returns the value of the #name
field.
class Person {
#name;
constructor(name) {
this.#name = name;
}
introduce() {
console.log(`Hello, my name is ${this.#name}.`);
}
_getName() {
return this.#name;
}
}
class Student extends Person {
#grade;
constructor(name, grade) {
super(name);
this.#grade = grade;
}
introduce() {
console.log(
`Hello, my name is ${this._getName()} and I am in grade ${this.#grade}.`
);
}
}
const student = new Student("John", 5);
student.introduce();