Disclaimer: this guide might have been written under the influence of a few glasses of wine (what a lovely Pinotage), do NOT take the author's piss taking and opinions seriously.
Native apps for noobs (aka web devs, aka me)
Whether you are a [insert your framework/library of choice here] or vanilla JS lover, we can all agree (or not, you're entitled to your own opinion, me personally, don't care about it) that Vite has become a sort of de facto build/bundling tool (if you are still maintaining some dreaded webpack config that nobody knows wtf is actually doing, I feel for you). Built by a fantastic community, it's got plugins for almost anything, it's fast, it's simple, and it's awesome.
Wouldn't it be great if we could use it to take our apps beyond the browser, in a neat simple way? Well, thanks to Socket Supply and its Socket Runtime now we can (it's not like we couldn't before but for a long time all the options sucked, it wasn't simple, it was far from neat, not to point out names but remember Cordova, they have gotten better... but meh).
The Socket Runtime it's a runtime (duh 🙄) that allows you to build and run your app natively, on Desktop and Mobile. Still in development stages but it's already pretty effing sick, to make it plain without listing all the bels and whistles (I might get slapped for the next plain description), think of Electron but without the Chromium overhead (as I'm writing this, Discord is at ~800MB of RAM usage, just sitting there in the background, neat 😒) optional native extension API (i.e. build/bring your own stuff), bring your own backend, AND an actual, optional, peer to peer network, but let's not get into that or we might end up in a never ending debate, followed by throwing chairs at each other across the room.
Blah blah blah, whatever, stfu and get to the point.
We're not gonna build a real app (if you are here I assume you know wtf you are doing and building an app is not the subject of this little guide) we'll build a bare Hello World
demo app, using Vite as our bundler/build tool, and Socket Supply as our runtime. We'll use React (which I'm not a fan of and dread a little bit to be honest but hey, we can't all be perfect) but you can use whatever you want, it's all the same.
- Node.js: FYI, you can use the Socket Runtime without
node
if your app doesn't need bundling/build tools but that's not why you are reading this, I'm assuming you are a React and TypeScript lover and feel the pains of React Native (as I said, we can't all be perfect) - Socket Supply CLI (
ssc
): based on the assumption above do anpm i @socketsupply/socket -g
orpnpm i @socketsupply/socket -g
(I'll be usingpnpm
because like you, I also got opinions) here's the docs if you need them, there's anode
less install option
Start by scaffolding a new React app using Vite's template, I'll call it socket-supplied-react
because I'm a noob and naming is hard.
pnpm create vite@latest --template react-ts socket-supplied-react
cd
into the project's directory and install dependencies.
cd socket-supplied-react && pnpm i
The project's file structure will look something like the below tree:
.
├── README.md
├── index.html
├── package.json
├── public
│ └── vite.svg
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ └── react.svg
│ ├── index.css
│ ├── main.tsx
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
Initialize the Socket Runtime in the project's directory, it will create a socket.ini
configuration file.
ssc init
The configuration file has quite a few options, (don't stress, but do read the great inline documentation from the lovely people at Socket Supply) we'll only need to change a couple of them:
- first, we'll tell the Socket Runtime where our source code (aka app) will be located, by default it's
src
but we'll change it todist
(or whatever tickles your fancy, exceptbuild
, if you want to usebuild
make sure to also update Socket'soutput
option to something else) which is where we'll tell Vite to spit the bundled code. - second, we'll tell it to run a build script before starting the runtime, we'll use
pnpm build
since Vite is bundling our code.
[build]
; ssc will copy everything in this directory to the build output directory.
; This is useful when you want to avoid bundling or want to use tools like
; vite, webpack, rollup, etc. to build your project and then copy output to
; the Socket bundle resources directory.
; default value: "src"
copy = "dist" 👈
...
; The build script. It runs before the `[build] copy` phase.
script = "pnpm build" 👈
; IMPORTANT NOTE: if you are using `build` as the `copy` directory, make sure to change
; the `output` directory option below to something else, copy and output CANNOT clash.
output = "build" 👈
...
Tell Vite to spit the bundled code in the dist
directory.
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
build: {
outDir: 'dist', 👈
},
})
We're ready to build and run our app, from the project's root directory run:
ssc build --run
or the shorthand
ssc build -r
And just like that your React app is now native, I know, mind effing blowing.
Socket Runtime's got it, and it's enabled by default, just run:
ssc build --run --watch
or the shorthand
ssc build -r -w
Socket Runtime will watch for changes in your source code, run your build
script and reload the app when it detects them.
What if your app is so awesome (and big) that you don't want to rebuild it every time you make a change? Well, Socket Runtime's got a workaround for that too
- first, start Vite's dev server.
pnpm dev
- second, in a second terminal start Socket Runtime providing a host and port for the dev server, host is optional, if not provided it will default to
localhost
.
ssc build --run --host=localhost --port=5173
or the shorthand
ssc build -r --host=localhost --port=5173
Socket Runtime will proxy Vite's dev server, you can now make changes to your source code and see them reflected in the app without rebuilding it.
You are ready to add some native capabilities to your app, like access to the file system, or find out the host's OS platform/architecture, guess what, Socket Runtime's got it too.
Socket Runtime provides a bunch of native bindings available to your app via the 'socket:*' modules like socket:fs
or socket:os
, you can find a list here. Think of those as a sort of virtual/dynamic/aliased modules that only exists within the Socket Runtime, they are not part of your app's source code, they are provided by the Socket Runtime, and they are only available when building/running your app with the Socket Runtime.
Before we can use them we need to tell Vite those modules are external. Vite has a config option which allows us to specify external dependencies, we'll use a regex to match all the socket:*
modules. At the time of writing, this config option is only available when building/bundling your app, not when running the dev server, but as I said Vite's got a great community and some lovely people have already took the time and effort to scratch our itch, so go and share some love to the authors of vite-plugin-externalize-dependencies
Once you've finished sharing the love, lets install the plugin.
pnpm i -D vite-plugin-externalize-dependencies
And configure Vite to externalise the socket:*
modules for both build and dev server.
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import externalize from 'vite-plugin-externalize-dependencies' 👈
export default defineConfig({
plugins: [
externalize({
externals: [/^socket:.*/], 👈
}),
react(),
],
build: {
outDir: 'dist',
rollupOptions: {
external: [/^socket:.*/], 👈
},
},
})
Now we can import and use the socket:*
modules in our app.
// src/App.tsx
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";
import os from 'socket:os' 👈
...
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
You are running this application on <b>{os.platform()}</b> platform. 👈
</p>
</div>
...
I'm very excited about the Socket Runtime, if you are too, go and send some love to the lovely folks at Socket Supply.
I have exactly followed same steps. I am still not able to import socket modules in proxy mode. live reload mode is working fine. Why socket.ini file is empty on stackblitz?