This question already has answers here:
how to add domains to next.config.js for "next/image" while using a plugin
(2 answers)
Closed 10 months ago.
I'm having an issue with next.config.js. I'm currently running a project with next js on typescript. In this project i am working with ThreeJs, #react-three/fiber & #react-three/drei. But I also want to include some images from a specific public YouTube url.
In older projects i have implemented this withought having ThreeJs inside like this:
module.exports = {
reactStrictMode: true,
images: {
domains: ['i3.ytimg.com', 'img.youtube.com'],
formats: ['image/webp'],
},
}
That being on my next.config.js and it still works like a charm. But when I put it in my current project and try to load an image I get error saying:
Error: Invalid src prop ([url]) on next/image, hostname "img.youtube.com" is not configured under images in your next.config.js
Current next.config.js file
module.exports = {
reactStrictMode: true,
images: {
domains: ['i3.ytimg.com', 'img.youtube.com'],
formats: ['image/webp'],
},
}
const withTM = require('next-transpile-modules')(['three', '#react-three/fiber', '#react-three/drei']);
module.exports = withTM();
On my component now:
export default function ProjectCard({ song }: { song: Lyrics }) {
const img = hqDefault(song.thumbnailURL);
return (
<div>
{song.singer}
<Image src={img} alt={`${song.singer} ${song.title}`} layout="fill" />
</div>
)
}
hqDefault Function:
export const hqDefault = (url: string): string => {
return `https://img.youtube.com/vi/${url}/hqdefault.jpg`;
}
Any help will be appriciated!
You are supposed to export a single configuration object.
First, Install 'next-compose-plugins':
npm install --save next-compose-plugins
Import it:
const withPlugins = require('next-compose-plugins');
And then export your config like this:
module.exports = withPlugins([
[withTM]
], nextConfig);
Related
Hey I am playing around with web3 inside react as a client application (using vite react-ts) and trying to call web3.eth.net.getId() but this will throw me an error that callbackify is not a function I digged a little and found an old issue on the github which states that older versions of Nodejs.util (prior version 0.11) didn't have this function. So I checked the package.json where the error occurs (web3-core-requestmanager) it has "util":"^0.12.0", so callbackify should be available.
In fact when I am looking at their imports, they seem to be able to import it:
(following code is ./node_modules\web3-core-requestmanager\src\index.js
const { callbackify } = require('util');
but when they want to use it, callbackify is undefined
//RequestManager.prototype.send function
const callbackRequest = callbackify(this.provider.request.bind(this.provider));
I tried to play around with the dependencies and tried different versions of web3.js (1.7.3; 1.6.0; 1.5.1) all of them had the same util dependency (0.12.0).
My code in all this matter looks like this:
class Blockchain {
public blockchainBaseUrl: string;
public web3;
public provider;
public account: string = '';
public contract: any;
constructor() {
if (process.env.REACT_APP_BLOCKCHAIN_BASE_URL === undefined) {
throw new Error('REACT_APP_BLOCKCHAIN_BASE_URL is not defined');
}
this.provider = window.ethereum;
if (this.provider === undefined) {
throw new Error('MetaMask is not installed');
}
this.setUpInitialAccount();
this.addEthereumEventListener();
this.blockchainBaseUrl = process.env.REACT_APP_BLOCKCHAIN_BASE_URL;
this.web3 = new Web3(Web3.givenProvider || this.blockchainBaseUrl);
this.setContract();
}
async setContract() {
// error comes from the next line
const networkId = await this.web3.eth.net.getId();
this.contract = new this.web3.eth.Contract(
// #ts-ignore
Token.abi,
// #ts-ignore
Token.networks[networkId].address
);
}
}
I also was told that I should simply add a .catch() to web3.eth.net.getId() but this did nothing. Am I doing something wrong or is this a dependency problem? If anyone could point me in the right direction I would really appreciate it. Do I need to expose the util API to the browser somehow? To me, it seems that the API is simply not available.
This is should be the relevant part of my vite.config.ts:
import GlobalsPolyfills from '#esbuild-plugins/node-globals-polyfill';
import NodeModulesPolyfills from '#esbuild-plugins/node-modules-polyfill';
import { defineConfig } from 'vite';
import react from '#vitejs/plugin-react';
export default defineConfig({
plugins: [
react(),
],
optimizeDeps: {
esbuildOptions: {
plugins: [
NodeModulesPolyfills(),
GlobalsPolyfills({
process: true,
buffer: true,
}),
],
define: {
global: 'globalThis',
},
},
},
});
Here is my complete vite config
https://pastebin.com/zvgbNbhQ
Update
By now I think that I understand the issue - it seems that it is a VIte-specific problem and I need to polyfill the NodeJs.util API. I am already doing this (at least I thought). Perhaps someone can provide some guidance on what I am doing wrong with my config?
Update 2
I actually have now the util API inside the browser, but it is still giving me the same error. This is my new config:
https://pastebin.com/mreVbzUW I can even log it out:
Update 3
SO I am still facing this issue - I tried a different approach to polyfill I posted the update to the github issue https://github.com/ChainSafe/web3.js/issues/4992#issuecomment-1117894830
Had similar problem with vue3 + vite + we3
It's started from errors: process in not defined than Buffer is not defined and finally after I configure polyfill I came to callbackify is not defined
Did a lot of researches and finally solved this issue with next trick:
Rollback all polyfill configurations
Add to the head html file
<script>window.global = window;</script>
<script type="module">
import process from "process";
import { Buffer } from "buffer";
import EventEmitter from "events";
window.Buffer = Buffer;
window.process = process;
window.EventEmitter = EventEmitter;
</script>
vite.config.ts
import vue from '#vitejs/plugin-vue'
export default {
resolve: {
alias: {
process: "process/browser",
stream: "stream-browserify",
zlib: "browserify-zlib",
util: 'util'
}
},
plugins: [
vue(),
]
}
add these dependencies browserify-zlib, events, process, stream-browserify, util
Source https://github.com/vitejs/vite/issues/3817#issuecomment-864450199
Hope it will helps you
I have a react app where I wanted to import a javascript file from a third-party library but file is mark with shebang #!/usr/bin/env node.
I found (e.g. here How to Configure Webpack with Shebang Loader to Ignore Hashbang Importing Cesium React Component into Typescript React Component) I can load file by overriding webpack configuration and adding a new loader shebang-loader (I also have tried shebang-loader2) but overriding webpack in react app is recommended only with #craco/craco so I added it to package.json and tried add loader to existing webpack-config.js.
I produced this lines of code. File craco.config.js:
const throwError = (message) =>
throwUnexpectedConfigError({
packageName: 'craco',
githubRepo: 'gsoft-inc/craco',
message,
githubIssueQuery: 'webpack',
});
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
const shebangLoader = { test: /node_modules\/npm-groovy-lint\/lib\/groovy-lint.js$/, loader: "shebang-loader" }
const {isAdded: shebangLoaderIsAdded1} = addAfterLoader(webpackConfig, loaderByName('url-loader'), shebangLoader);
if (!shebangLoaderIsAdded1) throwError('failed to add shebang-loader');
return webpackConfig;
},
},
};
It resolves problem with shebang and it ignores #!/usr/bin/env node but now I still get error
Module parse failed: Unexpected token (14:16)
File was processed with these loaders:
* ./node_modules/shebang2-loader/index.js
You may need an additional loader to handle the result of these loaders.
| const { getSourceLines, isErrorInLogLevelScope } = require("./utils");
| class NpmGroovyLint {
> "use strict";
| options = {}; // NpmGroovyLint options
| args = []; // Command line arguments
It looks like it does not recognise "use strict" line.
Can anyone put some suggestions what should be a problem ?
After few hours of investigation, I have finally come to a resolution. Firstly I have to say that there is no option to use NpmGroovyLint in react-like applications that run in browsers because after I resolved mentioned problem up here I figured that NpmGroovyLint uses node libraries as perf_hooks which are not available in a browser enviroment.
But I can post code that resolves the problem described in my question. It was needed to add a plugin to babel-loader named 'plugin-proposal-class-properties'. Here is my snipped of craco config. You can use it as a recipe occasionally.
const {addAfterLoader, getLoaders, loaderByName, removeLoaders, throwUnexpectedConfigError} = require('#craco/craco');
const throwError = (message) =>
throwUnexpectedConfigError({
packageName: 'craco',
githubRepo: 'gsoft-inc/craco',
message,
githubIssueQuery: 'webpack',
});
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
const {hasFoundAny, matches} = getLoaders(webpackConfig, loaderByName('babel-loader'));
if (!hasFoundAny) throwError('failed to find babel-loader');
const {hasRemovedAny, removedCount} = removeLoaders(webpackConfig, loaderByName('babel-loader'));
if (!hasRemovedAny) throwError('no babel-loader to remove');
if (removedCount !== 2) throwError('had expected to remove 2 babel loader instances');
//add plugin proposal class properties to existing babel loader
const propClassOptions = {...matches[1].loader.options, ...{plugins: ["#babel/plugin-proposal-class-properties"]}};
const propClassLoader = {...matches[1].loader, ...{options: propClassOptions}};
const babelLoaderWithPropClassPlugin = {...matches[1], ...{loader: propClassLoader}};
const shebangLoader = {
test: /node_modules\/npm-groovy-lint\/lib\/groovy-lint.js$/,
use: [{loader: 'shebang2-loader'}, {...{loader: require.resolve('babel-loader')}, ...{options: propClassOptions}}]
}
const {isAdded: babelLoaderWithPropClassIsAdded} = addAfterLoader(webpackConfig, loaderByName('url-loader'), matches[0].loader);
if (!babelLoaderWithPropClassIsAdded) throwError('failed to add ts-loader');
const {isAdded: babelLoaderIsAdded} = addAfterLoader(webpackConfig, loaderByName('babel-loader'), babelLoaderWithPropClassPlugin.loader);
if (!babelLoaderIsAdded) throwError('failed to add back babel-loader for non-application JS');
const {isAdded: shebangLoaderIsAdded1} = addAfterLoader(webpackConfig, loaderByName('url-loader'), shebangLoader);
if (!shebangLoaderIsAdded1) throwError('failed to add shebang-loader');
return webpackConfig;
},
},
};
I'm trying to prepare my portfolio website with Nextjs. I want to use gif in the site. You can find my code below. I could not find how to do it.
Next/Image does support GIF files...my first thought would be to ask if you have explicitly whitelisted a set of external domains in your next.config.js file? For the Next/Image Loader to handle external domains they must be individually whitelisted. Here are the contents of my next.config.js file.
const path = require('path');
const withBundleAnalyzer = require('#next/bundle-analyzer')({
enabled: !!process.env.ANALYZE
});
module.exports = withBundleAnalyzer({
webpack(
config,
{
dev = process.env.NODE_ENV === 'development',
isServer = typeof window === 'undefined'
}
) {
if (isServer) {
require('./scripts/generate-sitemap');
}
/**
* !dev ? preact/compat : react, react-dom on build
* reduce page weight in production by ~10%
*/
if (!dev && !isServer) {
Object.assign(
(config.resolve.alias['#/'] = path.resolve('./')),
{
react: 'preact/compat',
'react-dom': 'preact/compat'
}
);
}
return config;
},
sourceMaps: {
productionBrowserSourceMaps: true
},
images: {
domains: [
'avatars.githubusercontent.com',
'faderoom-headless.us',
'www.faderoom-headless.us',
'dtmqnbkq3btfh.cloudfront.net',
'secure.gravatar.com',
'automattic.com',
'serve.onegraph.com',
'onegraph.com',
'maps.google.com',
'lh3.googleusercontent.com',
'maps.gstatic.com',
'thefaderoom146.booksy.com',
'dev-3cqt2bq0.auth0.com',
'scontent-sea1-1.xx.fbcdn.net',
'd2zdpiztbgorvt.cloudfront.net',
'platform-lookaside.fbsbx.com',
'square-postoffice-production.s3.amazonaws.com'
]
},
future: {
webpack5: true,
strictPostcssConfiguration: true
},
i18n: {
locales: ['en-US'],
defaultLocale: 'en-US'
}
});
console.log(
'next.config.js',
JSON.stringify(module.exports, null, 2)
);
So you would have to whitelist media.giphy.com and it should work just fine. I also do recommend setting the quality prop for the Image component. Quality defaults to 75 out of 100 but I'd suggest making that closer to 100 for better UX.
Next/Image now supports gifs.
You should be able to import the gif and then toss it into the src like this
import Image from 'next/image';
import myGif from 'url'
...
<Image src={myGif} alt="my gif" height={500} width={500} />
If the url doesn't work here, it should work if you download the gif and toss it into assets.
At first I entered your code:
Your code
and nextjs gave me this as an error:
Screenshot erreur
So I added the domain 'media.giphy.com' in the configuration 'next.config.js'
This file must be added to the root of the project, at the same level as the 'pages' or 'lib' folder for example and must be called 'next.config.js':
File place screenshot
And in it you have to put this:
module.exports = {
images: {
domains: ['media.giphy.com']
}
};
Then you have to restart your next js server.
And normally you get this:
Image Screenshot
Here is some documentation to read to better understand:
https://nextjs.org/docs/basic-features/image-optimization
You can also use the prop unoptimized to serve the image as it is:
make sure you white list your domain in the next.config.js
module.exports = {
images: {
domains: ['SOURCE_IMAGE_DOMAIN']
}
};
then in your image component:
import Image from 'next/image';
<Image unoptimized={true} src={GIF} alt="the gif" height={500} width={500} />
Next documentation:
https://nextjs.org/docs/api-reference/next/image#animated-images
I'm trying to use Nuxt JS's 2.9.2 generate object to generate dynamic pages as static files using my .env file to pull a URL, I'm having difficuility in getting it to properly link up:
nuxt.config.js
require('dotenv').config();
import pkg from './package'
import axios from 'axios'
export default {
mode: 'universal',
env: {
blog_api: process.env.BLOG_API || "http://localhost:3000/articles/blogs.json"
},
/*
** Build directory
*/
generate: {
dir: 'dist-next',
routes: function () {
return axios.get(`${process.env.blog_api}`)
.then((res) => {
return res.data.blogs.map((blog) => {
return '/posts/view/' + blog.title
})
})
}
}
}
The above code, more specifically ${process.env.blog_api}, can't seem to resolve the routes, despite it working perfectly if I replace it with my own local domain.
.env
BLOG_API="http://my-local-domain.clone/articles/blogs.json"
EDIT:
Updated code with my config, http://my-local-domain.clone/articles/blogs.json is inside of static/articles
You should use dotenv module:
https://www.npmjs.com/package/dotenv
More Info about configuration with NUXT you have here:
https://samuelcoe.com/blog/nuxt-dotenv/
You probably want to set your env property in nuxt.config.js, for example:
module.exports = {
env: {
BLOG_API: process.env.BLOG_API_URL,
},
In your component, you can now use them :
makeAsyncCall({
to: process.env.BLOG_API,
})
I'm creating an application based on gatsby framework, but I have problem with initialize gatsby theme. From official documentation:
https://www.gatsbyjs.org/tutorial/part-three/
import Typography from 'typography';
import fairyGateTheme from 'typography-theme-github';
const typography = new Typography(fairyGateTheme);
export const { scale, rhythm, options } = typography;
export default typography;
But typography-theme-github import has dotted underline when I hovered mouse on it I have got this tip:
Could not find a declaration file for module 'typography-theme-github'. '/Users/jozefrzadkosz/Desktop/hello-world/node_modules/typography-theme-github/dist/index.js' implicitly has an 'any' type.
Try npm install #types/typography-theme-github if it exists or add a new declaration (.d.ts) file containing declare module 'typography-theme-github';ts(7016)
When I run gatsby develop I'm getting this error:
Error: Unable to find plugin "undefined". Perhaps you nee d to install its package?
EDIT
I have looked on this file node_modules/typography-theme-github/dist/index.js and I found one similar issue:
var _grayPercentage = require("gray-percentage");
This require has exactly same tip as my theme import.
SECOND EDIT
Gatsby.config.js
module.exports = {
plugins: [
[`gatsby-plugin-sass`],
{
resolve: `gatsby-plugin-typography`,
options: {
pathToConfigModule: `src/utils/typography`
}
}
]
};
I notice you placed gatsby-plugin-sass in an array, which is why gatsby didn't recognize it:
module.exports = {
plugins: [
- [`gatsby-plugin-sass`], <-- error
+ `gatsby-plugin-sass`,
{
resolve: `gatsby-plugin-typography`,
options: {
pathToConfigModule: `src/utils/typography`
}
}
]
};
This is probably not a problem with gatsby-plugin-typography.