mirror of
https://github.com/bspeice/speice.io
synced 2024-11-14 22:18:10 -05:00
184 lines
49 KiB
HTML
184 lines
49 KiB
HTML
<!doctype html><html lang=en dir=ltr class="blog-wrapper blog-post-page plugin-blog plugin-id-default" data-has-hydrated=false><meta charset=UTF-8><meta name=generator content="Docusaurus v3.6.0"><title data-rh=true>Isomorphic desktop apps with Rust | The Old Speice Guy</title><meta data-rh=true name=viewport content="width=device-width,initial-scale=1.0"><meta data-rh=true name=twitter:card content=summary_large_image><meta data-rh=true property=og:url content=https://speice.io/2018/09/isomorphic-apps><meta data-rh=true property=og:locale content=en><meta data-rh=true name=docusaurus_locale content=en><meta data-rh=true name=docusaurus_tag content=default><meta data-rh=true name=docsearch:language content=en><meta data-rh=true name=docsearch:docusaurus_tag content=default><meta data-rh=true property=og:title content="Isomorphic desktop apps with Rust | The Old Speice Guy"><meta data-rh=true name=description content="I both despise Javascript and am stunned by its success doing some really cool things. It's"><meta data-rh=true property=og:description content="I both despise Javascript and am stunned by its success doing some really cool things. It's"><meta data-rh=true property=og:type content=article><meta data-rh=true property=article:published_time content=2018-09-15T12:00:00.000Z><link data-rh=true rel=icon href=/img/favicon.ico><link data-rh=true rel=canonical href=https://speice.io/2018/09/isomorphic-apps><link data-rh=true rel=alternate href=https://speice.io/2018/09/isomorphic-apps hreflang=en><link data-rh=true rel=alternate href=https://speice.io/2018/09/isomorphic-apps hreflang=x-default><script data-rh=true type=application/ld+json>{"@context":"https://schema.org","@id":"https://speice.io/2018/09/isomorphic-apps","@type":"BlogPosting","author":{"@type":"Person","name":"Bradlee Speice"},"dateModified":"2024-11-09T21:40:50.000Z","datePublished":"2018-09-15T12:00:00.000Z","description":"I both despise Javascript and am stunned by its success doing some really cool things. It's","headline":"Isomorphic desktop apps with Rust","isPartOf":{"@id":"https://speice.io/","@type":"Blog","name":"Blog"},"keywords":[],"mainEntityOfPage":"https://speice.io/2018/09/isomorphic-apps","name":"Isomorphic desktop apps with Rust","url":"https://speice.io/2018/09/isomorphic-apps"}</script><link rel=alternate type=application/rss+xml href=/rss.xml title="The Old Speice Guy RSS Feed"><link rel=alternate type=application/atom+xml href=/atom.xml title="The Old Speice Guy Atom Feed"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css integrity=sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM crossorigin><link rel=stylesheet href=/assets/css/styles.ae6ff4a3.css><script src=/assets/js/runtime~main.751b419d.js defer></script><script src=/assets/js/main.62ce6156.js defer></script><body class=navigation-with-keyboard><script>!function(){var t,e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();t=null!==e?e:"light",document.documentElement.setAttribute("data-theme",t)}(),function(){try{for(var[t,e]of new URLSearchParams(window.location.search).entries())if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id=__docusaurus><div role=region aria-label="Skip to main content"><a class=skipToContent_fXgn href=#__docusaurus_skipToContent_fallback>Skip to main content</a></div><nav aria-label=Main class="navbar navbar--fixed-top"><div class=navbar__inner><div class=navbar__items><button aria-label="Toggle navigation bar" aria-expanded=false class="navbar__toggle clean-btn" type=button><svg width=30 height=30 viewBox="0 0 30 30" aria-hidden=true><path stroke=currentColor stroke-linecap=round stroke-miterlimit=10 stroke-width=2 d="M4 7h22M4 15h22M4 23h22"/></svg></button><a class=navbar__brand href=/><div class=navbar__logo><img src=/img/logo.svg alt="Sierpinski Gasket" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src=/img/logo-dark.svg alt="Sierpinski Gasket" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div><b class="navbar__title text--truncate">The Old Speice Guy</b></a></div><div class="navbar__items navbar__items--right"><a href=https://github.com/bspeice target=_blank rel="noopener noreferrer" class="navbar__item navbar__link header-github-link"></a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type=button disabled title="Switch between dark and light mode (currently light mode)" aria-label="Switch between dark and light mode (currently light mode)" aria-live=polite aria-pressed=false><svg viewBox="0 0 24 24" width=24 height=24 class=lightToggleIcon_pyhR><path fill=currentColor d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"/></svg><svg viewBox="0 0 24 24" width=24 height=24 class=darkToggleIcon_wfgR><path fill=currentColor d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"/></svg></button></div><div class=navbarSearchContainer_Bca1><div class=navbar__search><span aria-label="expand searchbar" role=button class=search-icon tabindex=0></span><input id=search_input_react type=search placeholder=Loading... aria-label=Search class="navbar__search-input search-bar" disabled></div></div></div></div><div role=presentation class=navbar-sidebar__backdrop></div></nav><div id=__docusaurus_skipToContent_fallback class="main-wrapper mainWrapper_z2l0"><div class="container margin-vert--lg"><div class=row><aside class="col col--3"><nav class="sidebar_re4s thin-scrollbar" aria-label="Blog recent posts navigation"><div class="sidebarItemTitle_pO2u margin-bottom--md">All posts</div><div role=group><h3>2022</h3><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2011/11/webpack-industrial-complex>The webpack industrial complex</a></ul></div><div role=group><h3>2019</h3><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/12/release-the-gil>Release the GIL</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/09/binary-format-shootout>Binary format shootout</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/06/high-performance-systems>On building high performance systems</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/05/making-bread>Making bread</a></ul><div role=group><h4>Allocations in Rust</h4><ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/02/understanding-allocations-in-rust>Foreword</a><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/02/the-whole-world>Global memory</a><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/02/stacking-up>Fixed memory</a><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/02/a-heaping-helping>Dynamic memory</a><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/02/08/compiler-optimizations>Compiler optimizations</a><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2019/02/summary>Summary</a></ul></ul></div></div><div role=group><h3>2018</h3><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2018/12/allocation-safety>QADAPT - debug_assert! for allocations</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2018/12/what-small-business-really-means>More "what companies really mean"</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2018/10/case-study-optimization>A case study in heaptrack</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a aria-current=page class="sidebarItemLink_mo7H sidebarItemLinkActive_I1ZP" href=/2018/09/isomorphic-apps>Isomorphic desktop apps with Rust</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2018/09/primitives-in-rust-are-weird>Primitives in Rust are weird (and cool)</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2018/06/dateutil-parser-to-rust>What I learned porting dateutil to Rust</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2018/05/hello>Hello!</a></ul><div role=group><h4>Captain's Cookbook</h4><ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2018/01/captains-cookbook-part-1>Project setup</a><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2018/01/captains-cookbook-part-2>Practical usage</a></ul></ul></div></div><div role=group><h3>2016</h3><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/11/pca-audio-compression>PCA audio compression</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/10/rustic-repodcasting>A Rustic re-podcasting server</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/06/event-studies-and-earnings-releases>Event studies and earnings releases</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/05/the-unfair-casino>The unfair casino</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/04/tick-tock>Tick tock...</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/03/tweet-like-me>Tweet like me</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/03/predicting-santander-customer-happiness>Predicting Santander customer happiness</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/02/profitability-using-the-investment-formula>Profitability using the investment formula</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/02/guaranteed-money-maker>Guaranteed money maker</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/01/cloudy-in-seattle>Cloudy in Seattle</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2016/01/complaining-about-the-weather>Complaining about the weather</a></ul></div><div role=group><h3>2015</h3><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2015/12/testing-cramer>Testing Cramer</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2015/11/autocallable>Autocallable Bonds</a></ul><ul class="sidebarItemList_Yudw clean-list"><li class=sidebarItem__DBe><a class=sidebarItemLink_mo7H href=/2015/11/welcome>Welcome, and an algorithm</a></ul></div></nav></aside><main class="col col--7"><article><header><h1 class=title_f1Hy>Isomorphic desktop apps with Rust</h1><div class="container_mt6G margin-vert--md"><time datetime=2018-09-15T12:00:00.000Z>September 15, 2018</time> · <!-- -->10 min read</div><div class="margin-top--md margin-bottom--sm row"><div class="col col--12 authorCol_Hf19"><div class="avatar margin-bottom--sm"><div class="avatar__intro authorDetails_lV9A"><div class=avatar__name><span class=authorName_yefp>Bradlee Speice</span></div><div class=authorSocials_rSDt><a href=https://github.com/bspeice target=_blank rel="noopener noreferrer" class=authorSocialLink_owbf title=GitHub><svg viewBox="0 0 256 250" width=1em height=1em class="authorSocialLink_owbf githubSvg_Uu4N" style=--dark:#000;--light:#fff preserveAspectRatio=xMidYMid><path d="M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46 6.397 1.185 8.746-2.777 8.746-6.158 0-3.052-.12-13.135-.174-23.83-35.61 7.742-43.124-15.103-43.124-15.103-5.823-14.795-14.213-18.73-14.213-18.73-11.613-7.944.876-7.78.876-7.78 12.853.902 19.621 13.19 19.621 13.19 11.417 19.568 29.945 13.911 37.249 10.64 1.149-8.272 4.466-13.92 8.127-17.116-28.431-3.236-58.318-14.212-58.318-63.258 0-13.975 5-25.394 13.188-34.358-1.329-3.224-5.71-16.242 1.24-33.874 0 0 10.749-3.44 35.21 13.121 10.21-2.836 21.16-4.258 32.038-4.307 10.878.049 21.837 1.47 32.066 4.307 24.431-16.56 35.165-13.12 35.165-13.12 6.967 17.63 2.584 30.65 1.255 33.873 8.207 8.964 13.173 20.383 13.173 34.358 0 49.163-29.944 59.988-58.447 63.157 4.591 3.972 8.682 11.762 8.682 23.704 0 17.126-.148 30.91-.148 35.126 0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002 256 57.307 198.691 0 128.001 0Zm-80.06 182.34c-.282.636-1.283.827-2.194.39-.929-.417-1.45-1.284-1.15-1.922.276-.655 1.279-.838 2.205-.399.93.418 1.46 1.293 1.139 1.931Zm6.296 5.618c-.61.566-1.804.303-2.614-.591-.837-.892-.994-2.086-.375-2.66.63-.566 1.787-.301 2.626.591.838.903 1 2.088.363 2.66Zm4.32 7.188c-.785.545-2.067.034-2.86-1.104-.784-1.138-.784-2.503.017-3.05.795-.547 2.058-.055 2.861 1.075.782 1.157.782 2.522-.019 3.08Zm7.304 8.325c-.701.774-2.196.566-3.29-.49-1.119-1.032-1.43-2.496-.726-3.27.71-.776 2.213-.558 3.315.49 1.11 1.03 1.45 2.505.701 3.27Zm9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033-1.448-.439-2.395-1.613-2.103-2.626.301-1.01 1.747-1.484 3.207-1.028 1.446.436 2.396 1.602 2.095 2.622Zm10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95-1.53.034-2.769-.82-2.786-1.86 0-1.065 1.202-1.932 2.733-1.958 1.522-.03 2.768.818 2.768 1.868Zm10.555-.405c.182 1.03-.875 2.088-2.387 2.37-1.485.271-2.861-.365-3.05-1.386-.184-1.056.893-2.114 2.376-2.387 1.514-.263 2.868.356 3.061 1.403Z"/></svg></a></div></div></div></div></div></header><div id=__blog-post-container class=markdown><p>I both despise Javascript and am stunned by its success doing some really cool things. It's
|
|
<a href=https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript target=_blank rel="noopener noreferrer">this duality</a> that's
|
|
led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I
|
|
bootstrap a simple desktop application.</p>
|
|
<p>See, as much as
|
|
<a href=https://webassembly.org/docs/faq/#is-webassembly-trying-to-replace-javascript target=_blank rel="noopener noreferrer">Webassembly isn't trying to replace Javascript</a>,
|
|
<strong>I want Javascript gone</strong>. There are plenty of people who don't share my views, and they are
|
|
probably nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think
|
|
it's hilarious that the
|
|
<a href=https://ecma-international.org/publications/standards/Ecma-402.htm target=_blank rel="noopener noreferrer">language specification</a>
|
|
dramatically outpaces anyone's
|
|
<a href=https://kangax.github.io/compat-table/es2016plus/ target=_blank rel="noopener noreferrer">actual implementation</a>. The answer to this
|
|
conundrum is of course to recompile code from newer versions of the language to older versions <em>of
|
|
the same language</em> before running. At least <a href=https://babeljs.io/ target=_blank rel="noopener noreferrer">Babel</a> is a nice tongue-in-cheek reference.</p>
|
|
<p>Yet for as much hate as <a href=https://electronjs.org/ target=_blank rel="noopener noreferrer">Electron</a> receives, it does a stunningly good job at solving a really hard
|
|
problem: <em>how the hell do I put a button on the screen and react when the user clicks it</em>? GUI
|
|
programming is hard, straight up. But if browsers are already able to run everywhere, why don't we
|
|
take advantage of someone else solving the hard problems for us? I don't like that I have to use
|
|
Javascript for it, but I really don't feel inclined to whip out good ol' <a href=https://wxwidgets.org/ target=_blank rel="noopener noreferrer">wxWidgets</a>.</p>
|
|
<p>Now there are other native solutions (<a href=https://github.com/LeoTindall/libui-rs/ target=_blank rel="noopener noreferrer">libui-rs</a>, <a href=https://github.com/PistonDevelopers/conrod target=_blank rel="noopener noreferrer">conrod</a>, <a href=https://github.com/kenz-gelsoft/wxRust target=_blank rel="noopener noreferrer">oh hey wxWdidgets again!</a>), but
|
|
those also have their own issues with distribution, styling, etc. With Electron, I can
|
|
<code>yarn create electron-app my-app</code> and just get going, knowing that packaging/upgrades/etc. are built
|
|
in.</p>
|
|
<p>My question is: given recent innovations with WASM, <em>are we Electron yet</em>?</p>
|
|
<p>No, not really.</p>
|
|
<p>Instead, <strong>what would it take to get to a point where we can skip Javascript in Electron apps?</strong></p>
|
|
<p>Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There
|
|
may already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to
|
|
try and organize what I did manage to discover.</p>
|
|
<p>I should also mention that the content and things I'm talking about here are not intended to be
|
|
prescriptive, but more "if someone else is interested, what do we already know doesn't work?" <em>I
|
|
expect everything in this post to be obsolete within two months.</em> Even over the course of writing
|
|
this, <a href=https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/ target=_blank rel="noopener noreferrer">a separate blog post</a> had
|
|
to be modified because <a href=https://github.com/WebAssembly/binaryen/pull/1642 target=_blank rel="noopener noreferrer">upstream changes</a> broke a
|
|
<a href=https://github.com/rustwasm/wasm-bindgen/pull/787 target=_blank rel="noopener noreferrer">Rust tool</a> the post tried to use. The post
|
|
ultimately
|
|
<a href=https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/#comment-477 target=_blank rel="noopener noreferrer">got updated</a>, <strong>but
|
|
all this happened within the span of a week.</strong> Things are moving quickly.</p>
|
|
<p>I'll also note that we're going to skip <a href=http://asmjs.org/ target=_blank rel="noopener noreferrer">asm.js</a> and <a href=https://kripken.github.io/emscripten-site/ target=_blank rel="noopener noreferrer">emscripten</a>. Truth be told, I couldn't get
|
|
either of these to output anything, and so I'm just going to say
|
|
<a href=https://en.wikipedia.org/wiki/Here_be_dragons target=_blank rel="noopener noreferrer">here be dragons.</a> Everything I'm discussing here
|
|
uses the <code>wasm32-unknown-unknown</code> target.</p>
|
|
<p>The code that I <em>did</em> get running is available
|
|
<a href=https://github.com/speice-io/isomorphic-rust target=_blank rel="noopener noreferrer">over here</a>. Feel free to use it as a starting point,
|
|
but I'm mostly including the link as a reference for the things that were attempted.</p>
|
|
<h1>An Example Running Application</h1>
|
|
<p>So, I did <em>technically</em> get a running application:</p>
|
|
<p><img decoding=async loading=lazy alt="Electron app using WASM" src=/assets/images/electron-percy-wasm-9ccb2be15a9bed6da44486afc266bad5.png width=800 height=319 class=img_ev3q></p>
|
|
<p>...which you can also try out if you want:</p>
|
|
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">git</span><span class="token plain"> clone https://github.com/speice-io/isomorphic-rust.git</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">cd</span><span class="token plain"> isomorphic_rust/percy</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">yarn</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">install</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">yarn</span><span class="token plain"> start</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|
<p>...but I wouldn't really call it a "high quality" starting point to base future work on. It's mostly
|
|
there to prove this is possible in the first place. And that's something to be proud of! There's a
|
|
huge amount of engineering that went into showing a window with the text "It's alive!".</p>
|
|
<p>There's also a lot of usability issues that prevent me from recommending anyone try Electron and
|
|
WASM apps at the moment, and I think that's the more important thing to discuss.</p>
|
|
<h1>Issue the First: Complicated Toolchains</h1>
|
|
<p>I quickly established that <a href=https://github.com/rustwasm/wasm-bindgen target=_blank rel="noopener noreferrer">wasm-bindgen</a> was necessary to "link" my Rust code to Javascript. At
|
|
that point you've got an Electron app that starts an HTML page which ultimately fetches your WASM
|
|
blob. To keep things simple, the goal was to package everything using <a href=https://webpack.js.org/ target=_blank rel="noopener noreferrer">webpack</a> so that I could just
|
|
load a <code>bundle.js</code> file on the page. That decision was to be the last thing that kinda worked in
|
|
this process.</p>
|
|
<p>The first issue
|
|
<a href=https://www.reddit.com/r/rust/comments/98lpun/unable_to_load_wasm_for_electron_application/ target=_blank rel="noopener noreferrer">I ran into</a>
|
|
while attempting to bundle everything via <code>webpack</code> is a detail in the WASM spec:</p>
|
|
<blockquote>
|
|
<p>This function accepts a Response object, or a promise for one, and ... <strong>[if > it] does not match
|
|
the <code>application/wasm</code> MIME type</strong>, the returned promise will be rejected with a TypeError;</p>
|
|
<p><a href=https://webassembly.org/docs/web/#additional-web-embedding-api target=_blank rel="noopener noreferrer">WebAssembly - Additional Web Embedding API</a></p>
|
|
</blockquote>
|
|
<p>Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the
|
|
web this isn't a huge issue, as the server can set MIME types when delivering the blob. With
|
|
Electron, you're resolving things with a <code>file://</code> URL and thus can't control the MIME type:</p>
|
|
<p><img decoding=async loading=lazy alt="TypeError: Incorrect response MIME type. Expected &#39;application/wasm&#39;." src=/assets/images/incorrect-MIME-type-a977835e8dcbfdb20fdda3c67ee4f76c.png width=795 height=301 class=img_ev3q></p>
|
|
<p>There are a couple of solutions depending on how far into the deep end you care to venture:</p>
|
|
<ul>
|
|
<li>Embed a static file server in your Electron application</li>
|
|
<li>Use a <a href=https://electronjs.org/docs/api/protocol target=_blank rel="noopener noreferrer">custom protocol</a> and custom protocol handler</li>
|
|
<li>Host your WASM blob on a website that you resolve at runtime</li>
|
|
</ul>
|
|
<p>But all these are pretty bad solutions and defeat the purpose of using WASM in the first place.
|
|
Instead, my workaround was to
|
|
<a href=https://github.com/webpack/webpack/issues/7918 target=_blank rel="noopener noreferrer">open a PR with <code>webpack</code></a> and use regex to remove
|
|
calls to <code>instantiateStreaming</code> in the
|
|
<a href=https://github.com/speice-io/isomorphic-rust/blob/master/percy/build.sh#L21-L25 target=_blank rel="noopener noreferrer">build script</a>:</p>
|
|
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">cargo</span><span class="token plain"> +nightly build </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">wasm32-unknown-unknown </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> wasm-bindgen </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$WASM_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/debug/</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$WASM_NAME</span><span class="token string" style="color:hsl(119, 34%, 47%)">.wasm"</span><span class="token plain"> --out-dir </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> --no-typescript </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Have to use --mode=development so we can patch out the call to instantiateStreaming</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/node_modules/webpack-cli/bin/cli.js"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--mode</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">development </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/app_loader.js"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/bundle.js"</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sed</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-i</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'s/.*instantiateStreaming.*//g'</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/bundle.js"</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|
<p>Once that lands, the
|
|
<a href=https://github.com/speice-io/isomorphic-rust/blob/master/percy_patched_webpack/build.sh#L24-L27 target=_blank rel="noopener noreferrer">build process</a>
|
|
becomes much simpler:</p>
|
|
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">cargo</span><span class="token plain"> +nightly build </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">wasm32-unknown-unknown </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> wasm-bindgen </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$WASM_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/debug/</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$WASM_NAME</span><span class="token string" style="color:hsl(119, 34%, 47%)">.wasm"</span><span class="token plain"> --out-dir </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> --no-typescript </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/node_modules/webpack-cli/bin/cli.js"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--mode</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">production </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/app_loader.js"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/bundle.js"</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|
<p>But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (via
|
|
<code>wasm-bindgen</code> and <code>webpack</code>), we still have to make an Electron app. For this purpose I used a
|
|
starter app from <a href=https://electronforge.io/ target=_blank rel="noopener noreferrer">Electron Forge</a>, and then a
|
|
<a href=https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8 target=_blank rel="noopener noreferrer"><code>prestart</code> script</a>
|
|
to actually handle starting the application.</p>
|
|
<p>The
|
|
<a href=https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8 target=_blank rel="noopener noreferrer">final toolchain</a>
|
|
looks something like this:</p>
|
|
<ul>
|
|
<li><code>yarn start</code> triggers the <code>prestart</code> script</li>
|
|
<li><code>prestart</code> checks for missing tools (<code>wasm-bindgen-cli</code>, etc.) and then:<!-- -->
|
|
<ul>
|
|
<li>Uses <code>cargo</code> to compile the Rust code into WASM</li>
|
|
<li>Uses <code>wasm-bindgen</code> to link the WASM blob into a Javascript file with exported symbols</li>
|
|
<li>Uses <code>webpack</code> to bundle the page start script with the Javascript we just generated<!-- -->
|
|
<ul>
|
|
<li>Uses <code>babel</code> under the hood to compile the <code>wasm-bindgen</code> code down from ES6 into something
|
|
browser-compatible</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li>The <code>start</code> script runs an Electron Forge handler to do some sanity checks</li>
|
|
<li>Electron actually starts</li>
|
|
</ul>
|
|
<p>...which is complicated. I think more work needs to be done to either build a high-quality starter
|
|
app that can manage these steps, or another tool that "just handles" the complexity of linking a
|
|
compiled WASM file into something the Electron browser can run.</p>
|
|
<h1>Issue the Second: WASM tools in Rust</h1>
|
|
<p>For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only
|
|
bits aren't any better at the moment. I get it, a lot of projects are just starting off, and that
|
|
leads to a fragmented ecosystem. Here's what I can recommend as a starting point:</p>
|
|
<p>Don't check in your <code>Cargo.lock</code> files to version control. If there's a disagreement between the
|
|
version of <code>wasm-bindgen-cli</code> you have installed and the <code>wasm-bindgen</code> you're compiling with in
|
|
<code>Cargo.lock</code>, you get a nasty error:</p>
|
|
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">it looks like the Rust project used to create this wasm file was linked against</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">a different version of wasm-bindgen than this binary:</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">rust wasm file: 0.2.21</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> this binary: 0.2.17</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain" style=display:inline-block></span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">Currently the bindgen format is unstable enough that these two version must</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">exactly match, so it's required that these two version are kept in sync by</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">either updating the wasm-bindgen dependency or this binary.</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|
<p>Not that I ever managed to run into this myself (<em>coughs nervously</em>).</p>
|
|
<p>There are two projects attempting to be "application frameworks": <a href=https://chinedufn.github.io/percy/ target=_blank rel="noopener noreferrer">percy</a> and <a href=https://github.com/DenisKolodin/yew target=_blank rel="noopener noreferrer">yew</a>. Between those,
|
|
I managed to get <a href=https://github.com/speice-io/isomorphic-rust/tree/master/percy target=_blank rel="noopener noreferrer">two</a>
|
|
<a href=https://github.com/speice-io/isomorphic-rust/tree/master/percy_patched_webpack target=_blank rel="noopener noreferrer">examples</a> running
|
|
using <code>percy</code>, but was unable to get an
|
|
<a href=https://github.com/speice-io/isomorphic-rust/tree/master/yew target=_blank rel="noopener noreferrer">example</a> running with <code>yew</code> because
|
|
of issues with "missing modules" during the <code>webpack</code> step:</p>
|
|
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">ERROR </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> ./dist/electron_yew_wasm_bg.wasm</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">Module not found: Error: Can</span><span class="token string" style="color:hsl(119, 34%, 47%)">'t resolve '</span><span class="token function" style="color:hsl(221, 87%, 60%)">env</span><span class="token string" style="color:hsl(119, 34%, 47%)">' in '</span><span class="token plain">/home/bspeice/Development/isomorphic_rust/yew/dist'</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/electron_yew_wasm_bg.wasm</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/electron_yew_wasm.js</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/app.js</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/app_loader.js</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|
<p>If you want to work with the browser APIs directly, your choices are <a href=https://crates.io/crates/percy-webapis target=_blank rel="noopener noreferrer">percy-webapis</a> or <a href=https://crates.io/crates/stdweb target=_blank rel="noopener noreferrer">stdweb</a> (or
|
|
eventually <a href=https://crates.io/crates/web-sys target=_blank rel="noopener noreferrer">web-sys</a>). See above for my <code>percy</code> examples, but when I tried
|
|
<a href=https://github.com/speice-io/isomorphic-rust/tree/master/stdweb target=_blank rel="noopener noreferrer">an example with <code>stdweb</code></a>, I was
|
|
unable to get it running:</p>
|
|
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class=codeBlockContent_biex><pre tabindex=0 class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class=codeBlockLines_e6Vv><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">ERROR </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> ./dist/stdweb_electron_bg.wasm</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain">Module not found: Error: Can</span><span class="token string" style="color:hsl(119, 34%, 47%)">'t resolve '</span><span class="token function" style="color:hsl(221, 87%, 60%)">env</span><span class="token string" style="color:hsl(119, 34%, 47%)">' in '</span><span class="token plain">/home/bspeice/Development/isomorphic_rust/stdweb/dist'</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/stdweb_electron_bg.wasm</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/stdweb_electron.js</span><br></span><span class=token-line style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/app_loader.js</span><br></span></code></pre><div class=buttonGroup__atx><button type=button aria-label="Copy code to clipboard" title=Copy class=clean-btn><span class=copyButtonIcons_eSgA aria-hidden=true><svg viewBox="0 0 24 24" class=copyButtonIcon_y97N><path fill=currentColor d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"/></svg><svg viewBox="0 0 24 24" class=copyButtonSuccessIcon_LjdS><path fill=currentColor d=M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z /></svg></span></button></div></div></div>
|
|
<p>At this point I'm pretty convinced that <code>stdweb</code> is causing issues for <code>yew</code> as well, but can't
|
|
prove it.</p>
|
|
<p>I did also get a <a href=https://github.com/speice-io/isomorphic-rust/tree/master/minimal target=_blank rel="noopener noreferrer">minimal example</a>
|
|
running that doesn't depend on any tools besides <code>wasm-bindgen</code>. However, it requires manually
|
|
writing "<code>extern C</code>" blocks for everything you need from the browser. Es no bueno.</p>
|
|
<p>Finally, from a tools and platform view, there are two up-and-coming packages that should be
|
|
mentioned: <a href=https://crates.io/crates/js-sys target=_blank rel="noopener noreferrer">js-sys</a> and <a href=https://crates.io/crates/web-sys target=_blank rel="noopener noreferrer">web-sys</a>. Their purpose is to be fundamental building blocks that exposes
|
|
the browser's APIs to Rust. If you're interested in building an app framework from scratch, these
|
|
should give you the most flexibility. I didn't touch either in my research, though I expect them to
|
|
be essential long-term.</p>
|
|
<p>So there's a lot in play from the Rust side of things, and it's just going to take some time to
|
|
figure out what works and what doesn't.</p>
|
|
<h1>Issue the Third: Known Unknowns</h1>
|
|
<p>Alright, so after I managed to get an application started, I stopped there. It was a good deal of
|
|
effort to chain together even a proof of concept, and at this point I'd rather learn <a href=https://www.typescriptlang.org/ target=_blank rel="noopener noreferrer">Typescript</a>
|
|
than keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know...</p>
|
|
<p>The important point I want to make is that there's a lot unknown about how any of this holds up
|
|
outside proofs of concept. Things I didn't attempt:</p>
|
|
<ul>
|
|
<li>Testing</li>
|
|
<li>Packaging</li>
|
|
<li>Updates</li>
|
|
<li>Literally anything related to why I wanted to use Electron in the first place</li>
|
|
</ul>
|
|
<h1>What it Would Take</h1>
|
|
<p>Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and
|
|
WASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an
|
|
application in production a couple months from now. But at the moment, I'm personally going to stay
|
|
away.</p>
|
|
<p>Let's finish with a wishlist then - here are the things that I think need to happen before
|
|
Electron/WASM/Rust can become a thing:</p>
|
|
<ul>
|
|
<li>Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet
|
|
(<a href=https://github.com/webpack/webpack/pull/7983 target=_blank rel="noopener noreferrer">#7983</a>)</li>
|
|
<li>Browser API libraries (<code>web-sys</code> and <code>stdweb</code>) need to make sure they can support running in
|
|
Electron (see module error above)</li>
|
|
<li>Projects need to stabilize. There's talk of <code>stdweb</code> being turned into a Rust API
|
|
<a href=https://github.com/rustwasm/team/issues/226#issuecomment-418475778 target=_blank rel="noopener noreferrer">on top of web-sys</a>, and percy
|
|
<a href=https://github.com/chinedufn/percy/issues/24 target=_blank rel="noopener noreferrer">moving to web-sys</a>, both of which are big changes</li>
|
|
<li><code>wasm-bindgen</code> is great, but still in the "move fast and break things" phase</li>
|
|
<li>A good "boilerplate" app would dramatically simplify the start-up costs;
|
|
<a href=https://github.com/chentsulin/electron-react-boilerplate target=_blank rel="noopener noreferrer">electron-react-boilerplate</a> comes to
|
|
mind as a good project to imitate</li>
|
|
<li>More blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm
|
|
doing</li>
|
|
</ul></div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Blog post page navigation"><a class="pagination-nav__link pagination-nav__link--prev" href=/2018/09/primitives-in-rust-are-weird><div class=pagination-nav__sublabel>Older post</div><div class=pagination-nav__label>Primitives in Rust are weird (and cool)</div></a><a class="pagination-nav__link pagination-nav__link--next" href=/2018/10/case-study-optimization><div class=pagination-nav__sublabel>Newer post</div><div class=pagination-nav__label>A case study in heaptrack</div></a></nav></main></div></div></div><footer class=footer><div class="container container-fluid"><div class="footer__bottom text--center"><div class=footer__copyright>Copyright © 2024 Bradlee Speice</div></div></div></footer></div> |