Skip to content

Instantly share code, notes, and snippets.

@RoyalIcing
Last active March 9, 2022 04:23
Show Gist options
  • Save RoyalIcing/d9d2ca7ed6f056632696709a2ae3c413 to your computer and use it in GitHub Desktop.
Save RoyalIcing/d9d2ca7ed6f056632696709a2ae3c413 to your computer and use it in GitHub Desktop.
Mini modules
/**
* Pi to 8 decimal places
*/
export const pi = 3.14159265;
export const dateFormat = "YYYY/MM/DD";
export const isEnabled = true;
export const flavors = ["vanilla", "chocolate", "caramel", "raspberry"];
export const foo = null;
export const homeURL = new URL("https://example.org/");
export const aboutURL = new URL("/about", homeURL);
export const blogURL = new URL("/blog/", homeURL);
export const firstArticle = new URL("./first-article", blogURL);

Mini Modules (ES Modules Object Notation: ESMON)

Capabilities

  • calculate maths e.g. tax rates
  • talk to other APIs
  • render HTML
  • minify and bundle assets
  • render SVGs
  • parse and process CSVs

Features

  • const
  • number
  • string
  • arrays
  • UInt8Array
  • sets
  • maps
  • symbols
  • generator functions
  • URLs
  • fetch
  • Request
  • Response

Why

  • JSON doesn't allow richer data types: dates, colors, paths, sets,
  • JSON doesn't allow comments
  • JSON imports are awkward
  • JSON is awkward to write manually
  • ES Modules imports are fantastic
  • ES Modules allows richer data types
  • ES Modules allows comments
  • Leverage existing modules
  • Lever tooling such as TypeScript and JSDoc
  • Great for design tokens
  • Leverage existing tooling for minification, etc
  • Works in modern browsers
  • Take advantage of HTTP caching at the edge

What

  • Can export members with a name
  • Exports are JSON objects, must strictly be JSON syntax (double quotes)
  • Only const is supported, no variables
  • Must have semicolons at end of statements
  • Can use JSDoc as annotations
  • Can do dynamic imports: import("some url")
  • Can import CSS?
/**
 * Pi to 8 decimal places
*/
export const pi = 3.14159265;

export const dateFormat = "YYYY/MM/DD";

export const isEnabled = true;

export const flavors = ["vanilla", "chocolate", "caramel", "raspberry"];

export const foo = null;

Supported platforms

  • Swift
  • Cloudflare Workers with caching of imported modules
  • Go
  • Elixir
  • Python

Swift

let data = 

let module = try? ESModule.parse(data)
module.exports.names // ["pi", "dateFormat", "isEnabled", "flavors", "foo"]
module["pi"] // 3.14159265
module.pi // Dynamic member lookup

ESModule.loadAndEvaluate(URL("some url"))
  .sink { exports in  }

Cloudflare Worker

const data = await importData(someURL)

Future capabilities

  • Set, Map
  • Import from URL
  • Export from other modules
  • Maybe functions or generator functions
  • Can pass custom functions that can be imported and used
export const imageURL = new URL("./image.png", import.meta.url)
import { Set } from "es2015";

export const flavors = new Set(["vanilla", "chocolate", "caramel", "raspberry"]);

import someDataset from "https://cooldatasets.org/foo.json";

export * from "otherModule";

export function* sequence() {
  yield 1;
  yield 2;
  yield 3;
  yield 5;
  yield* otherGenerator;
}

URLs

export const home = new URL('/');
export const dashboard = new URL('/dashboard');
export const account = new URL('/account');

Design tokens

import { rgb } from 'css-values';

export const primaryColor = rgb(45, 91, 12);
export const secondaryColor = rgb(12, 34, 56);

/some-design-token.mjs.css

:root {
  --primaryColor: rgb(45, 91, 12);
  --secondaryColor: rgb(12, 34, 56);
}

Publish a library of assets

export { default as plus } from "image/svg+xml/8f43b18ca…";
export { default as profile } from "image/svg+xml/372db66…";
export { default as edit } from "image/svg+xml/1aeb067…";
  • Show preview inline of the images with VSCode extension

Take input

new URL(import.meta.url).searchParams.get('color');

Calculations

const input = new URL(import.meta.url).searchParams;
const income = searchParams.get('income');

export const gst = income * 0.10;
export const incomeTax = income * 0.37;

Perform a SHA256 hash of input

export default crypto.subtle.digest('SHA-256', import.meta.params['content']);

Unit tests

export 

Swift Combine API

let decoder = JSONDecoder()

dataProvider
  .tryMap { parseModule($0) }
  .flatMap { module in
    MergeMany([
      Just(module["profile"])
        .decode(type: Profile.self, using: decoder),
      Just(module["preferences"])
        .decode(type: Preferences.self, using: decoder),
      Just(module["pi"])
        .decode(type: Float.self, using: decoder)
    ])
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment