Omatsuri – your everyday app
Tags: webpack, react
Published: 2020-08-22 15:21:15

This week I've release [Omatsuri](https://omatsuri.app/) – [open source](https://github.com/rtivital/omatsuri) browser only application with 9 frontend and design focused tools. In this post I'll go through some technical challenges that I've faced during development.

![Omatsuri main](https://dev-to-uploads.s3.amazonaws.com/i/wjprqza1pr7v3vohdrdc.png)

## About application
Omatsuri translates to «festival» from Japanese (お祭り) and includes a festival of 9 tools:

* CSS Triangle Generator
* Color Shades Generator
* Curved Page Dividers Generator
* SVG compressor
* SVG to JSX converter
* Base64 encoder
* Realistic Fake Data Generator
* HTML/CSS Symbols Collection
* Lorem/Samuel/Poke Ipsum Generator

## Some technical details

My initial purpose was to make Omatsuri a browser only application. This approach allows to reduce costs for hosting server that does heavy jobs, like svg compression, prettier transformations and other heavy things.

### SVG compression

Did you know that there is actually only one good library for svg compression ([svgo](https://github.com/svg/svgo)) written in JavaScript? And it does not have browser support, only node.js. I found it very strange as svg compression is based entirely on string parsing and does not include any node specific logic. 

So my first task was to migrate svgo to browser. It was pretty easy, since all core logic did not require any modifications. And now you can use [svgo-browser](https://github.com/rtivital/svgo-browser) library in your projects if you ever need svg compression in browser.

### Web workers

As I said before, some task are very heavy and can block your browser for several seconds. To fix this, we can put them in separate thread using web workers so that they run in background without blocking the main thread. 

I was surprised how easy it is to work with web workers in webpack. All you need is [worker-loader](https://github.com/webpack-contrib/worker-loader) that will handle all worker bundling for you.

Here is an [example](https://github.com/rtivital/omatsuri/blob/master/src/workers/svg-to-jsx.worker.js) of web worker usage for transforming svg to jsx with prettier and svg compression:
```js
// svg-to-jsx.worker.js
  
import prettier from 'prettier/standalone';
import prettierBabel from 'prettier/parser-babel';
import svg2jsx from 'svg-to-jsx';
import optimize from 'svgo-browser/lib/optimize';

function generateComponent(svg) {
  return `import React from 'react';\n\nexport default function SvgComponent() { return ${svg} }`;
}

onmessage = (event) => {
  const { payload } = event.data;

  optimize(event.data.content)
    .then((content) => svg2jsx(content))
    .then((svg) =>
      prettier.format(generateComponent(svg), { parser: 'babel', plugins: [prettierBabel] })
    )
    .then((code) => postMessage({ error: null, payload, code }))
    .catch((error) => postMessage({ error, payload, content: null }));
};
```

```js
// react component

import React, { useState, useLayoutEffect } from 'react';
import Svg2jsxWorker from '../../workers/svg-to-jsx.worker';

const svg2jsx = new Svg2jsxWorker();

export default function SvgToJsx() {
  const [result, setResult] = useState({ loading: false, error: null, content: null });

  const handleMessage = (event) => {
    setResult({ loading: false, error: event.data.error, content: event.data.code });
  };

  const postMessage = (text) => svg2jsx.postMessage({ content: text });

  useLayoutEffect(() => {
    svg2jsx.addEventListener('message', handleMessage);
    return () => svg2jsx.removeEventListener('message', handleMessage);
  }, []);

  return (/* ... */);
}
```

### SPA prerendering
As app does not have any server logic it can be fully prerendered. To make that happen there is a [webpack pugin](https://github.com/chrisvfritz/prerender-spa-plugin) that automatically prerenders all app routes on production builds. You can view my configuration for this plugin [here](https://github.com/rtivital/omatsuri/blob/master/webpack.config.js#L169).

## Contributing
If you've been waiting to contribute to open source project, now is your chance! There are lots of features that can be added to the app, here is some of them:

* Offline support with service workers
* Dark theme support (automatically detected from user os)
* New application – e.g. gradient generator

If you decide to contribute don't forget to add yourself to [hall of fame](https://omatsuri.app/about) on the About page.

## What do you think?

Do you like this project? Will you use it? Don't be shy, comment about anything, I'll be happy to receive any feedback.