npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mitts

v0.3.1

Published

Toolkit for server side rendering Mithril applications and handling of dynamic imported modules

Downloads

13

Readme

Mitts

Helpful tools to quickly add server side rendering and dynamically imported components into a Mithril application.

Plugins

There are 2 plugins that are provided for ensuring a proper management of loaded component modules, and bundles on the server.

Webpack

// webpack.config.js
import { LoadablePlugin } from "mitts/webpack";

export default {
  plugins: [
    new LoadablePlugin({
      filename: "./build/mitts.json"
    })
  ]
};

Babel

// server.js
require("mithril/test-utils/browserMock")(global); // required to ensure mithril can be used on the server

import { LoadablePlugin } from "mitts/webpack";

// adapt as required, the options provided assume your server to be a project root dir and your client src is a project root dir `src`
require("@babel/register")({
  ignore: [/\/build\//],
  presets: [["@babel/preset-env", { targets: { node: "current" } }]],
  plugins: [
    [
      "babel-plugin-module-resolver",
      {
        root: ["../"],
        alias: {
          "@": "./src"
        }
      }
    ],
    "@babel/syntax-dynamic-import",
    "babel-plugin-dynamic-import-node",

    // ...

    "mitts/babel"
  ]
});

// ... declare server below

Server Side Rendering

Loader

Builds atop the mithril-node-render library and provides a Loader interface which can be adapted to run with your specific Node.JS server as a routing middleware.

An example express middleware is provided by default

// server/index.js
import express from "express";
import { express as MittsLoader } from "mitts/loader";

// retrieve your clientside mithril entrypoint
import client from "../src/index";

// set the target output dir of your static build
const buildDir = path.resolve(__dirname, "../build");

// path to the entrypoint html template
const html = `${buildDir}/app.html`;

// path to the module manifest provided by mitts plugin
const manifest = `${buildDir}/mitts.json`;

// [Optional] handle sessions however you need for users
const createSession = (req, store) => {};

// express server
const app = express();

// create a loader for express
const mitts = MittsLoader({
  html,
  manifest,
  createSession,
  // [Optional] create an application store to hydrate components via redux
  createStore: client.store,
  routes: client.routes
});

// register the middleware
app.use(express.static(buildDir));
app.use(mitts.middleware());

But handling for your own server type can be added easily by implementing an adapter and creating a new Loader object providing your server adapter.

// server/index.js
import http from "http";
import Loader from "mitts/loader";

const adapter = (req, res) => ({
  request: req,
  response: res
});

const mitts = new Loader(adapter, {
  // same options as above MittsLoader
});

const server = http.createServer(mitts.middleware());

// ...

Dynamic Component Loading

Loadable

Implementation credit and big thanks to the wonderful React based library react-loadable for providing a quality solution to dynamic import and code splitting/loading. The documentation they provide will be mostly correct for this mithril adapatation.

This adapatation aims to provide a nice experience for loading mithril components dynamically using import(). There is a provided Loadable interface which handles loading in a component with proper lifecycle management.

import m from "mithril";
import Mitts from "mitts";

const Loading = {
  view(vnode) {
    const { error, retry, pastDelay } = vnode.attrs;
    if (props.error) {
      return m("div", ["Error! ", m("button", { onclick: retry }, "Retry")]);
    } else if (pastDelay) {
      return m("div", "Loading...");
    } else {
      return null;
    }
  }
};

const LoadableWidget = Mitts({
  loader: () => import("@/components/widget"),
  loading: Loading,
  delay: 300 // 0.3 seconds
});

m.route(
  { "/": { view: () => m(LoadableWidget) } },
  "/",
  document.getElementById("root")
);

Examples

For a working sample you can reference the latest version of the mithril starter app I have been maintaining over here mithril-redux-starter

WIP

This is highly experimental and unfinished. Everything mostly works, but there are no tests or guarantees of any kind at this time. The documentation is also lacking. If there are bugs, suggestions or improvements please feel free to open an issue and send a pull request.