Skip to content

Hello world (Vite)

Chung Leong edited this page Apr 25, 2024 · 4 revisions

In this example we're going to create a very simple web app that outputs "Hello world!" to the console through Zig. It demonstrates the basics of working with rollup-plugin-zigar.

Create the app

First, we'll create a boilerplate app. In a terminal window, run the following command:

npm create vite@latest

Enter hello as name, and select React and JavaScript + SWC:

Need to install the following packages:
create-vite@5.2.2
Ok to proceed? (y) y
✔ Project name: … hello
✔ Select a framework: › React
✔ Select a variant: › JavaScript + SWC

Once the project is created, go into its directory and install the necessary files:

cd hello
npm install

Next, install the Zigar plugin:

npm install --save-dev rollup-plugin-zigar

Create a sub-directory for zig code:

mkdir zig

And add hello.zig:

const std = @import("std");

pub fn hello() void {
    std.debug.print("Hello world!", .{});
}

In a text editor, open vite.config.js and insert the plugin:

import react from '@vitejs/plugin-react-swc';
import zigar from 'rollup-plugin-zigar';  // <---
import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [ react(), zigar() ],  // <---
})

Add an import statement to App.jsx and change the button handle so that it calls hello() every time the button is clicked:

import { useState } from 'react'
import { hello } from '../zig/hello.zig' // <---
import './App.css'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'

function App() {
  const [count, setCount] = useState(0)

  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => hello()}>{/* <--- */}
          Say hello
        </button>
        <p>
          Edit <code>src/App.jsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  )
}

export default App

Finally, start Vite in dev mode:

npm run dev
  VITE v5.1.6  ready in 329 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

Open the link shown onscreen in Chrome. Press Ctrl-Shift-I to open Chrome's development console. The text message should appear there every time you click the button.

Now, let us test Vite's Hot Module Replacement feature. In the development console, change the display level to Verbose:

Chrome dev console

Switch to your text editor and change the message in hello.zig. When you return to Chrome, you should see a notification in the development console:

Chrome dev console

Creating production build

Run the usual command to build the app:

npm run build

Most likely you will encounter the following error:

Error: [vite:esbuild-transpile] Transform failed with 1 error:
assets/index-!~{001}~.js:3130:0: ERROR: Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides)

As of April 2024, support for top-level await is still not wide-spread enough for it be safely assumed. To work around this issue, we need to change the settings for rollup-plugin-zigar:

export default defineConfig({
  plugins: [react(), zigar({ topLevelAwait: false })],
})

Run the build command again. It will succeed this time. With top-level await switched off, our hello function can potentially be asynchronous momentarily (in the breif moment it takes to compile the WASM bytecodes). It's not a problem in this example, since we don't care about the return value.

FYI: According to caniuse.com, support for top-level await is available starting from Chrome 89, Edge 89, Firefox 89, and Safari 15.

To verify that the production code does in fact work, start Vite in preview mode:

npm run preview

And check the app once more in Chrome.

Conclusion

You have just learned how you can easily make use of WebAssembly in your Vite project with the help of Zig and Zigar. The app we built in this example doesn't do anything. Our code will do something more useful in the next sample.


SHA1 digest example