This article was first published on wechat public account “dependency injection”, please indicate the source of reprint.

In any case, now is the perfect time for front-end developers to learn Rust.

What is Rust?

Originally a private project of Mozilla employee Graydon Hoare, Rust was sponsored by Mozilla in 2009, first officially revealed in 2010 and released in version 1.0 in 2015. Over the past decade, the programming language Rust has been a breakthrough technology, and Rust has always stood in the challenging perspective of a unique combination of academic research and industry practicality. But to say that Rust’s impact is merely technical is to miss the point, as the community discussed in a series of blogs in 2016: “Rust is more than just a programming language or compiler “and “Rust makes everything accessible.” That same year Rust announced its official slogan: “A language that enables everyone to build reliable and efficient software”.

On February 8, 2021, the Rust Foundation was announced. Its board members are AWS, Google, Huawei, Microsoft and Mozilla. The birth of the Rust Foundation from the core Rust team and the financial commitment of five leading global industry companies marks a solid step towards the maturity of Rust.

Why Rust?

performance

Memory management varies among programming languages, but there are usually two ways to manage memory:

  1. Allocation and destruction by the developer: C, C++, etc. This approach is equivalent to leaving all the power to the developer, mismanagement is prone to memory leaks.
  2. Programming languages provide automatic garbage collection mechanisms: JavaScript, Java, Python, etc., which have run-time overhead that can have an impact on performance (note the “may”; there is no way to prove that performance is worse than the developer’s own management).

Rust takes a different approach to memory management by using ownership, borrowing, and life cycle mechanisms to automatically insert memory release logic at compile time. Without the runtime overhead of garbage collection, Rust is extremely fast and memory efficient overall.

fn main() {
   let a = String::from("hello rust");
   let b = a;           // Ownership is transferred
   println!("{}", a);// Failed to compile! "A" has been released and can no longer be used
}
Copy the code

In a benchmark comparing the performance of REST apis (Rust using Rocket and Node.js using Restify), Rust processed 72,000 requests per second compared to Node.js’s 8,000, using about 1MB of memory when idle, Node.js is 19MB. In another test (Rust using Nickel and Node.js using Restana), Rust responded to requests nearly 100 times faster on average than Node.js.

For details, see Web Frameworks Benchmark.

reliability

Rust’s rich type system and ownership model ensures memory safety and thread-safety, allowing you to eliminate a wide variety of errors at compile time. The following are the explanations for memory safety and thread-safety:

Memory safety: In a memory-safe programming language, all memory access is clearly defined. Generally, memory insecurity includes: null pointer, wild pointer, dangling pointer, using uninitialized pointer, illegal release, buffer overflow, execution of illegal function pointer, data contention, etc.

70% of Microsoft’s vulnerabilities are said to be memory security issues

Thread safety: Thread safety is a programming term that refers to the ability of a function or function library to correctly handle shared variables between multiple threads when called in a multi-threaded environment, so that the program functions can be correctly completed.

productivity

Rust has great documentation, a friendly compiler, and clear error messages, as well as integration with a top-notch package manager and build tools, multi-editor support for intelligent auto-completion and type checking, automatic formatting of code, and much more.

Application of Rust in front-end build tools

Deno

