Nextjs imgix configuration issue with ?url params - next.js

I'm trying to setup the built-in imgix loader for nextjs 12+.
When I look in the dom the srcsets are as follows:
https://account.imgix.net/?url=%2Fhero.jpeg%26fm%3Dwebp&w=640&q=20
It appends this ?url= and the image isn't shown because of it. Not sure if there is something I'm missing or not understanding ?
Thank you in advance!
My setup:
Next.config.js
loader: "imgix",
path: "https://account.imgix.net/",
domains: ["account.imgix.net"],
Then I try to render a next/image component like so:
<Image
alt="hero"
src={`/hero.jpeg`}
fill
quality={20}
style={{
objectFit: "cover",
objectPosition: "20% center",
borderRadius: 10,
}}
priority
/>

As was mentioned in the first comment, next/image no longer supports global loader configurations. You have to use the loader prop.
// Example next/image loader
import Image from "next/image";
const normalizeSrc = (src) => (src[0] === "/" ? src.slice(1) : src);
const imgixLoader = ({ src, width, quality }) => {
const url = new URL("https://example.com/" + normalizeSrc(src));
const params = url.searchParams;
params.set("auto", params.getAll("auto").join(",") || "format");
params.set("fit", params.get("fit") || "max");
params.set("w", params.get("w") || width.toString());
if (quality) {
params.set("q", quality.toString());
}
return url.href;
};
const MyImage = (props) => {
return (
<Image
loader={imgixLoader}
src="me.png"
alt="Picture of the author"
width={500}
height={500}
/>
);
};
However, if you'd like to avoid having to do this each time you use the component, you can use the React Provider Pattern to provide that prop to any next/image component you're using. This will remove the need to set it inline on each instance of the component.
Take a look at this CodeSandbox where we use the Provider pattern to give all the Next <Image /> components the same imgix loader configuration if you want to learn more.

Seems like next 13 doesn't support global loaders anymore. So I will have to add the loader to each image component I'm rendering.

Related

Statically loading NextJS Image gives 404 on production but works on localhost

I don't understand why the static image is not found on production, but works on localhost. I put all my images in the directory: public/images/...
/* image.tsx */
return (
<Image
src={"/images/frame1.png"}
width="1000"
height="1000"
alt="Control description"
style={{
height: "auto",
maxWidth: "100%",
userSelect: "none",
}}
/>
)
/* next.config.js */
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
};
module.exports = nextConfig;
Cloudflare pages deployment:
Localhost:
My file structure:
The fix from <Image /> to <img /> does resolve it in some instances, but it is not the recommended way as then you are not taking advantage of NextJS's powerful image optimization.
Your problem is that you are using relative paths instead of importing the file and using it by reference.
To fix you issue, try this:
import Image from 'next/image';
import frameImage from '../public/images/frame1.png'; // path to your folder
export default function ImagePage() {
return (
<Image
src={frameImage}
...otherProps
/>
)
}
Docs here: https://beta.nextjs.org/docs/optimizing/images
first : did you try changing <Image/> to <img/> ? test this and see if it's fixed or not ( just to be sure where the problem is coming from )
second try this: change the name of the image files.from uppercase to lowercase letters.

Nextjs Image an issue with "loader" property that does not implement width

This is my code for the Nextjs Image component:
... Cell: ({ value }: CellType) => (
<Image
priority
src={value}
loader={() => value}
className={''}
height={100}
width={100}
alt={'profile_picture'}
/>
),
Does it mean I need a custom loader function to get rid off the warning? Thanks!
I had a same issue like yours and solved by adding unoptimized={true} prop into the <Image> tag.
If you don't apply optimizations, you need to announce that you don't optimize.
Something like below:
<Image
priority
src={value}
loader={() => value}
unoptimized={true} // <=== insert this prop
className={''}
height={100}
width={100}
alt={'profile_picture'}
/>
Please let me know if it work.
Thank you.
I had the same error but what I have done to fix it is to incorporate in the next.config.js file the URL of my media files, in my case it is cloudinary, the file should look like this:
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
domains: [
'res.cloudinary.com'
],
},
}
module.exports = nextConfig
And when I use the image component (next/image) I remove the loader and just put the URL like this:
<Image
key={element.id}
src={element.url}
width={500}
height={500}
alt="some description"
/>
I don't use unoptimized={true} because the point is that the component changes the quality of the image according to the client's device.
good look :)

