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

@engineerapart/nextscript

v2.0.2

Published

A custom Next script loader for Next.js. Replaces the built-in NextScript component and allows you to apply polyfill pre-loading and business logic.

Downloads

170

Readme

npm (scoped) npm David David

Version Notice

  • For Next <= v6, please use nextscript@~0.0.8
  • For Next >= 7, please use nextscript@^1.0.0
  • For Next 8 & 9, please use nextscript@^2.0.0
  • For Next >= 9.0.3 and above, if using experimental module support for modern browsers, this package is not needed (see: 9.0.3 release notes). This is due to the fact that all polyfills offered by polyfill.io are already supported by modern browsers.

In each new version of Next there are incompatible changes with the prior versions. This component was always a stepping stone to a more permanent solution, which the Next.js team are now working on in the Module/Nomodule RFC and the corresponding initial merge request that went into Next.js 9.0.3.

Once that feature is enabled by default, this component will be deprecated.

NextScript 💠

This project is not-so-cleverly named after the export of the same name in the amazing Next.js framework.

This component provides a flexible, business-rule oriented approach to loading the scripts in your Next project. By default, Next loads all scripts on page load, which may or may not be desirable behavior. Some of the reasons you may want to avoid that are:

  • Performance: Only load these scripts when needed, or wait until the page load event (for things like _error, if you know it is not needed immediately)
  • Preloading: It is not uncommon to need to run a script - or load a script from URL - before allowing your Next app to load.
  • Polyfill preloading: This is the most common application of the previous point. Next bundles some polyfills, but only the ones NEXT requires - not the ones YOU require. If you require IntersectionObserver for example, it is on you to load it yourself. Since that is a HUGE polyfill (7kb minzipped!), you do not want to deliver it to all clients - only the ones that absolutely require it (IE <= 11, Safari ALL).

This NextScript component allows you to accomplish these goals and more in a flexible, minimal way. This component itself compiles down to 2.3kb minzipped (although it is only ever executed on the server!) and has a simple API.

Built originally out of the NextScript component itself, all of that functionality is supported, in addition to the features above.

Motivation

Take a look at this issue on the Next.js repository. This is a common problem and sometimes it is not clear how to resolve it. This component gives you a seamless, drop-in way to handle polyfills that is performant and efficient, only delivering what is needed to each browser.

This component also retains and expands Next's support for nonces on script elements: Simply assign the nonce parameter and every script URL and every inline script will automatically get the nonce. This can be overridden on a per-script basis (can't imagine why you'd need to - but you can!).

Opt-In

This component's functionality is opt-in. You can configure the component to behave exactly as NextScript itself does, or you can optionally enable the above features. Simply rendering <NextScript /> will produce identical behavior to the component found in Next.

Getting started

Install from npm:

npm i @engineerapart/nextscript

# or

yarn add @engineerapart/nextscript

You will find an entry in NPM under nextscript. This is our placeholder to avoid confusion with potential package collisions and is not the published package.

Examples

Duplicate Next.js

The only difference between this example and the default Next _document is where NextScript is imported from:

import { NextScript } from '@engineerapart/nextscript';
import Document, { Head, Main } from 'next/document';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    return (
      <html>
        <Head>
          <style>{`body { margin: 0 } /* custom! */`}</style>
        </Head>
        <body className="custom_class">
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

Preload polyfills

The canonical example: How to preload polyfills, including polyfills not defined by this project.

import { NextScript, FeaturePolyfills } from '@engineerapart/nextscript';
import Document, { Head, Main } from 'next/document';

const features = [
  FeaturePolyfills.FETCH,
  FeaturePolyfills.CUSTOMEVENT,
  {
    test: `('entries' in Array.prototype)`,
    feature: 'Array.prototype.entries',
  },
];

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    return (
      <html>
        <Head></Head>
        <body className="custom_class">
          <Main />
          <NextScript features={features} />
        </body>
      </html>
    );
  }
}

Polyfill Service

Current this component points to the Polyfill.io service, which serves ~150 million polyfill requests per DAY (4.5 billion/month!). However, eventually this project will also support pointing to your own self-hosted polyfill service, provided that it adheres to the Polyfill.io API (instructions for self-hosting the Polyfill.io service can be found in their repository.)

How it works

The default NextScript implementation captures the scripts generated by the Next build process and immediately renders them to <script> tags in its render() function.

This component takes a different approach: It collects the same script information from the build that the original Next component does, but instead of immediately rendering them, it inserts the script information into a preloader script. This provides the opportunity to:

  1. Load something else first
  2. Load something else after
  3. Load them on command

After you've configured the component, it will execute your configurations inside the preloader, and then execute the Next scripts. If you don't configure the component, it does exactly the same thing that the original Next component does!

API

You can configure the component to behave exactly as NextScript itself does, or you can optionally enable the above features. Simply rendering <NextScript /> will produce identical behavior to the component found in Next.

NextScript Properties

If you are using Typescript, TS will automatically detect the typings, included with this project, and provide intellisense if you are using a TS-aware editor. These properties are also documented here.

All properties are optional. Rendering this component as <NextScript /> simply duplicates exactly what the NextScript component included with Next does.

| Prop | Type | Default | Description | |--- |--- |--- |--- | | nonce | string | undefined | Nonce to apply to all scripts loaded via this component | | allowUserMonitoring | boolean | true | Sends the rum URL parameter to the Polyfill service | | minify | boolean | true | Instructs the Polyfill service to send minified polyfills | | preLoadScripts | ScriptEntry[] | [] | Scripts to load before the Next scripts | | postLoadScripts | ScriptEntry[] | [] | Scripts to load after the Next scripts | | useFeatureDetection | boolean | true | Detect features in user's browser instead of letting the Polyfill service use the UA | | features | PolyfillDefinition[] | [] | The list of required features, selected from the FeaturePolyfills enum, or objects you defined yourself if not included in this project (feel free to PR!) | | preloadPolyfills | boolean | true | Flag to indicate whether the component will preload polyfills. If false, features and useFeatureDetection will be ignored. |

ScriptEntry Interface

Defined in Typescript, this interface consists of the following fields:

| Field | Type | Default | Description | |--- |--- |--- |--- | | src | string | [required] | The script source to load. For now, only URL sources are supported. | | nonce | string | undefined | The nonce to use for this script. If not supplied, the NextScript nonce will be used, or undefined if none are provided. | | id | string | undefined | An ID to identify this script node. | | async | boolean | false | Whether the async flag should be applied to this script node. |

If you need to load arbitrary scripts, you can mount a script node before this element in your Next project. It's on our list to support, so it is coming!

PolyfillDefinition Interface

This project supplies a small collection of default polyfill definitions to get you started, but does not currently support all 194 polyfills supported by Polyfill.io! Thus, it was important to be able to allow you to define arbitrary polyfills. This is accomplished by providing an array of PolyfillDefinition objects to the features prop of NextScript.

Defined in Typescript, this interface consists of the following fields:

| Field | Type | Default | Description | |--- |--- |--- |--- | | test | string | null | The test, as a string, the browser must run. For example '('fetch' in window)'. This should not be null unless you are providing a Polyfill.io category (default, es6); however these are already configured in this project. If null, no test will be made, and the feature value injected directly into the feature list sent to the Polyfill service | | feature | string | [required] | The Feature ID known by the Polyfill service. A full list can be found at Polyfill.io |

TODO

  1. Support a self-hosted Polyfill service
  2. Add all known polyfills to the FeaturePolyfills collection
  3. Support inline scripts to be injected in the preloader

Contributing

PRs are welcome. Make sure to read our contribution guidelines and code of conduct.

License

MIT