diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 83d530a8..78618342 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- site: [astro, lit, preact, qwik, react, solid, svelte, webc]
+ site: [astro, lit, preact, qwik, react, solid, webc]
steps:
- run: echo Running tests in ${{ matrix.site }}
- name: Checkout
diff --git a/docs/src/content/img/react.mdx b/docs/src/content/img/react.mdx
index cfb47a3e..ccb84c9a 100644
--- a/docs/src/content/img/react.mdx
+++ b/docs/src/content/img/react.mdx
@@ -79,7 +79,7 @@ import logo from "../public/logo.png";
/>
```
-> ⚠️ For versions of Next.js before 14.0.0, import from
+> ⚠️ For versions of Next.js before 13.5, import from
> `@unpic/react/next-legacy`, not `@unpic/react/nextjs`
### Differences from `next/image`
diff --git a/examples/nextjs/app/layout.tsx b/examples/nextjs/app/layout.tsx
new file mode 100644
index 00000000..1c43d2ea
--- /dev/null
+++ b/examples/nextjs/app/layout.tsx
@@ -0,0 +1,16 @@
+export const metadata = {
+ title: "Next.js",
+ description: "Generated by Next.js",
+};
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
{children}
+
+ );
+}
diff --git a/examples/nextjs/app/rsc/page.tsx b/examples/nextjs/app/rsc/page.tsx
new file mode 100644
index 00000000..c472abb1
--- /dev/null
+++ b/examples/nextjs/app/rsc/page.tsx
@@ -0,0 +1,45 @@
+import Head from "next/head";
+import { Image } from "@unpic/react/nextjs";
+export default function Home() {
+ return (
+ <>
+
+ Create Next App
+
+
+
+
+
+ >
+ );
+}
diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json
index 021ebafe..88bbd06e 100644
--- a/examples/nextjs/package.json
+++ b/examples/nextjs/package.json
@@ -14,11 +14,11 @@
"@types/react-dom": "^18.2.22",
"@unpic/react": "workspace:^",
"next": "^14.1.3",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
"typescript": "^5.4.2"
},
"devDependencies": {
- "@netlify/plugin-nextjs": "5.0.0-rc.1"
+ "@netlify/plugin-nextjs": "^5.0.0"
}
}
\ No newline at end of file
diff --git a/examples/nextjs/tsconfig.json b/examples/nextjs/tsconfig.json
index 8b8e5811..279f94bf 100644
--- a/examples/nextjs/tsconfig.json
+++ b/examples/nextjs/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -15,9 +19,23 @@
"jsx": "preserve",
"incremental": true,
"paths": {
- "@/*": ["./*"]
- }
+ "@/*": [
+ "./*"
+ ]
+ },
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
- "exclude": ["node_modules"]
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}
diff --git a/packages/react/README.md b/packages/react/README.md
index ede7c6d6..a0278a08 100644
--- a/packages/react/README.md
+++ b/packages/react/README.md
@@ -87,7 +87,7 @@ import logo from "../public/logo.png";
>;
```
-> ⚠️ For versions of Next.js before 14.0.0, import from
+> ⚠️ For versions of Next.js before 13.5, import from
> `@unpic/react/next-legacy`, not `@unpic/react/nextjs`
### Differences from `next/image`
diff --git a/packages/react/package.json b/packages/react/package.json
index 40c26276..14b1abd8 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -93,7 +93,7 @@
"@unpic/core": "0.0.49"
},
"peerDependencies": {
- "next": "^14.0.0",
+ "next": "^13.0.0 || ^14.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
},
diff --git a/packages/react/src/nextjs.tsx b/packages/react/src/nextjs.tsx
index c0a8985f..0733f781 100644
--- a/packages/react/src/nextjs.tsx
+++ b/packages/react/src/nextjs.tsx
@@ -1,10 +1,11 @@
-import { useContext, forwardRef, useMemo, useEffect } from "react";
+import { forwardRef, useMemo } from "react";
import type { ImageProps as UnpicImageProps } from "./index";
import { Image as UnpicImage } from "./index";
import { getImageCdnForUrl } from "unpic";
-import type { ImageConfigComplete } from "next/dist/shared/lib/image-config.js";
-import { imageConfigDefault } from "next/dist/shared/lib/image-config.js";
-import { ImageConfigContext } from "next/dist/shared/lib/image-config-context.shared-runtime.js";
+import {
+ imageConfigDefault,
+ type ImageConfigComplete,
+} from "next/dist/shared/lib/image-config.js";
//
const configEnv = process.env
@@ -32,37 +33,6 @@ export type ImageProps = Omit & {
src: string | StaticImport;
};
-function checkMatchingPatterns(config: ImageConfigComplete, src: string) {
- if (
- // match-remote-pattern doesn't support the edge runtime
- process.env.NEXT_RUNTIME === "edge" ||
- // we don't have access to the image domains/remotePatterns in production
- process.env.NODE_ENV !== "development"
- ) {
- return;
- }
-
- if (!src?.startsWith("http://") && !src?.startsWith("https://")) {
- return;
- }
- let parsedSrc: URL;
- try {
- parsedSrc = new URL(src);
- } catch (err) {
- console.error(err);
- return;
- }
-
- import("next/dist/shared/lib/match-remote-pattern").then(({ hasMatch }) => {
- if (!hasMatch(config.domains, config.remotePatterns, parsedSrc)) {
- throw new Error(
- `[Unpic]: Invalid src (${src}). Images that aren't on a supported image CDN must be configured under images in your \`next.config.js\`\n` +
- `See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host`,
- );
- }
- });
-}
-
// Next.js allows various different shapes of the src prop
function getImageData(src: string | StaticImport): StaticImageData | void {
if (typeof src === "string") {
@@ -79,8 +49,7 @@ export const Image = forwardRef(
// If using the next/image server we can only serve images with
// the same breakpoints as those in the config
- const configContext = useContext(ImageConfigContext);
- const config = configEnv || configContext || imageConfigDefault;
+ const config = configEnv || imageConfigDefault;
const breakpoints = useMemo(() => {
return [...config.deviceSizes, ...config.imageSizes];
}, [config]);
@@ -131,13 +100,6 @@ export const Image = forwardRef(
const isRemoteCdn = cdn && cdn !== "nextjs" && cdn !== "vercel";
- useEffect(() => {
- if (!src || !config || isRemoteCdn) {
- return;
- }
- checkMatchingPatterns(config, src);
- }, [src, isRemoteCdn, config]);
-
// Other image CDNs can use normal Unpic breakpoints
if (isRemoteCdn) {
return ;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 92a85ad8..47ff9e47 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -80,7 +80,7 @@ importers:
version: 2.3.1(astro@4.7.0)
'@astrojs/preact':
specifier: ^3.2.0
- version: 3.2.0(@babel/core@7.24.3)(preact@10.20.2)(vite@5.2.10)
+ version: 3.2.0(@babel/core@7.24.4)(preact@10.20.2)(vite@5.2.10)
'@astrojs/react':
specifier: ^3.3.1
version: 3.3.1(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1)(react@18.3.1)(vite@5.2.10)
@@ -266,20 +266,20 @@ importers:
version: link:../../packages/react
next:
specifier: ^14.1.3
- version: 14.1.3(react-dom@18.2.0)(react@18.2.0)
+ version: 14.1.3(react-dom@18.3.1)(react@18.3.1)
react:
- specifier: ^18.2.0
- version: 18.2.0
+ specifier: ^18.3.1
+ version: 18.3.1
react-dom:
- specifier: ^18.2.0
- version: 18.2.0(react@18.2.0)
+ specifier: ^18.3.1
+ version: 18.3.1(react@18.3.1)
typescript:
specifier: ^5.4.2
version: 5.4.2
devDependencies:
'@netlify/plugin-nextjs':
- specifier: 5.0.0-rc.1
- version: 5.0.0-rc.1
+ specifier: ^5.0.0
+ version: 5.1.2
examples/preact:
dependencies:
@@ -1890,17 +1890,17 @@ packages:
- supports-color
dev: false
- /@astrojs/preact@3.2.0(@babel/core@7.24.3)(preact@10.20.2)(vite@5.2.10):
+ /@astrojs/preact@3.2.0(@babel/core@7.24.4)(preact@10.20.2)(vite@5.2.10):
resolution: {integrity: sha512-p49NO/EgMbO5tCugFYXPQVAJelww46hXt947uGjXC8IchslS4MNqj4lH0ZzNGeeK1hRKXovz7/LK6AXJgMxleA==}
engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0}
peerDependencies:
preact: ^10.6.5
dependencies:
- '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.3)
- '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.24.3)
- '@preact/preset-vite': 2.8.2(@babel/core@7.24.3)(preact@10.20.2)(vite@5.2.10)
+ '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.4)
+ '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.24.4)
+ '@preact/preset-vite': 2.8.2(@babel/core@7.24.4)(preact@10.20.2)(vite@5.2.10)
'@preact/signals': 1.2.3(preact@10.20.2)
- babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.24.3)
+ babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.24.4)
preact: 10.20.2
preact-render-to-string: 6.3.1(preact@10.20.2)
preact-ssr-prepass: 1.2.1(preact@10.20.2)
@@ -3241,14 +3241,14 @@ packages:
'@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.1)
dev: true
- /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.24.3):
+ /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.24.4):
resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
- '@babel/core': 7.24.3
- '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.3)
+ '@babel/core': 7.24.4
+ '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.4)
dev: false
/@babel/plugin-transform-react-jsx-self@7.24.1(@babel/core@7.24.1):
@@ -6212,11 +6212,6 @@ packages:
engines: {node: '>=14'}
dev: true
- /@netlify/plugin-nextjs@5.0.0-rc.1:
- resolution: {integrity: sha512-VrGZo0z2OVChgQWuVinVNFXycSVfvvzcnMVNuoi9cSyFCyoV0zETF4gRgb+uDjq3zio0Z9eKkM56CC7p3vaQ+A==}
- engines: {node: '>=18.0.0'}
- dev: true
-
/@netlify/plugin-nextjs@5.1.2:
resolution: {integrity: sha512-rftBlZmrkxy8zeXZ/tT2u/v2iIZd9s0cV7MdtjUFOgizjhtY0fCZEUQ7OIEQIMogzGNMDXFcb84HXX9a8OZ8/w==}
engines: {node: '>=18.0.0'}
@@ -8263,18 +8258,18 @@ packages:
- supports-color
dev: true
- /@preact/preset-vite@2.8.2(@babel/core@7.24.3)(preact@10.20.2)(vite@5.2.10):
+ /@preact/preset-vite@2.8.2(@babel/core@7.24.4)(preact@10.20.2)(vite@5.2.10):
resolution: {integrity: sha512-m3tl+M8IO8jgiHnk+7LSTFl8axdPXloewi7iGVLdmCwf34XOzEUur0bZVewW4DUbUipFjTS2CXu27+5f/oexBA==}
peerDependencies:
'@babel/core': 7.x
vite: 2.x || 3.x || 4.x || 5.x
dependencies:
- '@babel/core': 7.24.3
- '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.3)
- '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.24.3)
+ '@babel/core': 7.24.4
+ '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.24.4)
+ '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.24.4)
'@prefresh/vite': 2.4.5(preact@10.20.2)(vite@5.2.10)
'@rollup/pluginutils': 4.2.1
- babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.24.3)
+ babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.24.4)
debug: 4.3.4(supports-color@9.4.0)
kolorist: 1.8.0
magic-string: 0.30.5
@@ -11629,12 +11624,12 @@ packages:
'@babel/core': 7.24.1
dev: true
- /babel-plugin-transform-hook-names@1.0.2(@babel/core@7.24.3):
+ /babel-plugin-transform-hook-names@1.0.2(@babel/core@7.24.4):
resolution: {integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==}
peerDependencies:
'@babel/core': ^7.12.10
dependencies:
- '@babel/core': 7.24.3
+ '@babel/core': 7.24.4
dev: false
/babel-preset-solid@1.8.15(@babel/core@7.24.1):
@@ -19684,7 +19679,7 @@ packages:
type-fest: 2.19.0
dev: true
- /next@14.1.3(react-dom@18.2.0)(react@18.2.0):
+ /next@14.1.3(react-dom@18.3.1)(react@18.3.1):
resolution: {integrity: sha512-oexgMV2MapI0UIWiXKkixF8J8ORxpy64OuJ/J9oVUmIthXOUCcuVEZX+dtpgq7wIfIqtBwQsKEDXejcjTsan9g==}
engines: {node: '>=18.17.0'}
hasBin: true
@@ -19705,9 +19700,9 @@ packages:
caniuse-lite: 1.0.30001599
graceful-fs: 4.2.11
postcss: 8.4.31
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
- styled-jsx: 5.1.1(react@18.2.0)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ styled-jsx: 5.1.1(@babel/core@7.24.1)(react@18.3.1)
optionalDependencies:
'@next/swc-darwin-arm64': 14.1.3
'@next/swc-darwin-x64': 14.1.3
@@ -24329,24 +24324,6 @@ packages:
'@babel/core': 7.24.1
client-only: 0.0.1
react: 18.3.1
- dev: true
-
- /styled-jsx@5.1.1(react@18.2.0):
- resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
- engines: {node: '>= 12.0.0'}
- peerDependencies:
- '@babel/core': '*'
- babel-plugin-macros: '*'
- react: '>= 16.8.0 || 17.x.x || ^18.0.0-0'
- peerDependenciesMeta:
- '@babel/core':
- optional: true
- babel-plugin-macros:
- optional: true
- dependencies:
- client-only: 0.0.1
- react: 18.2.0
- dev: false
/stylehacks@6.1.0(postcss@8.4.38):
resolution: {integrity: sha512-ETErsPFgwlfYZ/CSjMO2Ddf+TsnkCVPBPaoB99Ro8WMAxf7cglzmFsRBhRmKObFjibtcvlNxFFPHuyr3sNlNUQ==}