Font Awesome 6 (beta) and dynamic icon name in Next JS

I am developing a website with Next JS. This is the first time I use this language and I still have a lot to learn.
Now, I have a Pro subscription to Font Awesome and I am looking to use their component directly in my project, as described in their guides.
https://fontawesome.com/v6.0/docs/web/use-with/react/
https://fontawesome.com/v6.0/docs/web/use-with/react/add-icons
Basically, just using a component like this:
<FontAwesomeIcon icon={brands("google")} />
It works.
The problem, which I can't solve, is how to set the "google" value dynamically, in a previously initialized variable. I need that because this values are coming dynamically from a database.
If I try:
var example = "google";
<FontAwesomeIcon icon={brands(example)} />
Then I receive this error: "Only string literals are supported when referencing icons (use a string here instead)".
Anyone have any ideas?
The way you import your icons uses a babel macro. It means that the referenced icon must be known at build time. It just won't work, because Babel can't figure out what icon should be imported, it can only be done during runtime. That's why it tells you that only string literals are supported.
So you need to use the second method, explained in the docs. You have to have some kind of mapping between icon and the value from DB and then grab the relevant icon. Something like this:
// not sure about exact import
import { faGoogle } from '#fortawesome/free-brand-svg-icons';
// you'd put all valid values that can come from the backend here
const myIcons = {
google: faGoogle
}
// ...
const example = 'google';
<FontAwesomeIcon icon={myIcons[example]} />
The other option is to use library.add, explained here and then do the same as above but instead of imported icon use a string, e.g. google: 'fa-brands fa-google' (again, not sure about exact value here).
Would the following work?
var example = ['fab', 'google'];
<FontAwesomeIcon icon={example} />
P.S. It is recommended to use the let or const keywords with ES6.
// Utils
const UpperFirst = (sentence) => {
if (!sentence || (typeof sentence !== 'string')) return null
return `${sentence.charAt(0).toUpperCase()}${sentence.slice(1)}`
}
// React Generic Component
import React from 'react'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import * as solid from '#fortawesome/free-solid-svg-icons'
import * as regular from '#fortawesome/free-regular-svg-icons'
import { UpperFirst } from '#utils'
const GenFontAwe = ({ isReg, customClass, nameIco }) => {
if (!nameIco) return null
const finalName = nameIco.split('-').map((cv, ind) => ind === 0 ? cv : UpperFirst(cv)).join('')
const finalIcon = isReg ? regular[finalName] : solid[finalName]
if(!finalIcon) return null
return <FontAwesomeIcon icon={finalIcon} className={customClass || ''} />
}
export default GenFontAwe
// Consume that way:
<GenFontAwe nameIco='fa-folder-open' isReg customClass="h1 p-5" />

React-tooltip and Next.js SSR issue

