next/image does not load images from external URL after deployment - reactjs

I use the Next.js Image component for image optimization. It works great on dev but it doesn't load images from external URLs in production.
What can I do?

You need to set the configuration in the next.config.js file first.
For Example:
on next.config.js
module.exports = {
images: {
domains: ['images.unsplash.com'],
},
}
on pages/your_page_file.tsx
<Image
alt="The guitarist in the concert."
src="https://images.unsplash.com/photo-1464375117522-1311d6a5b81f?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=2250&q=80"
width={2250}
height={1390}
layout="responsive"
/>

Add and declare your domain in your next config, next.config.js:
module.exports = {
reactStrictMode: true,
images: {
domains: ["yourDomain.com"],
formats: ["image/webp"],
},
};
The configuration file, next.config.js, should be in the root of your project.
And lastly, restart project even in dev mode.

For future references, I was having the same problem after deploying my next.js site to Netlify. Only later, reading my logs, I found
Image domains set in next.config.js are ignored.
Please set the env variable NEXT_IMAGE_ALLOWED_DOMAINS to "cdn.sanity.io" instead
So this is probably something to note. In the meanwhile before I saw it, I plugged this next-sanity-image plugin https://www.sanity.io/plugins/next-sanity-image to my page, which also bypassed the problem

If you want to display any images in nextjs app from accross the internet; here is my next config:
const nextConfig = {
reactStrictMode: true,
i18n,
sassOptions: {
includePaths: [path.join(__dirname, 'src/styles')],
prependData: `#import "variables.scss";`,
},
images: {
remotePatterns: [
{
protocol: 'https',
hostname: '**',
port: '',
pathname: '**',
},
],
},
}

For me was just add blocker extension.

Related

Next.js complains of unconfigured hostname for Next/Image, but it actually is

hope you are well.
With Next.js 13.0.5, I've been trying to use the Next/Image component with an external source (Amazon S3 through CloudFront).
<Image src={"https://d2ss8eaptdxs3l.cloudfront.net/profile_pictures/default.jpg"}
width={200}
height={200}
className="rounded-full"
/>
However, Next is complaining that I haven't configured the external hostname in next.config.js...
Error: Invalid src prop (https://d2ss8eaptdxs3l.cloudfront.net/profile-pictures/default.jpg) on `next/image`, hostname "d2ss8eaptdxs3l.cloudfront.net" is not configured under images in your `next.config.js`
See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
... while I actually did like so:
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
remotePatterns: [
{
protocol: "https",
hostname: "d2ss8eaptdxs3l.cloudfront.net",
port: "",
pathname: "/**",
},
],
},
}
module.exports = nextConfig
I've also tried the < 12.3.0 variation as described in the docs, with no success. https://nextjs.org/docs/messages/next-image-unconfigured-host
Could anyone help me out? Thank you very much.

Certain parts of tailwind CSS not working in production