Github((80.9k STAR) : github.com/denoland/de…

Deno is a simple, modern, and secure JavaScript and TypeScript runtime that uses V8 and is built on Rust. Deno was created by Ryan Dahl, the creator of Node.js, and was first unveiled at the 2018 JS Conf Berlin lecture Design Mistakes in Node.

Deno was created to address the age-old problem of Node insecurity and bad package management, which sometimes causes headaches and angers for Node.js developers. Node-ipc, which creates a file on the desktop of all users to promote the author’s political views, has affected many open source projects including Vue CLI.

So Deno naturally has the following features:

  1. By default, programs running with Deno have no file, network, or environment access unless specifically enabled

    deno run --allow-read mod.ts
    Copy the code
  2. Support TypeScript right out of the box

  3. Only a single executable is compiled

  4. Embrace Web ecology standards, built-in FETCH, localStorage, Location, and other apis

    localStorage.setItem("myDemo"."Deno App"); // Has a persistent storage limit of 10M
    Copy the code
  5. Built-in dependency checker deno Info and code formatting tool deno FMT

  6. There is a standard set of reviewed modules that can be used with Deno: deno.land/ STD

At present, many companies are actively exploring Deno, including Amazon, Github, IBM, Vercel, Tencent, Microsoft and other head technology companies.

SWC

Github (21K STAR) : github.com/swc-project…

SWC is an extensible rust-based front-end build tool that currently has core functionality equivalent to Babel and contains the following modules:

The module state role
@swc/cli stable This module provides a command line entry
@swc/core stable This module provides the core SWC API
@swc/wasm-web stable This module allows you to synchronize transformation code within the browser using WebAssembly
@swc/jest stable Ts-jest substitute, can make the unit test speed has a qualitative increase
swc-loader stable This module allows SWC to be used with Webpack
swcpack In the construction of This module attempts to provide a complete builder module, which can be understood simply as Rust’s Rollup or Webpack

The official benchmark data is as follows:

name 1 core, sync 4 promises 100 promises
swc (es3) 616 ops/sec 1704 ops/sec 2199 ops/sec
swc (es2015) 677 ops/sec 1688 ops/sec 1911 ops/sec
swc (es2016) 1963 ops/sec 3948 op s/sec 5580 ops/sec
swc (es2017) 1971 ops/sec 3948 ops/sec 6259 ops/sec
swc (es2018) 2555 ops/sec 4884 ops/sec 8108 ops/sec
swc-optimize (es3) 645 ops/sec 1716 ops/sec 1860 ops/sec
babel (es5) 34.05 ops/SEC 27.28 ops/SEC 32 ops/sec

SWC is 20 times faster than Babel on a single thread and 70 times faster on four cores.

SWC is already widely used by tools like next.js, Parcel, and Deno, as well as by companies like Vercel, Bytedance, Tencent, And Shopify.

Parcel

Github (40K STAR) : github.com/parcel-bund…

With a zero-configuration build tool that uses HTML as an entry point, Parcel supports a variety of languages and file types right out of the box, from Web technologies like HTML, CSS and JavaScript to assets like images, fonts, and video. When you use file types that aren’t included by default, Parcel automatically installs all the necessary plug-ins and development dependencies for you. The JavaScript compiler and source mapping for Parcel is built on top of the SWC compiler, where Parcel implements dependency collection, bundling, tree shaking, hot overloading, and more.

Parcel is already being used by Microsoft, Atlassian, SourceGraph, and more.

Rome

Github (17.2 STAR) : github.com/rome/tools

Rome is a Node.js-based front-end build bucket by Babel, which includes but is not limited to JavaScript, TypeScript, JSON, HTML, Markdown, and CSS. Announced plans to use Rust refactoring on September 21, 2021.

Other Tools (WIP)

Dprint: 30x faster than Prettier, written in Rust

Postcss-rs: written in Rust, 20x faster than PostCSS

The application of Rust in desktop application development

Tauri

Github (34.7 STAR) : github.com/tauri-apps/…

For a long time, including now, Electron has been the most popular cross-platform desktop application development framework, currently with 101K stars on Github. It allows you to build desktop applications using pure front-end technologies (HTML, CSS, JS, Node.js), However, there are two obvious flaws that have been criticized: the package size is too large and the memory footprint is too high. The root cause of these two problems is that Electron is built on Chromium and Node.js.

Tauri is a replacement for Electron. Now Tauri is trying to remove Chromium and use Rust to bind to the system’s built-in Webview. Basically, in the Electon era, your application will always use Chromium kernel. Back in the Tauri era, your app used Edge/Webview2 on Windows, WebKit on macOS, and WebKitGTK on Linux. The benefits of Rust and Webview are obvious: the package size is minimal and the memory footprint is extremely low. Here are the official figures:

Detail Tauri Electron
Installer Size Linux 3.1 MB 52.1 MB
Memory Consumption Linux 180 MB 462 MB
Launch Time Linux 0.39 s 0.80 s
Interface Service Provider WRY Chromium
Backend Binding Rust Node.js (ECMAScript)
Underlying Engine Rust V8 (C/C++)
FLOSS Yes No
Multithreading Yes Yes
Bytecode Delivery Yes No
Multiple Windows Yes Yes
Auto Updater Yes Yes1
Custom App Icon Yes Yes
Windows Binary Yes Yes
MacOS Binary Yes Yes
Linux Binary Yes Yes
iOS Binary Soon No
Android Binary Soon No
Desktop Tray Yes Yes
Sidecar Binaries Yes

That looks pretty good, but don’t forget that if you’re developing with Tauri, the back end (or main process in Electron) can only use Rust at the moment, which is quite a learning cost, and Tauri has a long way to go, but it’s a Renaissance innovation.

Application of Rust in WebAssembly

WebAssembly is a new way of encoding with a compact binary format that can run with near-native performance in modern Web browsers. There are currently two main use cases for Rust and WebAssembly:

  • Entire Web applications are developed based on Rust: frameworks like Yew

  • Use Rust in an existing JavaScript front end

Yew

Github (Github 20K STAR) : github.com/yewstack/ye…

Yew is an advanced Rust framework designed to create multithreaded front-end applications using WebAssembly. It has several features:

  • Component-based framework that makes it easy to create interactive UIs. Developers with experience with frameworks such as React or Elm will feel comfortable working with Yew.
  • High performance. Front-end developers can easily offload work to the back end to reduce DOM API calls and achieve exceptional performance. (Another “Renaissance innovation”… 😂)
  • Support for interaction with JavaScript, allowing developers to use NPM packages and combine them with existing JavaScript applications.

A simple Yew application code looks like this:

use yew::prelude::*;

enum Msg {
    AddOne,
}

struct Model {
    value: i64,}impl Component for Model {
    type Message = Msg;
    type Properties = ();

    fn create(_ctx: &Context<Self- > >)Self {
        Self {
            value: 0,}}fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            Msg::AddOne => {
                self.value += 1;
                // the value has changed so we need to
                // re-render for it to appear on the page
                true}}}fn view(&self, ctx: &Context<Self>) -> Html {
        // This gives us a component's "`Scope`" which allows us to send messages, etc to the component.
        let link = ctx.link();
        html! {
            <div>
                <button onclick={link.callback(|_| Msg::AddOne)}>{ "+ 1" }</button>
                <p>{ self.value }</p>
            </div>
        }
    }
}