I use the react-tooltip library in my Next.js app.
I noticed that every time I refresh a website while visiting a page that uses the tooltip I get an error:
react-dom.development.js:88 Warning: Prop `dangerouslySetInnerHTML` did not match.
CSS classes are different on the client and on the server
The weird part is I do not get that error while navigating from a random page to a page that uses the react-tooltip.
The tooltip related code:
<StyledPopularityTooltipIcon src="/icons/tooltip.svg" alt="question mark" data-tip="hello world" />
<ReactTooltip
effect="solid"
className="tooltip"
backgroundColor="#F0F0F0"
arrowColor="#F0F0F0"
clickable={true}
/>
I had the same issue, I had to use state to detect when component has been mounted, and show the tooltip only after that.
P.S. You don't see the error when navigating, because the page is not rendered on server when you navigate, it's all front-end :)
In case you are using any server-side rendering (like Next.js) - you will need to make sure your component is mounted first before showing the react-tooltip.
I fixed this by using the following:
import React, { useEffect, useState } from 'react';
const [isMounted,setIsMounted] = useState(false); // Need this for the react-tooltip
useEffect(() => {
setIsMounted(true);
},[]);
return (<div>
{isMounted && <ReactTooltip id={"mytip"} effect={"solid"} />}
<span data-tip={"Tip Here"} data-for={"mytip"}>Hover me</span>
</div>)
You should wrap your JSX in the following component:
import React, { useEffect, useState } from 'react';
const NoSsr = ({ children }): JSX.Element => {
const [isMounted, setMount] = useState(false);
useEffect(() => {
setMount(true);
}, []);
return <>{isMounted ? children : null}</>;
};
export default NoSsr;
Like this:
<NoSsr>
<YourJSX />
</NoSsr>
If you are working with NEXTJS this might be a good approach, you can check the documentation here as well, also if you are working with data-event, globalEventOff or any other prop and is not hiding or not working in your localhost, this only occurs in Development Strict Mode. ReactTooltip works fine in Production code with React 18. So you can set reactStrictMode : false, in your next.config.js to test it locally and then set it back to true, hope this helps :) info reference here
import dynamic from 'next/dynamic'
const ReactTooltip = dynamic(() => import('react-tooltip'), { ssr : false });
function Home() {
return (
<div>
<Button
data-tip
data-event="click focus"
data-for="toolTip"
onClick={():void => ()}
/>
<ReactTooltip id="toolTip" globalEventOff="click"/>
</div>
)
}
export default Home

VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) with Azure Media Services

I have a Next app where I want to embed a player. To do so, I decided to use the video.js library.
Everything works fine with, eg, youtube videos.
However, Video.js player doesn't play videos hosted on Azure Media Service
My player code:
import { useCallback, useEffect, useState } from 'react';
import videojs from 'video.js';
import 'videojs-youtube';
import 'videojs-flash';
import 'videojs-vimeo';
const Player = (props) => {
const [videoEl, setVideoEl] = useState(null);
const onVideo = useCallback((el) => {
setVideoEl(el);
}, []);
useEffect(() => {
if (videoEl == null) return;
const player = videojs(videoEl, props);
console.log('quality', player.getVideoPlaybackQuality());
return () => {
player.dispose();
};
}, [props, videoEl]);
return (
<>
{/* wrap the player in a div with a `data-vjs-player` attribute
so videojs won't create additional wrapper in the DOM */}
<div data-vjs-player>
<video
ref={onVideo}
className="video-js"
style={{ width: '100%', height: '100%' }}
playsInline
/>
</div>
</>
);
};
export default Player;
The options for videos are the following:
const videoJsOptions = {
techOrder: ['html', 'youtube', 'flash', 'other supported tech'],
autoplay: true,
controls: true,
usingNativeControls: true,
sources: [
{
src:
'https://my-video.streaming.media.azure.net/49a94f-122/manifest',
type: 'application/vnd.ms-sstr+xml'
}
]
};
In the head of the app I injected the following links from the Azure docs:
<link
href="//amp.azure.net/libs/amp/2.3.5/skins/amp-default/azuremediaplayer.min.css"
rel="stylesheet"
/>
<script src="//amp.azure.net/libs/amp/2.3.5/azuremediaplayer.min.js"></script>
I get this error
VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) No compatible source was found for this media.
Not sure exactly about the specific issue noted above, I think that you may be trying to use Smooth Streaming "ms-sstr+xml" which is not going to be the best choice on Video.js.
We do have some samples in this repo that we just published that shows how to use Video.js with AMS - and also lists off the known issues.
https://github.com/Azure-Samples/media-services-3rdparty-player-samples
Take a look there and see if that helps with your use case scenario. Would welcome your feedback on this repo since it is new. Add Issues in the github if you see any.

Resources