<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用 Rust 編寫更快的 React 組件

          共 7023字,需瀏覽 15分鐘

           ·

          2021-12-10 01:55

          大家好,我是 ConardLi,上周發(fā)了一篇 Wasm 的文章,主要分析的是今年 Google 開發(fā)者大會上的 Wasm 主題:

          Wasm 為 Web 開發(fā)帶來無限可能

          其實主要還是我個人對 Rust 比較感興趣,在今天的文章中,我將帶大家完成一個將 Rust 實際應用到 React 項目中的小 Demo

          Wasm

          在開始之前,我們還是先來回顧下 Wasm:

          WebAssembly 是一種二進制指令格式,簡稱為 Wasm,它可以運行在適用于堆棧的虛擬機上。

          WebAssembly 存在的意義就是成為編程語言的可移植編譯目標,讓在 Web 上部署客戶端和服務端應用成為可能。

          Wasm 具有緊湊的二進制格式,可為我們提供近乎原生的網(wǎng)絡性能。隨著它變得越來越流行,許多語言都編寫了編譯成 Web 程序集的綁定工具。

          為什么是 Rust

          Rust 是一個快速、可靠二期又節(jié)約內(nèi)存的編程語言。在過去六年的 stackoverflow 的最受喜愛的編程語言中,它一直蟬聯(lián)榜首的位置,主要還是這個語言本身擁有眾多的優(yōu)點,比如:

          • 內(nèi)存安全
          • 類型安全
          • 消除數(shù)據(jù)競爭
          • 使用前編譯
          • 建立(并且鼓勵)在零抽象之上
          • 最小的運行時(無停止世界的垃圾搜集器,無 JIT 編譯器,無 VM
          • 低內(nèi)存占用(程序可以運行在資源受限的環(huán)境,比如小的微控制器)
          • 針對裸機(比如,寫一個 OS 內(nèi)核或者設備驅(qū)動,把 Rust 當一個 ‘高層’匯編器使用)”

          另外,RustWebAssembly 領域的貢獻非常大的,使用 Rust 編寫 WebAssembly 非常簡單。

          但是,Rust 存在的目的不是為了替代 JavaScript 而是和他形成互補,因為 Rust 語言的學習曲線是非常陡峭的,用它去完全替代 Web 開發(fā)幾乎是不可能的。

          所以,我們一般會在 Web 開發(fā)的工具鏈,或者前端頁面中一些非常大量的數(shù)據(jù)計算中的操作用到它。

          前置知識

          在開始開發(fā)之前,你需要了解一些前置知識,React 相關的就不多說了,我們來看看 Rust 相關的幾個重要概念。

          cargo

          cargorust 的代碼組織和包管理工具,你可以將它類比為 node.js 中的 npm

          cargo 提供了一系列強大的功能,從項目的建立、構建到測試、運行直至部署,為 rust 項目的管理提供盡可能完整的手段。同時,它也與 rust 語言及其編譯器 rustc 本身的各種特性緊密結合。

          rustup

          rustupRust 的安裝和工具鏈管理工具,并且官網(wǎng)推薦使用 rustup 安裝 Rust

          rustuprustc(rust編譯器) 和 cargo 等工具安裝在 Cargobin 目錄,但這些工具只是 Rust 工具鏈中組件的代理,真正工作的是工具鏈中的組件。通過 rustup 的命令可以指定使用不同版本的工具鏈。

          wasm-bindgen

          wasm-bindgen 提供了 JSRust 類型之間的橋梁,它允許 JS 使用字符串調(diào)用 Rust API,或者使用 Rust 函數(shù)來捕獲 JS 異常。

          wasm-bindgen 的核心是促進 javascriptRust 之間使用 wasm 進行通信。它允許開發(fā)者直接使用 Rust 的結構體、javascript的類、字符串等類型,而不僅僅是 wasm 支持的整數(shù)或浮點數(shù)類型。

          wasm-pack

          wasm-packRust / Wasm 工作組開發(fā)維護,是現(xiàn)在最為活躍的 WebAssembly 應用開發(fā)工具。

          wasm-pack 支持將代碼打包成 npm 模塊,并且附帶 Webpack 插件(wasm-pack-plugin),借助它,我們可以輕松的將 Rust 與已有的 JavaScript 應用結合。

          wasm32-unknown-unknown

          通過 rustuptarget 命令可以指定編譯的目標平臺,也就是編譯后的程序在哪種操作系統(tǒng)上運行。

          wasm-pack 使用 wasm32-unknown-unknown 目標編譯代碼。

          好了,了解了 Rust 相關的一些知識,我們一起來完成這個 Demo 吧。

          一起來做個 Demo

          在開始之前,要確保你的電腦上已經(jīng)安裝了 NodeRust,可以在命令行分別輸入 npmrustup 看看能否找到命令,如果沒安裝的話自己先安裝一下。

          初始化一個簡單 React 程序

          首先,我們來初始化一個 React 項目,命令行執(zhí)行 npm init

          然后,我們安裝一些開發(fā)項目必備的包:

          $?npm?i?react?react-dom
          $?npm?i?-D?webpack?webpack-cli?webpack-dev-server?html-webpack-plugin?
          $?npm?i?-D?babel-core?babel-loader?@babel/preset-env?@babel/preset-react

          然后,我們在項目中創(chuàng)建一些常用的文件夾:srcpagepublicbuild、和 dist

          我們在 page 文件夾中創(chuàng)建一個 index.jsx,編寫一些測試代碼:

          import?React?from?'react';
          import?ReactDOM?from?'react-dom';

          ReactDOM.render(<h1>code秘密花園?Hello,?world!h1>,?document.getElementById('root'));

          然后,我們?yōu)?babelwebpack 創(chuàng)建兩個配置文件:

          .babelrc

          {
          ????"presets":?[
          ????????"@babel/preset-env",
          ????????"@babel/preset-react"
          ????]
          }

          webpack.config.js

          const?HtmlWebpackPlugin?=?require('html-webpack-plugin');

          const?path?=?require('path');

          module.exports?=?{
          ??entry:?'./page/index.jsx',
          ??output:?{
          ????path:?path.resolve(__dirname,?'dist'),
          ????filename:?'bundle.[hash].js',
          ??},
          ??devServer:?{
          ????compress:?true,
          ????port:?8080,
          ????hot:?true,
          ????static:?'./dist',
          ????historyApiFallback:?true,
          ????open:?true,
          ??},
          ??module:?{
          ????rules:?[
          ??????{
          ????????test:?/.(js|jsx)$/,
          ????????exclude:?/node_modules/,
          ????????use:?{
          ??????????loader:?'babel-loader',
          ????????},
          ??????},
          ????],
          ??},
          ??plugins:?[
          ????new?HtmlWebpackPlugin({
          ??????template:?`${__dirname?}/public/index.html`,
          ??????filename:?'index.html',
          ????}),
          ??],
          ??mode:?'development',
          ??devtool:?'inline-source-map',
          };

          然后,在 public 下創(chuàng)建一個 index.html

          html>
          <html?lang="en">

          <head>
          ????<meta?charset="UTF-8">
          ????<meta?name="viewport"?content="width=device-width,?initial-scale=1.0">
          ????<title>code秘密花園title>
          head>

          <body>
          ????<div?id="root">div>
          body>

          html>

          下面檢查下你的 package.json,看看和我的是不是一樣:

          {
          ??"name":?"react-wasm",
          ??"version":?"1.0.0",
          ??"description":?"一個?Rust?編寫?React?組件的?Demo",
          ??"main":?"src/index.jsx",
          ??"scripts":?{
          ????"dev":?"webpack?server"
          ??},
          ??"keywords":?[],
          ??"author":?"ConardLi",
          ??"license":?"MIT",
          ??"dependencies":?{
          ????"react":?"^17.0.2",
          ????"react-dom":?"^17.0.2"
          ??},
          ??"devDependencies":?{
          ????"@babel/core":?"^7.16.0",
          ????"@babel/preset-env":?"^7.16.4",
          ????"@babel/preset-react":?"^7.16.0",
          ????"babel-loader":?"^8.2.3",
          ????"html-webpack-plugin":?"^5.5.0",
          ????"webpack":?"^5.64.2",
          ????"webpack-cli":?"^4.9.1",
          ????"webpack-dev-server":?"^4.5.0"
          ??}
          }

          下面,執(zhí)行 npm install,然后 npm run dev,你就可以跑起來一個非常簡單的 React 應用:

          引入 Rust

          好了,下面我們來編寫我們的 Rust 組件(別忘了回顧下上面提到的 Rust 前置知識),首先我們使用 Rust 的包管理工具 cargo 來初始化一個簡單的 Rust 應用程序:

          cargo?init?--lib?.

          執(zhí)行完之后,會創(chuàng)建一個 Cargo.toml 和一個 src/lib.rc 文件。

          然后,我們在 ?Cargo.toml 中引入 wasm-bindgen 這個包,另外我們還需要告訴編譯器這個包是一個 cdylib

          [package]
          name = "react-wasm"
          version = "1.0.0"
          edition = "2021"

          [lib]
          crate-type = ["cdylib"]

          [dependencies]
          wasm-bindgen = "0.2"

          現(xiàn)在,你可以先嘗試執(zhí)行下 cargo build

          第一次執(zhí)行可能會比較慢,可以 Google 搜一下怎么將 cargo 配置為國內(nèi)源。

          好了,上面只是測試一下構建,它現(xiàn)在還派不上用場,我們下面還要執(zhí)行一下編譯目標,執(zhí)行:

          $?rustup?target?add?wasm32-unknown-unknown

          指定好 wasm32-unknown-unknown 這個編譯目標,我們才能把它應用到我們的 React 程序中,下面我們給我們的 src/lib.rs 寫兩個簡單的函數(shù):

          use?wasm_bindgen::prelude::*;

          #[wasm_bindgen]
          extern?"C"?{
          ????fn?alert(s:?&str);
          }

          #[wasm_bindgen]
          pub?fn?big_computation()?{
          ????alert("這個是一個超級耗時的復雜計算邏輯");
          }

          #[wasm_bindgen]
          pub?fn?welcome(name:?&str)?{
          ???alert(&format!("Hi 我是?{}?,我在 code秘密花園?!",?name));
          }

          為了確保我們的 Rust 應用程序正常工作,我們重新用 wasm32-unknown-unknown 編譯一下:

          $?cargo?build?--target?wasm32-unknown-unknown

          然后我們安裝一下 wasm-bindgen-cli 這個命令行工具,以便我們能利用我們創(chuàng)建的 WebAssembly 代碼:

          $?cargo?install?-f?wasm-bindgen-cli

          安裝后,我們可以使用 Rust 生成的 WebAssembly 給我們的 React 代碼創(chuàng)建一個包:

          $?wasm-bindgen?target/wasm32-unknown-unknown/debug/react_wasm.wasm?--out-dir?build

          執(zhí)行完成后,編譯好的 JavaScript 包和優(yōu)化好的 Wasm 代碼會保存到我們的 build 目錄中,以供 React 程序使用。

          在 React 程序中應用 Wasm

          下面,我們嘗試一下在我們的 React 程序中用上這些 Wasm 代碼,我們現(xiàn)在 package.json 中添加一些常用的 npm 腳本:

          ??"build:wasm":?"cargo?build?--target?wasm32-unknown-unknown",
          ??"build:bindgen":?"wasm-bindgen?target/wasm32-unknown-unknown/debug/rusty_react.wasm?--out-dir?build",
          ??"build":?"npm?run?build:wasm?&&?npm?run?build:bindgen?&&?npx?webpack",

          然后我們執(zhí)行 npm run build 就可以打包所有代碼啦。

          下面,我們還需要安裝一下上面我們提到的 wasm-packWebpack 插件,它可以幫助我們把 Wasm 代碼打包成 NPM 模塊:

          npm?i?-D?@wasm-tool/wasm-pack-plugin

          最后更新一下我們的 webpack.config.js,添加下面的配置:

          const?WasmPackPlugin?=?require("@wasm-tool/wasm-pack-plugin");

          ??...

          ??plugins:?[
          ????...
          ????new?WasmPackPlugin({
          ??????crateDirectory:?path.resolve(__dirname,?".")
          ????}),
          ??],
          ??...
          ??experiments:?{
          ????asyncWebAssembly:?true
          ??}

          下面,執(zhí)行一下這幾個命令:npm run build:wasm、npm run build:bindgen、npm run build,應該都不會報錯。

          最后,我們在我們的 React 組件中調(diào)用一下我們剛剛生成的 Wasm 模塊:

          import?React,?{?useState?}?from?"react";
          import?ReactDOM?from?"react-dom";

          const?wasm?=?import("../build/rusty_react");

          wasm.then(m?=>?{
          ??const?App?=?()?=>?{
          ????const?[name,?setName]?=?useState("");
          ????const?handleChange?=?(e)?=>?{
          ??????setName(e.target.value);
          ????}
          ????const?handleClick?=?()?=>?{
          ??????m.welcome(name);
          ????}

          ????return?(
          ??????<>
          ????????<div>
          ??????????<h1>Hi?thereh1>

          ??????????<button?onClick={m.big_computation}>Run?Computationbutton>
          ????????div>
          ????????<div>
          ??????????<input?type="text"?onChange={handleChange}?/>
          ??????????<button?onClick={handleClick}>Say?hello!button>
          ????????div>
          ??????
          ????);
          ??};

          ??ReactDOM.render(<App?/>,?document.getElementById("root"));
          });

          下面,你就可以在 React 組件中愉快的使用 Rust 了!

          參考

          • https://www.rust-lang.org/learn
          • https://rustwasm.github.io/
          • https://www.joshfinnie.com/blog/using-webassembly-created-in-rust-for-fast-react-components/

          最后

          遷移公眾號后之前的星標就丟失啦,而且之前的一些長讀記錄也會丟失,所以你可能會經(jīng)常收不到我公眾號的消息推送,大家可以點公眾號右上角的更多(...)— 設為星標


          我的書 「《算法通關之路》」 已經(jīng)出版了,想要突破算法面試的朋友不要錯過,京東淘寶當當亞馬遜等均有出售,電子版也有哦~

          • 后臺回復:typescript,獲取我寫的 typescript 系列文章,絕對精品
          • 后臺回復:電子書,自動獲取我為大家整理的大量經(jīng)典電子書,省去你篩選以及下載的時間
          • 后臺回復:不一樣的前端,自動獲取精選優(yōu)質(zhì)前端文章。
          • 后臺回復:算法,自動獲取精選算法文章。另外也可關注我的另外一個專注算法的公眾號力扣加加
          • 后臺回復:每日一薦,自動獲取我為大家總結的每日一薦月刊,內(nèi)含精品文章,實用技巧,高效工具等等



          瀏覽 72
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  男女福利视频 | 亚洲熟妇一区二区三区 | 天天日日天天爱人人爱人人爽 | 天天操天天操天天操 | 日韩大香蕉 |