-
Notifications
You must be signed in to change notification settings - Fork 1
SHA1 digest (Webpack)
In this example we're going to create an app that calculates SHA-1 digests of files, using a built-in function of Zig's standard library.
First, we'll create the basic skeleton:
mkdir sha1
cd sha1
npm init -y
npm install --save-dev react react-dom\
webpack webpack-cli webpack-dev-server css-loader style-loader html-webpack-plugin\
@babel/core @babel/preset-env @babel/preset-react babel-loader http-server\
zigar-loader
mkdir src zig
Create sha1.zig
:
const std = @import("std");
pub fn sha1(bytes: []const u8) [std.crypto.hash.Sha1.digest_length * 2]u8 {
var digest: [std.crypto.hash.Sha1.digest_length]u8 = undefined;
std.crypto.hash.Sha1.hash(bytes, &digest, .{});
return std.fmt.bytesToHex(digest, .lower);
}
Then App.jsx
:
import { useState, useCallback } from 'react';
import { sha1 } from '../zig/sha1.zig';
function App() {
const [ digest, setDigest ] = useState('-');
const onChange = useCallback(async (evt) => {
const [ file ] = evt.target.files;
if (file) {
const buffer = await file.arrayBuffer();
const { string } = sha1(buffer);
setDigest(string);
} else {
setDigest('-');
}
});
return (
<div className="App">
<input type="file" onChange={onChange} />
<h2>{digest}</h2>
</div>
);
}
export default App
Then index.js
:
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
And finally index.html
:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>WebPack + React + Zigar</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
We then create webpack.config.js
, identical to the one used in
the previous example:
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js',
},
plugins: [
new htmlWebpackPlugin({
template: 'src/index.html',
}),
],
devServer: {
port: 3030,
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ],
},
{
test: /\.zig$/,
exclude: /node_modules/,
use: 'zigar-loader',
},
],
},
};
Plus .babelrc
, which is also the same:
{
"presets": [
"@babel/preset-env",
[ "@babel/preset-react", { "runtime": "automatic" } ]
]
}
In package.json
we have the same three commands as previously:
"scripts": {
"dev": "webpack serve --mode development",
"build": "webpack --mode production",
"preview": "http-server ./dist"
},
We use the first to verify that our app works:
npm run dev
Just run the following commands:
npm run build
npm run preview
You should notice that the app runs faster now than in dev mode. zigar-loader by default sets
optimize
to ReleaseSmall
when building for production. That removes overhead from Zig's
runtime safety system.
This example is still relatively simple. All we're doing is calling a function. It accepts an uncomplicated argument and returns an uncomplicated value. In the next example, the function involved will take more complicated arguments and return something complicated as well.