MiuJS: a framework for building HTML applications packed with the minimum necessary functionality
Tags: node, javascript, typescript, opensource
Published: 2022-04-27 02:28:42


# MiuJS in a minute
[Github](https://github.com/tknf/miujs)

MiuJS is a full-stack framework running on Node.js that includes utilities necessary for developing small websites.
It does not rely on specific front-end libraries such as React or Vue.js, yet packs as many features as possible that are necessary for development.

## Features
- Runs server-side instead of SSG
- Built-in controller to handle non-GET requests
- HTML-first development using Nunjucks templates, pre-built templates to avoid using `fs` in production
- Scoped CSS feature, no mass production of CSS files
- No external library dependencies for client-side JavaScript bundles (initial 5kb or less in production builds!)
- Built-in dev server with live reload and built-in production server with connect

## Recommended for
- Creating web pages that do not want to overload the client-side
- Lightweight websites that are not platform specific
- Corporate sites with templates + small amount of POST actions, etc.

## Incompatibility
- Large scale website and web application development
- SPA development
- Blogs and documentation sites with large amounts of local Markdown

Although the above is a narrow demand, I believe that it can be useful for those who fell that existing frameworks are over-specified when they want to speed up the construction of a small site.
If you are interested, please continue reading.

---

As of 2022, there are countless libraries and mods named "web frameworks" regardless of languages.
When developing the actual core software of a product, large frameworks such as Ruby on Rails and Django may be used.

However, if you are building a website just to introduce that product, for example, these frameworks feel over-engineered.
There are various options to solve this, but the main issues I felt were:
- I love React used by Next.js, Remix, etc., but the bundle size is a concern for creating a small site.
- Sveltekit made by Svelte as well as 1.
- CMSs such as Wordpress are similarly over-specified and have too many files to begin with.
- There is an option to use a static site generator (e.g. Hugo), but it needs to be built every time data is updated.

In other words, what I wanted was:
- Requires few or no development time
- Small in size
- Runs on the server-side

## Considering the existing options
First, I narrowed down our choices of frameworks that could satisfy the above.

I tried various small frameworks such as [Sinatra](http://sinatrarb.com/) and [Gin](https://gin-gonic.com/), but I felt that most of them are based on the assumption of customization to the extent that they extend the HTTP router.

The goal of this project is to develop a small website. I wanted a utility that specializes in front-end rather than extensibility.

Therefore, **I decided to create our own framework**.

## Create a framework

### Requirements
- Ability to use template engines with low learning costs
- Support for server-side rendering
- Not a static site generator
- Built-in HTTP server, capable of handing POST requests

### Additional
- JavaScript bundling
- Can use scoped CSS, or CSS modules, etc.
- Can run without JavaScript
- Live reload during development
- No `fs` in server runtime (want to run with Vercel, Netlify, etc.)

I have developed a web framework that can satisfy these requirements as much as possible.

# MiuJS
The result is MiuJS, which meets all of the above requirements.

[MiuJS Website](https://www.miujs.com)

## From project creation to build
As detailed use is described on our website, I will only provide a simplified introduction.

### Create project
It can be created from npx by the `create-miu` package.
```bash
npx create-miu@latest my-project
```

At this stage, the deployment targets can be selected from built-in server, Netlify, and Vercel, each with templates for JavaScript and TypeScript.

### Development
Built-in dev server with live reload.
```bash
yarn dev
# or 
npm run dev
```

### Request workflow
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxy7bow9c42hfgdhia55.jpg)
MiuJS server requests are processed in the following order:
- Request handlers created for each platform, such as `createVercelRequestHandler`
- Function calls corresponding to request methods such as `get`, `post` described in files under `src/routes`
- `createServerRequest` function in `src/entry-server.js`

Basically, each Route file plays the role of a controller in MVC, and detailed processing can be described here.

### Route files
Under `src/routes`, Next.js-like file system routing in employed, with `src/routes/index.js` automatically routed to `/`, `src/routes/about.js` to `/about`, and so on.
In addition, each Route file can be implemented by exporting a function with an HTTP method name.

```ts
import type { RouteAction } from "miujs/node";
import { render, json } from "miujs/node";

// http://localhost:3000/posts#GET
export const get: RouteAction = ({ createContent }) = > {
  return render(createContent({ layout: "default" }), { status: 200 });
};

// http://localhost:3000/posts#POST
export const post: RouteAction = ({ query, params }) => {
  console.log(`query: `, query);
  console.log(`params: `, params);

  return json({}, { status: 200 });
};
```

###Templating
The `createContent` function passed from `RouteAction` has a built-in mechanism for using template files from cached post-build Nunjucks templates without using `fs`, and this function can be used to generate html rendered Nunjucks from the specified directory.

```ts
import type { RouteAction } from "miujs/node";
import { render } from "miujs/node";

export const get: RouteAction = async ({ createContent, params }) => {
  const data = await fetchSource({ handle: params!.handle }).catch(() => null);
  if (!data) {
    return render(createContent({ layout: "404" }), { status: 404 });
  }
  return render(
    createContent({
      layout: "default", // Templates that are entry points that reference files under src/layouts
      sections: [ // Section name and scope variables that reference to files under src/sections
        { name: "header", settings: { name: "Akiyoshi" } }
      ],
      data // Global data
    }),
    { status: 200, headers: { "Cache-Control": "public, max-age=900" } }
  );
};
```
```html
<!-- layouts/default.njk -->
<!DOCTYPE html>
<html>
  <head>
    <title>{{ data.title }}</title>
  </head>
  <body>
    The contents of the `sections` are compiled and inserted in the following comment fragment.
    <!-- content -->
  </body>
</html>
```
```html
<!-- sections/header.njk -->
<header>
  The `settings` scope provides access to section-specific scope variables.
</header>
```

## Scoped CSS
Scoped CSS can be applied to content in `src/partials` and `src/sections` with markup like Vue.js or Svelte.
```html
<style scoped>
  .price:scope {
    display: flex;
    align-items: center;
  }
</style>

<template>
  <div class="price"><small>$</small>{{ price }}</div>
</template>
```

### Build
Build is also completed with a single command.
```bash
yarn build
# or 
npm run build
```
Build for each server target (node, netlify, vercel) based on the settings described in miu.config.js.

### Deploy
The built-in server works only with Node.js, so it can be deployed to any environment where the Node.js runtime is available.
```bash
yarn serve
# or 
npm run serve
```
Deploying to services that use serverless functions such as Vercel or Netlify requires some tricky configuration, but the templates in the `create-miu` package include configuration files, so you can deploy without configuration, except in cases where special handling is required.

---

## Future implementations
This framework is intended to meet the niche demand of developing "small websites that need a server-side but do not want to be as over-specified as existing full-stack frameworks.

In implementing the necessary functionality, most of the code, such as session storage, is implemented in time by copying parts of it from frameworks I admire, such as Remix. Since MiuJS is not intended to be used for developing large-scale applications, the usage scenario may be limited to begin with.

---

If anyone matches this narrow demand, please use it if you like.

Thanks for reading.

[MiuJS Github](https://github.com/tknf/miujs)
[MiuJS website](https://www.miujs.com)

I plan to rewrite this area so that it can be used more simply in a PHP-like manner.