I've built a static website for my next JS app that uses tailwind CSS for styling. I'm using statically as a CDN. The website in the development server(local host) works perfectly alright. However, in production, certain parts of styling seem to be broken (Header, Footer, and toggling between dark/light mode to be precise). Attaching screenshots for reference.
Local server:
Production:
When I inspect the corresponding elements in local and production env, there seems to be no difference in the HTML structure and class names, but when I hover over the broken elements (nav items in this case) in production, the corresponding elements are not being highlighted.
So far this is what I was able to find. Below are few config files:
next.config.js:
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
reactStrictMode: true,
images: {
// domains: ['raw.githubusercontent.com','ibb.co'],
domains: ['raw.githubusercontent.com'],
loader:'imgix',
path:''
},
assetPrefix: isProd ? 'CDN_LINK_HERE' : '',
}
tailwind.config.css :
module.exports = {
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
darkMode: 'class', // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
How do I go about fixing this?
Thanks.
Ensure to add a complete list of paths you need your CSS applied to in the purge array of tailwind.config.css.
module.exports = {
// ▼ here you need to add all paths according to your needs
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}', './your-other-component-folder/**/*.{js,ts,jsx,tsx}'],
darkMode: 'class', // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}

Click events in Nuxt don't work after generating static site [duplicate]

Does someone know why this happens? If I run nuxt locally (server) it works fine, but whenever I run yarn generate and load the index.html file in my browser all content between <client-only> tags disappear.
My nuxt config file:
export default {
// Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
ssr: true,
// Target: https://go.nuxtjs.dev/config-target
target: 'static',
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'Site name',
htmlAttrs: {
lang: 'nl'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'Description
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'preconnect', href: "https://fonts.gstatic.com"},
{ href: 'https://fonts.googleapis.com/css2?family=Nunito:wght#400;600;700&family=Open+Sans+Condensed:wght#700&display=swap', rel: 'stylesheet'}
],
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: ["#/assets/css/hamburgers.scss"],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/tailwindcss
'#nuxtjs/tailwindcss',
'#nuxtjs/fontawesome',
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
],
styleResources: {
scss: [
"assets/css/variables.scss",
"assets/css/hamburgers.scss",
]
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
Okay I've got it to work.
Javascript wasn't working properly because the files weren't linked correctly when I open index.html.
Because index.html is in a local folder somewhere on my PC, it searches for the javascript files on the root of the machine (where they don't exist).
I tested this locally on an Apache server with XAMPP and the same problem ocurred when I put the dist content generated by yarn generate in a subfolder so the URL would be localhost/subfolder.
The fix for this specific problem in this context would be to add to nuxt.config.js this:
router: {
base: '/subfolder/'
},
In the end this solution was not neccesary for me because when I were to host this on an actual Apache server and would put the files in the root directory so then the router property isn't needed unless I would put it there in a subfolder.
Earlier related questions from me:
Click events in Nuxt don't work after generating static site
Href and src generated by Nuxt in static site are not properly linked to js files after nuxt generate

<client-only> in Nuxt makes content disappear when running generate

Does someone know why this happens? If I run nuxt locally (server) it works fine, but whenever I run yarn generate and load the index.html file in my browser all content between <client-only> tags disappear.
My nuxt config file:
export default {
// Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
ssr: true,
// Target: https://go.nuxtjs.dev/config-target
target: 'static',
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'Site name',
htmlAttrs: {
lang: 'nl'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'Description
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'preconnect', href: "https://fonts.gstatic.com"},
{ href: 'https://fonts.googleapis.com/css2?family=Nunito:wght#400;600;700&family=Open+Sans+Condensed:wght#700&display=swap', rel: 'stylesheet'}
],
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: ["#/assets/css/hamburgers.scss"],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/tailwindcss
'#nuxtjs/tailwindcss',
'#nuxtjs/fontawesome',
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
],
styleResources: {
scss: [
"assets/css/variables.scss",
"assets/css/hamburgers.scss",
]
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
Okay I've got it to work.
Javascript wasn't working properly because the files weren't linked correctly when I open index.html.
Because index.html is in a local folder somewhere on my PC, it searches for the javascript files on the root of the machine (where they don't exist).
I tested this locally on an Apache server with XAMPP and the same problem ocurred when I put the dist content generated by yarn generate in a subfolder so the URL would be localhost/subfolder.
The fix for this specific problem in this context would be to add to nuxt.config.js this:
router: {
base: '/subfolder/'
},
In the end this solution was not neccesary for me because when I were to host this on an actual Apache server and would put the files in the root directory so then the router property isn't needed unless I would put it there in a subfolder.
Earlier related questions from me:
Click events in Nuxt don't work after generating static site
Href and src generated by Nuxt in static site are not properly linked to js files after nuxt generate

Best way to integrate webpack builds with ASP.NET Core 3.0?

I'm upgrading my ASP.NET Core app to V3, and using Visual Studio 2019 for development / debugging. The process has been smooth except for this:
public void Configure(…..
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = false,
ReactHotModuleReplacement = false
});
UseWebpackDevMiddleware is no more: https://github.com/aspnet/AspNetCore/issues/12890 .
I'm now looking to understand the best way to have VS run webpack every time I debug, ideally only on JS code that has changed. This was the value I was getting from UseWebpackDevMiddleware. My app is a React app, and it seems like there is some new replacement for this if your app was started from CreateReactApp, but mine was not. (I believe apps that stated from this but then separated are called "ejected.") Is it somehow possible for me to still take advantage of whatever that facility is, even though my app does not leverage CreateReactApp? Also, what is the role of CreateReactApp after it bootstraps your new React application? I imagined it would be only used for inflating template code at the first go.
What is the role of Microsoft.AspNetCore.SpaServices.Extensions in all of this?
I don't need hot module replacement; I don't need server side prerendering. I'm really just trying to understand how to get my JS to transparently build (via Webpack) as part of my debugging process. Is this something that I could hook into MSBuild for? I imagine others are going to face the same question as they upgrade.
Thanks for any suggestions.
So, I was using UseWebpackDevMiddleware for HMR for a much smoother dev process - In the end I reverted to using webpack-dev-server
Steps:
1) Add package to package.json: "webpack-dev-server": "3.8.2",
2) Add webpack.development.js
const merge = require('webpack-merge');
const common = require('./webpack.config.js');
const ExtractCssPlugin = require('mini-css-extract-plugin');
const webpackDevServerPort = 8083;
const proxyTarget = "http://localhost:8492";
module.exports = merge(common(), {
output: {
filename: "[name].js",
publicPath: '/dist/'
},
mode: 'development',
devtool: 'inline-source-map',
devServer: {
compress: true,
proxy: {
'*': {
target: proxyTarget
}
},
port: webpackDevServerPort
},
plugins: [
new ExtractCssPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
});
Note that the proxy setting here will be used to proxy through to ASP.Net core for API calls
Modify launchSettings.json to point to webpack-dev-server:
"profiles": {
"VisualStudio: Connect to HotDev proxy": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "http://localhost:8083/",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:8492/"
}
}
(also I had some problem with configuring the right locations in webpack, and found this useful
Also, will need to start webpack-dev-server which can be done via a npm script:
"scripts": {
"build:hotdev": "webpack-dev-server --config webpack.development.js --hot --inline",
And then this is bootstrapped
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "build:hotdev");
}
});
(or you can install the npm task runner extension and:
"-vs-binding": {
"ProjectOpened": [
"build:hotdev"
]
}
Alternatively I realise you can proxy the other way using the following - this way any request to under "dist" will be pushed through to the proxy webpack-dev-server
app.UseSpa(spa =>
{
spa.Options.SourcePath = "dist";
if (env.IsDevelopment())
{
// Ensure that you start webpack-dev-server - run "build:hotdev" npm script
// Also if you install the npm task runner extension then the webpack-dev-server script will run when the solution loads
spa.UseProxyToSpaDevelopmentServer("http://localhost:8083");
}
});
And then you don't need to proxy though from that back any more and can just serve /dist/ content
- both hot and vendor-precompiled using as web.config.js like this:
module.exports = merge(common(), {
output: {
filename: "[name].js",
publicPath: '/dist/',
},
mode: 'development',
devtool: 'inline-source-map',
devServer: {
compress: true,
port: 8083,
contentBase: path.resolve(__dirname,"wwwroot"),
},
plugins: [
new ExtractCssPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
});
In my opinion, Kram's answer should be marked as accepted as it really gives what's needed. I've spent some time setting up a .NET Core/React/Webpack project recently, and I could not get the spa.UseReactDevelopmentServer to work, but the spa.UseProxyToSpaDevelopmentServer works like a charm. Thanks Kram!
Here are my few gotchas they might help someone:
webpack.config.js (excerpt):
const path = require('path');
const webpack = require('webpack');
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'build.[hash].js',
},
devServer: {
contentBase: path.resolve(__dirname, 'public'),
publicPath: '/dist',
open: false,
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
DevServer sets its root by publicPath property and completely ignores the output.path property in the root. So even though your output files (for prod) will go to dist folder, under webpack server they will be served under a root by default. If you want to preserve the same url, you have to set publicPath: '/dist'.
This means that your default page will be under http://localhost:8083/dist. I could not figure out a way to place assets under subfolder while keeping index in the root (other than hardcode the path for assets).
You need HotModuleReplacementPlugin in order to watch mode to work and also hot: true setting in the devServer configuration (or pass it as a parameter upon start).
If you (like me) copy some dev server configuration with open: true (default is false), you will finish up with two browsers opened upon application start as another one is opened by the launchSettings "launchBrowser": true. It was a bit of a surprise at the first moment.
Also, you will have to enable CORS for your project otherwise your backend calls will get blocked:
Startup.cs (excerpt):
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: "developOrigins",
builder =>
{
builder.WithOrigins("http://localhost:8083");
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
app.UseCors("developOrigins");
}
If anything else will come to my mind I will update the answer, hope this helps to someone.
Webpack 5 update
webpack-dev-server command doesn't work anymore. Use:
"build:hotdev": webpack serve --config webpack.config.development.js
You might also need to add target: 'web' to your webpack.config.js in Webpack 5 to enable hot module reload to work:
module.exports = {
target: 'web'
}
Alternatively you might need to create a browserlist file. Hope this issue gets fixed soon.
You mention VS. My solution is good for Visual Studio, but not VS Code.
I use WebPack Task Runner: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.WebPackTaskRunner
This adds webpack.config.js tasks into the "Task Runner Explorer" in Visual Studio, and you can then bind those tasks to events like "Before Build" or "After Build"
Extension is here : AspNetCore.SpaServices.Extensions
You could find examples here : https://github.com/RimuTec/AspNetCore.SpaServices.Extensions
With core 3.1 or 5.0
React with webpack
using :spaBuilder.UseWebpackDevelopmentServer(npmScriptName: "start");

Resources