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

samd

v0.1.1

Published

A tiny, static AMD API implementation

Downloads

414

Readme

SAMD

A tiny, static AMD API implementation that allows including AMD modules in regular script tags.

SAMD is currently experimental/awaiting feedback.

  • 1.3 KB minified & gzipped
  • No dynamic loading; all scripts are loaded by the browser
  • Works in every browser alive
  • Supports <script defer> & <script async>
  • Allows progressive optimizations without impact on development

When combined with TypeScript, SAMD may be used as an alternative to traditional JS bundling (e.g. webpack or rollup). This is the main use case for SAMD, as described below. An example project can be inspected under /example.

Try the example online

Usage

SAMD enables inclusion of UMD/AMD modules in regular script tags:

<script src="https://unpkg.com/samd@0/dist/samd.js" crossorigin></script>
<script async src="https://unpkg.com/moment@2/moment.js" crossorigin></script>
<script async src="https://unpkg.com/lodash@4/lodash.js" crossorigin></script>
<!-- more UMD/AMD dependencies... -->
<script>
  require(['moment', 'lodash'], function (moment, _) {
    // use dependencies
  });
</script>

No additional script loading or special markup is required.

Usage with TypeScript

Given a regular ES6/TypeScript project, with NPM dependencies and TypeScript configuration in place, TypeScript is able to produce one-file AMD builds with wide browser compatibility out-of-the-box:

tsc --outFile scripts/dist/app.js --target ES5 --module AMD

This generates an ES5 AMD bundle of the project, not including NPM modules but explicitly referencing NPM imports as AMD dependencies. Note that TypeScript is able to handle JS/JSX projects by using --allowJs.

This application bundle can be used directly in a website by including SAMD and UMD builds of the application dependencies from e.g. unpkg:

<div id="root"></div>
<script src="https://unpkg.com/samd@0/dist/samd.js" crossorigin></script>
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<!-- more UMD/AMD dependencies... -->
<script src="scripts/dist/app.js"></script>
<script>
  // assuming the entry point is index.ts/index.js and it exports an init() function:
  require(["scripts/index"], function (index) {
    index.init();
  });
</script>

SAMD infers module IDs from script src attributes, allowing the original NPM imports to be resolved from the application bundle.

This setup is sufficient for development:

  • It works in modern browsers.
  • Application code is based on modern JS/TypeScript with ES6 imports.
  • TypeScript's watch mode may be used to continuously build the application bundle.
  • Source maps are supported.

Note that CommonJS-only dependencies cannot be used. Dependencies must provide UMD/AMD builds (most popular libraries do, though).

Production

In production environments, the respective production/minified builds of dependencies should be used. Polyfills may be included using e.g. polyfill.io. For further optimization, the application bundle may be minified through terser.

<script src="https://polyfill.io/v3/polyfill.min.js?features=fetch,Promise" crossorigin></script>
<script src="https://unpkg.com/samd@0/dist/samd.min.js" crossorigin></script>
<script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script>
<script src="scripts/dist/app.min.js"></script>

It is reasonable to serve separate HTML documents for development and production environments. Employ templating techniques at build-time or on server-side as needed.

Because of unpkg's CDN, this setup is fairly performant when using popular libraries. It is also widely compatible regarding browser support, depending on the chosen TypeScript target.

Self-hosting

If vendor dependencies need to be self-hosted, it is recommended to copy the respective builds from node_modules to e.g. scripts/vendor. Compiling the set of polyfills is out of scope for this document.

<script src="scripts/vendor/polyfills.min.js"></script>
<script src="scripts/vendor/samd.min.js"></script>
<script src="scripts/vendor/react.production.min.js"></script>
<script src="scripts/vendor/react-dom.production.min.js"></script>
<script src="scripts/dist/app.min.js"></script>

It is encouraged to automate copying and other build steps through one or more shell scripts (see build.sh in the example project). Remember that SAMD infers AMD module IDs from script filenames (after last /, before first ., while still allowing @org/package).

When served with HTTP/2, this setup is sufficiently performant for a wide range of websites.

Bundling

When having many vendor dependencies or when HTTP/2 is unavailable, all scripts may be concatenated into a single file (optionally running it through terser again).

<script src="scripts/bundle.min.js"></script>

However, because UMD modules usually define anonymous modules, SAMD is not able to identify individual module IDs of a bundle without user input, so bundling cannot work by simple concatenation.

For this use case, SAMD ships with a CLI to infer and inject module IDs into given UMD module files (see build.sh in the example project). This CLI can also be used for concatenation.

samd -o scripts/dist/bundle.js \
  scripts/vendor/polyfills.min.js \
  scripts/vendor/samd.min.js \
  scripts/vendor/react.production.min.js \
  scripts/vendor/react-dom.production.min.js \
  scripts/dist/app.min.js
terser scripts/dist/bundle.js -o scripts.dist.bundle.js

Note that this only has to be done in bundling scenarios.

Libraries

SAMD is only useful for applications. Packages for the web should be distributed as UMD for maximum compatibility.

Conclusion

The presented TypeScript/SAMD-based workflow has useful properties and is fully compatible with the web platform.

  • Works with modern ES6/TypeScript projects, with little implications.
  • Wide browser compatibility (even Internet Explorer)
  • Loading of scripts is handled and optimized by the browser.
  • Production optimizations are progressive and don't impact development.
  • Bundling is (almost) reduced to simple concatenation.
  • Bundling does not require configuration; simple shell scripts are sufficient and provide additional flexibility.

At any point of the workflow, it is advised to measure page load performance and user experience, and only proceed optimizing if needed.

Limitations

  • Dependencies must provide AMD/UMD builds.
  • Multiple versions of dependencies are not supported.
  • CommonJS is not supported.
  • No tree-shaking.
  • Relative module dependencies are not supported (yet).