fn main() {
    yew::start_app::<Model>();
}
Copy the code

wasm-bindgen

Github (5.0k STAR) : github.com/rustwasm/wa…

The Current WebAssembly type system is small, with only four numeric types, so if you want to use complex types (such as strings, objects, arrays, structs), you need to be careful:

  • Convert a string or object into something that the WebAssembly module can understand
  • Converts the return value of a WebAssembly module to a string or object that JavaScript can understand

But converting them each time (serializing them into linear memory and providing references to their locations) is tedious and error-prone. Fortunately, Rust World came up with WASMA-BindGen to facilitate advanced interaction between WebAssembly modules and JavaScript, It’s also very simple to use:

  1. Create a Rust project

    $ cargo new --lib hello_world
    Created library `hello_world` package
    Copy the code
  2. Open the Cargo. Toml file and add the WASM-Bindgen dependency

    [package]
    name = "hello_world"
    version = "0.1.0 from"
    authors = ["Sendil Kumar <[email protected]>"]
    edition = "2018"
    
    [lib]
    crate-type = ["cdylib"]
    
    [dependencies]
    wasm-bindgen = "0.2.56"
    Copy the code
  3. Open the SRC /lib.rs file and replace the contents with the following

    use wasm_bindgen::prelude::*;
    
    #[wasm_bindgen]
    pub fn hello_world() - >String {
      "Hello World".to_string()
    }
    Copy the code
  4. Compile to wASM module

    cargo build --target=wasm32-unknown-unknown
    Copy the code
  5. Install wASM -bindgen- CLI and convert the wASM file to a JavaScript file

      cargo install wasm-bindgen-cli
      wasm-bindgen target/wasm32-unknown-unknown/debug/hello_world.wasm --out-dir .
    # ls -lrta
    # 76330 hello_world_bg.wasm
    # 1218 hello_world.js
    # 109 hello_world.d.ts
    # 190 hello_world_bg.d.ts
    Copy the code
  6. Then you can use the hello_world.js file, which loads the WASM files for you.

wasm-pack

Github (4.1k star) : github.com/rustwasm/wa…

This is a tool to package your Rust code directly into an NPM package with four simple commands:

  • new: Generate a new Rust Wasm project using the template
  • build: Generates an NPM WASM PKG from Rustwasm Crate
  • test: Run browser tests
  • pack å’Œ publish: Creates a compressed package and publishes it to the image repository

It’s worth noting that WebAssembly is not a panacea for improving the performance of Web applications, and for now, using the DOM API in WebAssembly is still slower than calling it from JavaScript. However, the WebAssembly Interface Types project will solve the temporary problem. If you want to learn more about this, check out this Mozilla article.

Binding between Rust and Node

NAPI-RS

Github (2.5K STAR) : github.com/napi-rs/nap…

API-RS is a framework for building pre-compiled Node.js plug-ins in Rust, on which SWC is based.

See the article “Developing High-performance Node.js Extensions with Rust and N-API” for more information.

Write in the last

With the increasing complexity of front-end development, the efficiency of supporting tool chain will not be ignored. Limited by the efficiency of Node.js language itself, more tools will be rewritten by Rust in recent years, and the efficiency is expected to be improved several times or even tens of times. The combination of Rust and WebAssembly is also exciting, but at this point it’s a long way from mass production.

References:

  • vercel.app
  • remix.run
  • deno.com/deploy
  • Github.com/rustwasm/wa…
  • Github.com/rustwasm/wa…
  • webassembly.org/
  • Github.com/yewstack/ye…
  • Github.com/tauri-apps/…
  • Github.com/postcss-rs/…
  • Github.com/devongovett…
  • rome.tools/
  • parceljs.org/
  • swc.rs/
  • deno.land/
  • Web-frameworks-benchmark.net lify. App/compare? F = e…
  • rocket.rs/
  • restify.com/
  • Github.com/nickel-org/…
  • Github.com/BackendStac…
  • www.thefeedbackloop.xyz/safety-is-r…
  • github.com/graydon
  • Github.com/WebAssembly…
  • Github.com/napi-rs/nap…
  • nextjs.org/
  • Developing High Performance Node.js extensions with Rust and N-API