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

lazy-init

v5.0.0

Published

Lazily initialize values by deferring their creation until first use, resulting in better performance.

Downloads

28

Readme

lazy-init

Lazily initialize values by deferring their creation until first use, resulting in better performance.

Now also bringing block expressions to JavaScript/TypeScript.

Index

Installation

This library requires your code is transpilied with any of the following:

If you require a version of next/swc unsupported by the plugin and it is listed here, create an issue requesting support.

Next.js

| Version | Plugin | | :---------------------- | :-------------------------: | | >= v13.4.20-canary.32 | @lazy-init/plugin-swc-v83 | | >= v13.4.10-canary.1 | @lazy-init/plugin-swc-v81 |

# using npm
npm install lazy-init && npm install --save-dev @lazy-init/plugin-swc-{{version}}
# using pnpm
pnpm add lazy-init && pnpm add -D @lazy-init/plugin-swc-{{version}}

Add the following to your next config file:

next.config.js

module.exports = {
   experimental: {
      swcPlugins: [
         // empty config object `{}` is required.
         [require.resolve('@lazy-init/plugin-swc-{{version}}'), {}],
      ],
   },
}

next.config.mjs (ESM)

import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)

export default {
   experimental: {
      swcPlugins: [
         // empty config object `{}` is required.
         [require.resolve('@lazy-init/plugin-swc-{{version}}'), {}],
      ],
   },
}

SWC - @swc/core

| Version | Supported | | :---------- | :-------------------------: | | >= 1.3.81 | @lazy-init/plugin-swc-v83 | | >= 1.3.68 | @lazy-init/plugin-swc-v81 |

# using npm
npm install lazy-init && npm install --save-dev @lazy-init/plugin-swc-{{version}} 
# using pnpm
pnpm add lazy-init && pnpm add -D @lazy-init/plugin-swc-{{version}}

The empty config object {} is required.

// .swcrc
{
   "jsc": {
      "experimental": {
         "plugins": [
            ["@lazy-init/plugin-swc-{{version}}", {}]
         ]
      }
   }
}

esbuild

| Version | Supported | | :------------------- | :-------------------------: | | 0.18.x \|\| 0.19.x | @lazy-init/esbuild-plugin |

# using npm
npm install lazy-init && npm install --save-dev @lazy-init/esbuild-plugin
# using pnpm
pnpm add lazy-init && pnpm add -D @lazy-init/esbuild-plugin

The include and exclude properties are glob arrays which follow the same behaviour as include and exclude in Typescripts tsconfig.json.

These options are not required. However, providing either will improve performance.

By default, imports from node_modules will be skipped by this plugin unless excludeNodeModules is set to false.

// your build file
const { lazyInitPlugin } = require('@lazy-init/esbuild-plugin')
const esbuild = require('esbuild')

esbuild.build({
   // ... other options
   plugins: [
      // If you are using plugins that transform paths, place them first.
      lazyInitPlugin({
         include: ['src'],
         exclude: ['src/**/*.test.ts'],
         excludeNodeModules: true, // default
      }),
   ],
})

tsup

tsup uses esbuild internally, therefore everything documented in the esbuild section applies here. The only difference is a slight change in the configuration.

| Version | Supported | | :--------- | :-------------------------: | | >= 7.x.x | @lazy-init/esbuild-plugin |

Note: just copy the include and exclude arrays from your tsconfig.json.

// tsup.config.ts
import { lazyInitPlugin } from '@lazy-init/esbuild-plugin'
import { defineConfig } from 'tsup'

export default defineConfig({
   // ... other options
   esbuildPlugins: [
      // If you are using plugins that transform paths, place them first.
      lazyInitPlugin({
         include: ['src'],
         exclude: ['src/**/*.test.ts'],
         excludeNodeModules: true, // default
      }),
   ],
})

eslint

This step is only necessary if you are planning on using the lz.async method and have @typescript-eslint with rules that require type checking.

# using npm
npm install --save-dev eslint-plugin-lazy-init 
# using pnpm
pnpm add -D eslint-plugin-lazy-init
// .eslintrc.js
module.exports = {
  extends: {
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
    // must come after
    'plugin:lazy-init/recommended'
  }
}

Basic Usage

For more in-depth examples, see the per method documentation.

import { lz, lzc } from 'lazy-init' // ESM
const { lz, lzc } = require('lazy-init') // Common JS

// call `lz` for non-primitive values
lz({ foo: 1 })
lz([1, 2, 3])
lz(new Map([['key', 'value']]))

// call `lz.fn` for sync functions
lz.fn(() => {})

// call `lz.async` for async functions
lz.async(async () => {})

// call `lzc` to cache by default
const first = lzc({ a: 'foo' })
const second = lzc({ a: 'foo' })

console.log(first === second) // true

Methods

Click the method to see its documentation:

Caching

Caching results in only a single value ever being created for the given value structure. This can improve performance and reduce memory usage.

Caching can be enabled by setting the cache property to true on a options object or by using the lzc method where caching is enabled by default.

// using `lz`
lz({}) // not cached
lz({}, { cache: true }) // cached

// using `lzc`
lzc({}) // cached
lzc({}, { cache: false }) // not cached

When caching is enabled, the value will also be frozen unless you explicitly say otherwise. This is because caching an object that is not frozen is dangerous.

The object may mistakenly be mutated by the user, yet other recipients of this cached object do not expect it to change.

// using `lz`
lz({}) // N/A
lz({}, { cache: true, freeze: false }) // cached
lz({}, { cache: true }) // cached & frozen

// using `lzc`
lzc({}) // cached & frozen
lzc({}, { freeze: false }) // cached
lzc({}, { cache: false }) // N/A

Referentially comparing cached and non-cached values:

// `cfoo` and `cbar` share the same structure and are both
// cached, therefore they are the same object.
const cfoo = lzc({ a: 1 })
const cbar = lzc({ a: 1 })
cfoo === cbar // true
// `cfoo` and `buzz` share the same structure, however, `buzz`
//  is not cached, therefore they are different objects.
const buzz = lzc({ a: 1 }, { cache: false })
cfoo === buzz // false
// `cfoo` and `cdiff` are cached, however, they do not share the
// same structure and are therefore different objects.
const cdiff = lzc({ a: 5 })
cfoo === cdiff // false

There are separate caches for frozen and non-frozen objects. Therefore, frozen and non-frozen objects with the same structure will not be the same object.

const cfoo = lzc({ a: 1 })
const cbar = lzc({ a: 1 }, { freeze: false })
cfoo === cbar // false

Freezing

By default, freezing a value will perform a deep freeze on it.

To change this behaviour, set the environment variable LAZY_INIT_FREEZE_MODE to one of the following values:

  • "deep" (default)
  • "shallow"
  • "none"

Deep Freeze

The values of each key and symbol property will be recursively frozen. However, this only applies to arrays and plain objects. Other objects such as Set and Map will not be frozen.

const foo = lz({
   val: 'bar',
   obj: { a: 0, b: [], c: new Set() },
}, true)
foo.val = 'buzz' // error
foo.obj.a = 2 // error
foo.obj.b.push(1) // error
foo.obj.c.add(1) // ok
foo.obj.c = null // error

Shallow Freeze

Only the value itself will be frozen, not any of its array/object properties.

const foo = lz({
   val: 'bar',
   obj: { a: 0 },
}, true)
foo.val = 'buzz' // error
foo.obj.a = 2 // ok
foo.obj = {} // error

None

The value will not be frozen.

License

See license.