commerce icon indicating copy to clipboard operation
commerce copied to clipboard

Placeholder Blur of Remote Shopify image with Next.js Image component fails - "Native Module not found: sharp"

Open hatchli opened this issue 2 years ago • 1 comments

Unable to implement placeholder blur of remote image (Shopify cdn) using the recommended Placeholder package implementation along with the Next.js Image component. Wondering if this has something to do with the Edge runtime that the vercel/commerce package uses.

Any help would be appreciated.

getbase64.ts

import { getPlaiceholder } from "plaiceholder"
export default async function getBase64(src: string) {
    const buffer = await fetch(src).then( async (res)=>{
        return Buffer.from(await res.arrayBuffer())
    })
   const {base64} = await getPlaiceholder(buffer)  
    return base64
}

components/layout/spread/index.tsx

import Image from 'next/image';
import getBase64 from 'lib/getBase64';

...

export default async function Spread({ priority = false, handle, alt }: Spread) {
...
 const myBlurDataUrl = await getBase64("https://cdn.shopify.com/s/files/1/0814/8126/9557/files/01a0e9c07671466919fa6577e1b070d34b2557d5-5297x3532.webp?v=1693503849")
...
return (
...
<Image
              alt={alt}
              src={metaobject?.image?.reference?.image?.url}
              priority={priority}
              fill
              className="object-cover object-center"
              sizes="(min-width: 1024px) 100vw, 150vw"
              placeholder="blur"
              blurDataURL={myBlurDataUrl}
              quality={priority ? 100 : 90}
            />
...

Terminal output:

- error TypeError: Native module not found: sharp
    at Object.sharp (/Users/.../Git/.../.next/server/app/page.js:29:18)
    at __webpack_require__ (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:37:33)
    at fn (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:325:21)
    at __webpack_require__ (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:37:33)
    at fn (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:325:21)
    at eval (./getBase64.ts:5:70)
    at Module.(rsc)/./getBase64.ts (/Users/.../Git/.../.next/server/app/page.js:2744:1)
    at __webpack_require__ (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:37:33)
    at fn (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:325:21)
    at eval (./components/layout/spread/index.tsx:10:67)
    at Module.(rsc)/./components/layout/spread/index.tsx (/Users/.../Git/.../.next/server/app/page.js:2711:1)
    at __webpack_require__ (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:37:33)
    at fn (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:325:21)
    at eval (./app/page.tsx:13:82)
    at Module.(rsc)/./app/page.tsx (/Users/.../Git/.../.next/server/app/page.js:2450:1)
    at __webpack_require__ (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:37:33)
    at Function.fn (/Users/.../Git/.../.next/server/edge-runtime-webpack.js:325:21)
    at async Promise.all (index 0)

package.json

{
  "private": true,
  "packageManager": "[email protected]",
  "engines": {
    "node": ">=18",
    "pnpm": ">=7"
  },
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "lint-staged": "lint-staged",
    "prettier": "prettier --write --ignore-unknown .",
    "prettier:check": "prettier --check --ignore-unknown .",
    "test": "pnpm lint && pnpm prettier:check"
  },
  "git": {
    "pre-commit": "lint-staged"
  },
  "lint-staged": {
    "*": "prettier --write --ignore-unknown"
  },
  "browser": {
    "child_process": false
  },
  "dependencies": {
    "@headlessui/react": "^1.7.17",
    "@heroicons/react": "^2.0.18",
    "@plaiceholder/next": "^3.0.0",
    "@plaiceholder/tailwindcss": "^3.0.0",
    "clsx": "^2.0.0",
    "next": "13.4.19",
    "plaiceholder": "^3.0.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "server-only": "^0.0.1",
    "sharp": "^0.32.5",
    "string-to-color": "^2.2.2",
    "uuid": "^9.0.0"
  },
  "devDependencies": {
    "@tailwindcss/container-queries": "^0.1.1",
    "@tailwindcss/forms": "^0.5.6",
    "@tailwindcss/typography": "^0.5.9",
    "@types/node": "20.5.7",
    "@types/react": "18.2.21",
    "@types/react-dom": "18.2.7",
    "@types/uuid": "^9.0.3",
    "@vercel/git-hooks": "^1.0.0",
    "autoprefixer": "^10.4.15",
    "eslint": "^8.48.0",
    "eslint-config-next": "^13.4.19",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-unicorn": "^48.0.1",
    "lint-staged": "^14.0.1",
    "postcss": "^8.4.29",
    "prettier": "3.0.3",
    "prettier-plugin-tailwindcss": "^0.5.4",
    "tailwindcss": "^3.3.3",
    "typescript": "5.2.2"
  }
}

next.config.mjs

// @ts-check
import withPlaiceholder from "@plaiceholder/next";
 

/** @type {import('next').NextConfig} */
const config = {
  eslint: {
    // Disabling on production builds because we're running checks on PRs via GitHub Actions.
    ignoreDuringBuilds: true
  },
  experimental: {
    serverActions: true
  },
  images: {
    formats: ['image/avif', 'image/webp'],
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'cdn.shopify.com',
        pathname: '/s/files/**'
      }
    ]
  },
  async redirects() {
    return [
      {
        source: '/password',
        destination: '/',
        permanent: true
      }
    ];
  }
};

export default withPlaiceholder(config)

hatchli avatar Sep 01 '23 16:09 hatchli

Did you ever resolve this, im getting the same error

chrisr0dgers avatar Apr 24 '24 20:04 chrisr0dgers