NextJS next/image Failed to parse src with Strapi 4 and Graphql - javascript

I'm not able to load the images with the next/image handler from the strapi cms.
the images are working perfectly with the normal tag but not with the next/image handler
My Setup
.env:
STRAPI_GRAPHQL_API=http://localhost:1337/graphql
API_URL=http://localhost:1337
IMAGES_DOMAIN=localhost
next.config.js:
module.exports = {
reactStrictMode: true,
images: {
domains: [process.env.IMAGES_DOMAIN],
path: '/_next/image',
loader: 'default',
},
}
Gallery component:
import Image from 'next/image'
const Intro = ({imageGallery}) => {
const { API_URL } = process.env
return (
<div>
{imageGallery.Images.data.map(image => {
const src = API_URL + image.attributes.url
return (
<div key={image.id}>
<Image src={src} width={200} height={200} />
</div>
);
})}
</div>
);
}
export default Intro;
Error Message:
1 of 6 unhandled errors
Unhandled Runtime Error
Error: Failed to parse src "undefined/uploads/Zucker_Nicolas_Gysin_DD_6_237_7b0eee1060.jpeg" on next/image, if using relative image it must start with a leading slash "/" or be an absolute URL (http:// or https://)
console.log(src) has a valid url with http://localhost:133/uploadas…

given this question is only 24 days old atm, I presume you use the latest Next.js version (version 9.4 or up).
If that is the case, you should not be defining your environment variables in your next.config.js file. Instead, you should be using your .env.local/ .env file to load and store your env constants.
Additionally you can expose these to the browser directly through starting your declarations with NEXT_PUBLIC_YOUR_VARIABLE.
So technically, your .env should be:
NEXT_PUBLIC_STRAPI_GRAPHQL_API=http://localhost:1337/graphql
NEXT_PUBLIC_API_URL=http://localhost:1337
NEXT_PUBLIC_IMAGES_DOMAIN=localhost

Related

I am having issue with my image src in next.js [duplicate]

This question already has answers here:
Environment variables not working (Next.JS 9.4.4)
(8 answers)
Closed 9 months ago.
I am using Sanity image url in my project and I am getting this error in my console page that says
next-dev.js?3515:25 Warning: Prop src did not match.
Server:"https://cdn.sanity.io/images/jbcyg7kh/production/4f6d8f5ae1bed2647201bfcaed2f270897b92306-800x533.jpg"
Client: "https://cdn.sanity.io/images/jbcyg7kh/undefined/4f6d8f5ae1bed2647201bfcaed2f270897b92306-800x533.jpg"
import sanityClient from "#sanity/client";
import imageUrlBuilder from "#sanity/image-url";
export const client = sanityClient({
projectId:"projectId",
dataset:process.env.NEXT_SANITY_DATASET,
useCdn: true,
apiVersion:"2022-05-13"
});
const builder = imageUrlBuilder(client)
export const urlFor= (source) =>builder.image(source)
import Link from "next/link";
import React from "react";
import { urlFor } from "../lib/client";
function Product({ product: { name, image, price, description, slug } }) {
return (
<div>
<Link href={`/product/${slug.current}`}>
<div>
<img src={urlFor(image[0])} alt="" />
<h4>{name}</h4>
<p>₦{price}</p>
<p>{description}</p>
</div>
</Link>
</div>
);
}
export default Product;
It looks like the urlBuilder builds the URL builder from sanityClient. Judging by the pattern of the URLs,
Server:"https://cdn.sanity.io/images/jbcyg7kh/production/4f6d8f5ae1bed2647201bfcaed2f270897b92306-800x533.jpg"
Client:"https://cdn.sanity.io/images/jbcyg7kh/undefined/4f6d8f5ae1bed2647201bfcaed2f270897b92306-800x533.jpg"
You can see that server has process.env.NEXT_SANITY_DATASET set, while client does not. You can add this environment variable by following the steps here.

Why image path is not resolved by require() when passed as prop in NuxtJS?

In my NuxtJS project I have a component that recieves an image path as a prop. I tried passing it directly to :src="imageAddress" but it neither resolve nor throws an error. Then I tried to use this path inside require() to resolve it properly. But I get this Nuxt error: Cannot find module '~/assets/icons/crown.png'. The path is correct and I tested that by placing an img element directly in index.vue. Do you have any idea why this happens?
This is how my code is structured:
pages/index.vue
<template>
<ChildComponent image-address="~/assets/icons/crown.png" />
</template>
___________________________________________________________________
components/ChildComponent.vue
<template>
<img v-if="imageAddress.length" :src="require(imageAddress)">
</template>
<script>
export default {
name: 'ChildComponent',
props: {
imageAddress: {
type: String,
required: true,
default: ''
}
}
}
</script>
You can try to make method in ChildComponent:
getUrl (img) {
return require(`~/assets/icons/${img}.png`);
}
then in template:
<img :src="getUrl(imageAddress)" alt="" />

Gatsby SVG with <use> not working with gastby build

I created some SVG sprites/symbols to be able to use icon as component and with gatsby develop and it works fine (img below).
Problem is when i try to build my Gatsby application with gatsby build SVG icons are not showing (img below).
Anyone has idea what am I missing?
My Icon component:
import { IconTypes } from "./types";
import Icons from "./icons.svg";
interface Props {
name: IconTypes;
className?: string;
width?: number;
height?: number;
fill?: string;
}
export const Icon: FC<Props> = ({ name, className, width, height, fill }) => {
return (
<svg className={className} width={width} height={height} fill={fill}>
<use href={`${Icons}#${name}`} />
</svg>
);
};
Using SVGs in Gatsby + React could be tricky. I would suggest using gatsby-plugin-react-svg since it controls all the fallbacks. In your gatsby-config.js:
plugins: [
{
resolve: "gatsby-plugin-react-svg",
options: {
rule: {
include: /svg/
}
}
}
];
Note that the including rule is a regular expression. It means that /svg/ folder is the folder path in all your project (i.e: if you have your SVGs inside /src/assets/svg in the plugin configuration must include only /svg/).
The rest of the configuration is similar to the one you've described:
import Icon from "./path/assets/icon.svg";
// ...
<Icon />;

Importing SVG in NextJS

I am trying to import an svg within a NextJS project, everytime I get this error
./assets/aboutimg.svg 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="578" height="1028" viewBox="0 0 578 1028">
| <image id="_64538565_2370063099695596_8091233071539421184_n" data-name="64538565_2370063099695596_8091233071539421184_n" width="578" height="1028" xlink:href="
I have tried using next-images and also svgr. I will paste my About.js code below, it would be excellent if someone could let me know what I have been doing wrong.
import LayoutNoLogo from '../comps/LayoutNoLogo'
import AboutImg from '../assets/aboutimg.svg'
const About = () => {
return (
<LayoutNoLogo>
<div className="row">
<div className="column-1">
<img src={AboutImg} />
</div>
<div className="column-2">
<h1>About</h1>
</div>
</div>
<style jsx>{`
`}</style>
</LayoutNoLogo>
)
}
export default About;
I've finally used file-loader for using SVG images in my project.
install webpack and file loader : yarn add webpack, yarn add file-loader -D
in next.config.js:
module.exports = {
//...other configs
webpack: (config, {}) => {
config.module.rules.push({
test: [/\.svg$/, /\.woff$/],
loader: 'file-loader',
options: {
name: '[name].[hash:8].[ext]',
publicPath: `/_next/static/images/`, //specify the base path
outputPath: 'static/images', //and output path
}
})
}
}
Now I can use import img from '../assets/image.svg'
Using next-images and adding the correct module exports allowed me to use images of all file types.
https://www.npmjs.com/package/next-images

React Server Side Rendering with Sass

As i have searched through the previous but could not find any relevant / solved issues on this so I ask...
Current stack: React, express/node, Sass, Webpack, Sass.
I have a question specific to the Styling of pages before server sends them to the browser.
Styling is working perfectly in the browser and by I mean when the pages are being navigated via browser router, all the styling works. However, I need to figure out a way to inject custom Sass styles to the page before the Server sends the page to the browser.
Current behavior: I access any page from the browser, I get serve the page with correct styling BUT there is a minor delay to get the correct styling in place to appear on the page. If view in slow motion, page appears without styling (because the server sent the page with no styling) and then browser takes over with correct styling.
I have tried webpack to generate all styles in a separate file but I can't seem to link this file to page before server sends it to the browser.
Any help / feedback will be appreciated?
server.js(route handler)
app.get('*', (req, res) => {
const store = createStore();
const promises = matchRoutes(Routes, req.path).map(({ route }) => {
return route.loadData ? route.loadData(store) : null;
});
Promise.all(promises)
.then(() => {
const context = {};
const content = renderer(req, store, context);
if (context.notFound) res.status(404);
res.send(content);
});
});
const PORT = process.env.PORT || 3000;
renderer.js
import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter, matchPath } from 'react-router-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import serialize from 'serialize-javascript';
import Routes from '../client/Routes';
export default (req, store, context) => {
// req.path is the url that the user is trying to access
const content = renderToString(
<Provider store={store}>
<StaticRouter location={req.path} context={context}>
<div>
{ renderRoutes(Routes) }
</div>
</StaticRouter>
</Provider>
);
return `
<html>
<head>
<link rel="stylesheet" href="../../public/styles.css">
</head>
<body>
<div id='app'>${content}</div>
<script>
window.INITIAL_STATE = ${serialize(store.getState())}
</script>
<script src="bundle.js"></script>
</body>
</html>
`;
};
webpack.config.js (I omitted the rest of config since its not relevant)
const extractSass = new ExtractTextPlugin({
filename: "styles.css",
disable: process.env.NODE_ENV === "development"
});
module: {
rules: [{
test: /\.scss$/,
use: extractSass.extract({
use: [{
loader: "css-loader"
}, {
loader: "sass-loader"
}],
// use style-loader in development
fallback: "style-loader"
})
}]
},
plugins: [ extractSass ],
This gives me a styles.css file in my /build folder. How can i link this to my html. If i try to throw a <link> tag the browser does not recognize the file.
I finally solved this issue by creating another route handler.
app.get('/styles.css', (req, res) => {
res.sendFile(__dirname + "/" + "styles.css");
});
My webpack compiles a styles.css file which gets put in the /public folder. Please note i changed the path of my styles file in webpack to this: ../public/styles.css
app.use(express.static('public'));
Above statement ^^^ makes the styles.css file accessible and finally styles are applied by supplying the below <link> tag in the response of server to the browser.
<link rel="stylesheet" href="../../public/styles.css">
If anyone else have a better solution, I would love to get feedback.

Categories