{"id":44360937,"url":"https://github.com/akzhy/nocojs","last_synced_at":"2026-02-11T17:25:39.238Z","repository":{"id":311474448,"uuid":"1026805751","full_name":"akzhy/nocojs","owner":"akzhy","description":"Build time library to generate image previews","archived":false,"fork":false,"pushed_at":"2025-10-28T16:26:12.000Z","size":11978,"stargazers_count":19,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-12-05T01:40:48.214Z","etag":null,"topics":["build-time","image"],"latest_commit_sha":null,"homepage":"https://nocojs.netlify.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akzhy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-26T16:45:08.000Z","updated_at":"2025-10-29T10:21:59.000Z","dependencies_parsed_at":"2025-08-24T21:44:16.069Z","dependency_job_id":"a8fdbb0c-0590-449c-8ac5-3fcd67a0bd27","html_url":"https://github.com/akzhy/nocojs","commit_stats":null,"previous_names":["akzhy/nocojs"],"tags_count":64,"template":false,"template_full_name":null,"purl":"pkg:github/akzhy/nocojs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akzhy%2Fnocojs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akzhy%2Fnocojs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akzhy%2Fnocojs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akzhy%2Fnocojs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akzhy","download_url":"https://codeload.github.com/akzhy/nocojs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akzhy%2Fnocojs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29339372,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T16:14:43.024Z","status":"ssl_error","status_checked_at":"2026-02-11T16:14:15.258Z","response_time":97,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-time","image"],"created_at":"2026-02-11T17:25:38.626Z","updated_at":"2026-02-11T17:25:39.233Z","avatar_url":"https://github.com/akzhy.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nocojs\n\nBuild-time image tooling for modern web apps. Generate lightweight placeholders, responsive image variants, and matching client helpers without shipping extra runtime code.\n\n## Overview\n\nnocojs can work both on the client side during bundling and on the server side in build scripts or SSR frameworks.\n\nFor client side, with appropriate bundler integration, nocojs scans your source during bundling, finds calls to `placeholder()`, and replaces them with inline data URLs.\nOn the server (Astro, NextJS, Tanstack Start) you can call `getPlaceholder()` or `getOptimizedImage()` to create the same assets programmatically.\n\n\n**Note:** nocojs focuses on build-time generation, you will have to handle lazy-loading yourself. Pair it with your preferred lazy-loading or progressive enhancement strategy, such as:\n- [react-lazy-load-image-component](https://www.npmjs.com/package/react-lazy-load-image-component)\n- [lozad.js](https://github.com/ApoorvSaxena/lozad.js)\n- [lazysizes](https://github.com/aFarkas/lazysizes)\n- [vanilla-lazyload](https://github.com/verlok/vanilla-lazyload)\n\n## Features\n\n- **Zero runtime overhead** – placeholders are inlined during the build.\n- **Multiple placeholder types** – blurred, grayscale, dominant-color, average-color, transparent, or the default miniaturized version.\n- **Responsive outputs** – `getOptimizedImage()` creates multi-format, multi-width srcsets and optional placeholders in one call.\n- **Bundler integrations** – works with Webpack, Rspack, Rollup/Vite, and Parcel.\n\n\n## Quick Start\n\n### Installation\n\nInstall the main package along with the bundler integration (if you require client-side support) that matches your stack:\n\n```bash\n# Pick the integration that matches your bundler\nnpm install nocojs @nocojs/rollup-plugin      # Rollup / Vite\nnpm install nocojs @nocojs/webpack-loader     # Webpack / Next.js\nnpm install nocojs @nocojs/rspack-loader      # Rspack\nnpm install nocojs @nocojs/parcel-transformer # Parcel\n```\n\n### Client usage\n\n```tsx\nimport { placeholder } from \"nocojs/client\";\n\nexport function HeroImage() {\n  return \u003cimg src={placeholder(\"/images/hero.jpg\")} alt=\"Hero\" /\u003e;\n}\n```\n\nWith an integration configured, the bundler replaces the call above with a base64 data URI during the build.\n\n### Server or build scripts\n\n```ts\nimport { getPlaceholder, getOptimizedImage } from \"nocojs\";\n\nconst heroPlaceholder = await getPlaceholder(\"./public/hero.jpg\", {\n  placeholderType: \"blurred\",\n  width: 16,\n});\n\nconst responsive = await getOptimizedImage(\"./public/hero.jpg\", {\n  outputDir: \"./public/generated\",\n  baseUrl: \"/generated\",\n  widths: [640, 960, 1280],\n  formats: [\"webp\", \"jpg\"],\n});\n\nconsole.log(heroPlaceholder.placeholder);\nconsole.log(responsive.srcset);\n```\n\n\n## Configuration\n\n### Vite / Rollup\n\n```js\nimport { defineConfig } from \"vite\";\nimport { rollupNocoPlugin } from \"@nocojs/rollup-plugin\";\n\nexport default defineConfig({\n  plugins: [\n    rollupNocoPlugin({\n      publicDir: \"public\",\n      cacheFileDir: \".nocojs\",\n      placeholderType: \"blurred\",\n      width: 12,\n    }),\n  ],\n});\n```\n\n### Webpack / Next.js\n\n```js\n// webpack.config.js\nmodule.exports = {\n  module: {\n    rules: [\n      {\n        test: /\\.(js|ts|jsx|tsx)$/,\n        use: [\n          {\n            loader: \"@nocojs/webpack-loader\",\n            options: {\n              publicDir: \"public\",\n              cacheFileDir: \".nocojs\",\n              placeholderType: \"blurred\",\n              width: 12,\n            },\n          },\n        ],\n      },\n    ],\n  },\n};\n```\n\n### Transform options\n\nBundler integrations forward these options to the core transformer:\n\n```ts\ninterface TransformOptions {\n  placeholderType?: \"normal\" | \"blurred\" | \"grayscale\" | \"dominant-color\" | \"average-color\" | \"transparent\";\n  width?: number;\n  height?: number;\n  wrapWithSvg?: boolean;\n  cache?: boolean;\n  replaceFunctionCall?: boolean;\n  publicDir?: string;\n  cacheFileDir?: string;\n  logLevel?: \"none\" | \"error\" | \"info\" | \"verbose\";\n}\n```\n\n### Placeholder options (server APIs)\n\n```ts\ninterface GetPlaceholderOptions {\n  placeholderType?: \"normal\" | \"blurred\" | \"grayscale\" | \"dominant-color\" | \"average-color\" | \"transparent\";\n  width?: number;\n  height?: number;\n  wrapWithSvg?: boolean;\n  cache?: boolean;\n  cacheFileDir?: string;\n  _enableLogging?: boolean;\n}\n```\n\n### Optimized image options\n\n```ts\ninterface GetOptimizedImageOptions {\n  outputDir: string;\n  widths?: number[];\n  baseUrl?: string;\n  formats?: string[];\n  quality?: number;\n  namingPattern?: string;\n  placeholderOptions?: GetPlaceholderOptions | null;\n  cache?: boolean;\n}\n```\n\n## Important Guidelines (for bundler integration)\n\n### DOs ✅\n\n- **Use static, analyzable paths**: Always provide fixed string literals or easily resolvable paths\n  ```typescript\n  placeholder('/images/hero.jpg')           // ✅ Good\n  placeholder('https://cdn.example.com/image.jpg') // ✅ Good\n  ```\n\n- **Use with lazy loading libraries**: Combine with libraries like `react-intersection-observer`, `lozad.js`, or `lazysizes`\n- **Keep placeholders small**: Default 12px width is optimized for performance\n- **Use consistent placeholder types**: Stick to one type across your application for visual consistency\n\n### DON'Ts ❌\n\n- **Avoid dynamic arguments**: The build-time parser cannot resolve dynamic values\n  ```typescript\n  const imagePath = '/images/photo.jpg';\n  placeholder(imagePath)                    // ❌ Bad - dynamic variable\n  placeholder(`/images/${filename}`)        // ❌ Bad - template literal with variables\n  placeholder(getImagePath())               // ❌ Bad - function call result\n  ```\n\n- **Don't use with conditionals**: Build-time analysis requires static calls\n  ```typescript\n  placeholder(condition ? 'img1.jpg' : 'img2.jpg') // ❌ Bad - conditional expression\n  ```\n\n- **Avoid runtime modifications**: The `placeholder()` function is replaced at build time\n  ```typescript\n  const result = placeholder('/image.jpg');\n  const modified = result + '?v=1';     // ❌ Bad - modifying the result\n  ```\n\n**Important**: All `placeholder()` function calls must be statically analyzable at build time. The arguments must be string literals or easily resolvable static expressions that the build tool can evaluate without executing your code.\n\n## Best Practices for client side usage\n\n- Use static string literals for `placeholder()` so the transformer can resolve paths.\n- Point relative paths to your `publicDir` (for example `placeholder(\"/images/photo.jpg\")`).\n- Combine the generated placeholders with a lazy-loading strategy to avoid layout shifts.\n- Keep the cache directory (default `.nocojs`) between builds for faster CI/CD pipelines.\n\n## Examples\n\nIntegration and usage examples can be found in the [examples repo](https://github.com/akzhy/nocojs-examples)\n\n## Caching\n\nnocojs stores metadata and generated placeholders in `.nocojs/cache.db` (configurable). Restoring this directory between builds allows the transformer and server APIs to reuse prior results.\n\n### CI examples\n\n**Netlify**\n\n```js\nexport const onPreBuild = async ({ utils }) =\u003e {\n  await utils.cache.restore(\".nocojs\");\n};\n\nexport const onPostBuild = async ({ utils }) =\u003e {\n  await utils.cache.save(\".nocojs\");\n};\n```\n\n\n## Packages\n\nThis monorepo contains the following packages:\n\n- **`nocojs`** – top-level package that re-exports the client `placeholder()` helper and the server utilities `getPlaceholder()` and `getOptimizedImage()`.\n- **`@nocojs/core`** – TypeScript engine that implements the transformer, placeholder generation, optimized image pipeline, and cache management.\n- **`@nocojs/rollup-plugin`** – Rollup/Vite integration.\n- **`@nocojs/webpack-loader`** – Webpack (and Next.js) loader.\n- **`@nocojs/rspack-loader`** – Rspack loader.\n- **`@nocojs/parcel-transformer`** – Parcel integration.\n\n## Development\n\nThis is a Lerna workspace with packages written in TypeScript.\n\n```\npackages/\n├── core/               # TypeScript engine shared by all integrations\n├── nocojs/             # Aggregated public API (client + server)\n├── rollup-plugin/      # Rollup / Vite integration + example\n├── webpack-loader/     # Webpack integration + example\n├── rspack-loader/      # Rspack integration\n└── parcel-transformer/ # Parcel integration + example\n```\n\n```bash\n# Enable pnpm via Corepack (once per environment)\ncorepack enable\n\n# Install dependencies\npnpm install\n\n# Build all packages\npnpm build:packages\n\n# Run tests\npnpm test\n```\n\n## Performance\n\n- **Fast builds** – `oxc-parser` provides speedy AST traversal and transformation.\n- **Efficient processing** – `sharp` powers resizing and color extraction.\n- **Tiny payloads** – placeholders are typically under 1 KB and served inline.\n\n## License\n\nMIT\n\n## Contributing\n\nContributions are welcome! To get started:\n\n1. Fork and clone the repo.\n2. Run `pnpm install` to bootstrap dependencies.\n3. Use `pnpm build:packages` and `pnpm test` to validate changes.\n4. Add or update documentation when introducing new features.\n5. Create a changeset with `pnpm changeset` before opening a pull request.\n\nCreate issues for bugs or ideas, or start a discussion if you’re planning a larger feature.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakzhy%2Fnocojs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakzhy%2Fnocojs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakzhy%2Fnocojs/lists"}