How to enable NextJS "next/future/image"? - next.js

I'm trying to use Next.js next/future/image experimental component.
I upgraded the Next.js version in package.json to "next": "^12.2.0".
Here's my next.config.js file:
/** #type {import('next').NextConfig} */
const nextConfig = {
strictMode: true,
experimental: {
images: {
allowFutureImage: true,
},
},
images: {
domains: ['firebasestorage.googleapis.com',],
},
};
module.exports = nextConfig;
It doesn't allow me to use this feature. Here's the error message in the browser console:
Error: The "next/future/image" component is experimental and may be subject to breaking changes. To enable this experiment, please include `experimental: { images: { allowFutureImage: true } }` in your next.config.js file.

For Next v13 users:
I believe next/future/image is now the default Image component. So no additional work necessary! Just import and use
import Image from 'next/image'
For Next v12.3 users(like the author of this question)
You don't need to add anything to the config to use future/image. The future image is now stable. Just use it directly by importing
import Image from 'next/future/image'
In fact, adding an images property to the config will cause an error, since the config schema has been updated. So don't do that.
// next.config.js
module.exports = {
experimental: {
images: { // This will cause an error
allowFutureImage: true,
},
},
}

The solution that worked for me was to add the experimental rule and stop the nextjs server and restart it. Then it would start working
module.exports = {
experimental: {
images: {
allowFutureImage: true,
},
},
}

I'm currently working with NextJS version 12.3.1, and if I enable it in the next.config.js then I get an ugly warning on the terminal. So it is best to just import Image from "next/future/image" and not add the config to avoid the Warning. Hope others using 12.3.1 find this useful ( using future/image gets rid of the nasty wrapper divs/spans around the )
Warning I'm seeing with config in place:
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
warn - Invalid next.config.js options detected:
- The value at .experimental has an unexpected property, images, which is not in the list of allowed properties (adjustFontFallbacks, amp, appDir, browsersListForSwc, cpus, craCompat, disableOptimizedLoading, disablePostcssPresetEnv, esmExternals, externalDir, fallbackNodePolyfills, forceSwcTransforms, fullySpecified, gzipSize, incrementalCacheHandlerPath, isrFlushToDisk, isrMemoryCacheSize, largePageDataBytes, legacyBrowsers, manualClientBasePath, modularizeImports, newNextLinkBehavior, nextScriptWorkers, optimizeCss, optimisticClientCache, outputFileTracingRoot, pageEnv, profiling, proxyTimeout, runtime, scrollRestoration, serverComponents, sharedPool, sri, swcFileReading, swcMinify, swcMinifyDebugOptions, swcPlugins, swcTraceProfiling, urlImports, workerThreads).
See more info here: https://nextjs.org/docs/messages/invalid-next-config
warn - You have enabled experimental feature (images) in next.config.js.
warn - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk.

Related

NextJS images are not shown using "export" script

I have a simple NextJs app.
When I'm running the app on a localhost everything seems to work fine - All the images are shown as expected
When I use this script: next build && next export
and browse to my local build, I don't see the images, but instead its "alt" text
The way I import an image:
import React from 'react';
import Image from 'next/image';
import someImage from '../../../public/images/some-image.png';
const Main = () => {
return (
<div>
<Image
src={someImage}
alt="Some Image"
placeholder="blur"
/>
</div>
}
next.config.js
/** #type {import('next').NextConfig} */
const configuration = {
reactStrictMode: true,
eslint: {
dirs: ['./src'],
ignoreDuringBuilds: true,
},
images: {
loader: 'akamai',
path: '',
},
};
module.exports = configuration;
My code design:
Environment:
"next": "13.1.6",
"react": "18.2.0",
Moreover, I tried to use a normal img tag and it causes the same problem.
If anyone here faces the same issue ill appreciate any help!
Refer to this page:
https://nextjs.org/docs/messages/export-image-api
You are attempting to run next export while importing the next/image component using the default loader configuration.
However, the default loader relies on the Image Optimization API which is not available for exported applications.
So, when running static NextJS app with export you cannot use NextJS optimization, as it should run in your non-existent server. You should use cloud solution (https://nextjs.org/docs/api-reference/next/image#loader-configuration) or remove optimization:
module.exports = {
images: {
unoptimized: true,
},
}
(https://nextjs.org/docs/api-reference/next/image#unoptimized)
When importing something statically from the public folder it already knows youre inside it. You only need the following import:
import someImage from 'images/some-image.png';

how can i use styled-component and local font in next js?

i am using styled-component in my next js app.
and for using it i had to add a babel file with this code:
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}
i want to use local font and i did it according to the document https://nextjs.org/docs/basic-features/font-optimization.
but problem is here that after using local font the app errors.
it errors that you have to use initial babel.
how can i use both styled-component and local font?
With the release of Next.js 12 you can use styled-components without additional plugins.
Just add styledComponents: true in your next.config.js
const nextConfig = {
...rest of your config,
compiler: {
styledComponents: true,
},
};
module.exports = nextConfig;
A related issue on GitHub

Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected

I am trying to import "../../node_modules/react-quill/dist/quill.snow.css"; in my next.js project but I get following error
[ error ] ./node_modules/react-quill/dist/quill.snow.css
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.js.
Read more: https://err.sh/next.js/css-global
Location: components\crud\BlogCreate.js
I managed to make it work with next.config.js. It worked with this configuration
// next.config.js
const withCSS = require('#zeit/next-css');
module.exports = withCSS({
cssLoaderOptions: {
url: false
}
});
But now I am getting a warning,
Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected.
See here for more info: https://err.sh/next.js/built-in-css-disabled
It seems my solution is not the best way to solve this problem. How could I get rid of this warning?
You may remove the #zeit/next-css plugin because the Next.js 9.3 is very simple. Then Next.js 9.3 is Built-in Sass Support for Global Stylesheets after removing the #zeit/next-css you may install
npm install sass
Then, import the Sass file within pages/_app.js.
Global CSS
Import any global CSS in the /pages/_app.js.
import '../styles.css'
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
Importing CSS in components or pages won't work with the built-in CSS support.
Component CSS
Next.js supports CSS Modules using the [name].module.css file naming convention.
components/Button.module.css
/*
You do not need to worry about .error {} colliding with any other `.css` or
`.module.css` files!
*/
.error {
color: white;
background-color: red;
}
components/Button.js
import styles from './Button.module.css'
export function Button() {
return (
<button
type="button"
// Note how the "error" class is accessed as a property on the imported
// `styles` object.
className={styles.error}
>
Destroy
</button>
)
}
CSS Module files can be imported anywhere in your application.
Third-party CSS on Component / Page level
You can use <link> tag in the component.
const Foo = () => (
<div>
<link
href="third.party.css"
rel="stylesheet"
/>
</div>
);
export default Foo;
The loaded stylesheet won't be automatically minified as it doesn't go through build process, so use the minified version.
If none of the options doesn't fit your requirements consider using a custom CSS loader like #zeit/next-css.
In that case you will see a warning which is fine:
Warning: Built-in CSS support is being disabled due to custom CSS configuration being detected.
See here for more info: https://err.sh/next.js/built-in-css-disabled
Suggested reading:
Next.js Built-In CSS Support
Global SASS
CSS Modules
Install sass module by running following command.
npm install sass
You then need to remove all css-loader and sass-loader configuration from next.config.js.
For example, I had to remove the withSass() function (in your case withCSS()) and just return the configuration object.
Had to remove the following lines from next.config.js
{
test: /\.scss$/,
use: {
loader: "sass-loader",
options: {
data: '#import "./scss/_variables.scss"',
sourceMap: true,
},
},
}
Move your options to sassOptions in next config file.
sassOptions: {
data: '#import "./scss/_variables.scss"',
sourceMap: true,
}
Also remove the old #zeit/next-sass and #zeit/next-css from package.json
I had to remove following #zeit dependency from my package.json
"dependencies": {
"#zeit/next-sass": "1.0.1",
This worked for me.
For more details, visit https://nextjs.org/docs/basic-features/built-in-css-support

How does NuxtJS css extraction work for generated static websites?

I am trying to generate a static website out of my (minimal) code with Nuxt. In that code, I integrate in particular the tailwindcss toolkit as well as vue2-leaflet. Upon
nuxt generate
I get two css files, one for the tailwindcss css and the other for the leaflet css. While the former file is fine and contains everything I need, the latter is pretty sparse:
.leaflet-tile-pane{z-index:200}#-webkit-keyframes leaflet-gestures-fadein{to{opacity:1}}#keyframes leaflet-gestures-fadein{0%{opacity:0}to{opacity:1}}
Of course, that makes my map render in a pretty strange way, because most of the css is missing. Here's my current nuxt.config.js:
module.exports = {
mode: 'universal',
head: {
title: pkg.name,
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
css: [
],
plugins: [
{ src: '~plugins/leaflet.js', mode: 'client' }
],
buildModules: [
'#nuxtjs/tailwindcss'
],
modules: ['#nuxtjs/apollo', 'nuxt-purgecss', ['nuxt-i18n', i18n]],
[...]
build: {
extractCSS: true,
}
}
Getting rid of the extractCSS ends up incorporating all the relevant css into the index.html. It works, but then I get the following error:
ERROR Webpack mode only works with build.extractCSS set to *true*. Either extract your CSS or use 'postcss' mode
I'm not sure I understand how that whole css extraction works. Could someone enlighten me? Why is it not working with extractCSS: true? How can I make it work? Why is it working in SPA mode but not in static mode?
You are using nuxt-purgecss which is using purgecss to strip unused CSS.
purgecss do scan HTML (or vue) files for CSS classes in use and then strip unused classes from final CSS bundle.
You can take a look at default purgecss configuration used by nuxt-purgecss here. The paths lists the paths purgecss will scan for CSS usage.
Because you are not using most of the leaflet css directly (in your components), its is necessary to configure purgecss to don't remove leaflet's css.
You can do that by whitelisting (btw not sure if "comment" method will work in Vue\Nuxt)
You can read more here and here
Not tested!!
// nuxt.config.js
{
purgeCSS: {
whitelistPatterns: [/leaflet/, /marker/]
}
}
Regarding the error message
Error message is from nuxt-purgecss module - it is clearly documented here
I don't have deep knowledge of Nuxt build process. So I just assume from the docs that extractCSS: true will use extract-css-chunks-webpack-plugin to extract all CSS to separate CSS file, while (default) extractCSS: false will use PostCSS to extract all CSS and put it directly into the <style> tag of rendered page.
All of that doesn't matter IMHO because the root problem is the use of purgecss and the solution is to configure it correctly to whitelist leaflet CSS classes....

Styling not applied to vue web component during development

While developing a Vue web component, the style is not applied to the web component, but added to the head of the document. This means that the style is ignored in the shadow DOM. Here is how I wrap the web component in main.js:
import Vue from 'vue';
import wrap from '#vue/web-component-wrapper';
import MyWebComponent from './components/MyWebComponent';
const WrappedElement = wrap(Vue, MyWebComponent);
window.customElements.define('my-web-component', WrappedElement);
Again, any CSS rules inside the style tags do not take effect.
When I build for production, the styles are added to the web component. I use the following command to do the wrapping:
vue-cli-service build --target wc --name my-web-component ./src/components/MyWebComponent.vue
Is there a way to achieve the same thing with vue-cli-service serve?
edit: example repo here: https://github.com/snirp/vue-web-component
edit2: I have the feeling my problem is closely related to this issue. I cannot make much sense of the workarounds, and I would value a more basic solution.
Based on the GitHub issue you linked, the solution is to set the shadowMode option in vue-loader and vue-style-loader. shadowMode is false by default in a Vue CLI project, but we can tweak that in vue.config.js.
First, we'd inspect the Webpack config to determine which loaders to change:
# run at project root
vue inspect
The command output reveals several loader configs with shadowMode: false:
/* config.module.rule('css') */
{
test: /\.css$/,
oneOf: [
/* config.module.rule('css').oneOf('vue-modules') */
{
resourceQuery: /module/,
use: [
/* config.module.rule('css').oneOf('vue-modules').use('vue-style-loader') */
{
loader: 'vue-style-loader',
options: {
sourceMap: false,
shadowMode: false // <---
}
},
/* ... */
]
},
/* ... */
full list of Webpack loader configs with shadowMode: false:
config.module.rule('vue').use('vue-loader')
config.module.rule('css').oneOf('vue-modules').use('vue-style-loader')
config.module.rule('css').oneOf('vue').use('vue-style-loader')
config.module.rule('css').oneOf('normal-modules').use('vue-style-loader')
config.module.rule('css').oneOf('normal').use('vue-style-loader')
config.module.rule('postcss').oneOf('vue-modules').use('vue-style-loader')
config.module.rule('postcss').oneOf('vue').use('vue-style-loader')
config.module.rule('postcss').oneOf('normal-modules').use('vue-style-loader')
config.module.rule('postcss').oneOf('normal').use('vue-style-loader')
config.module.rule('scss').oneOf('vue-modules').use('vue-style-loader')
config.module.rule('scss').oneOf('vue').use('vue-style-loader')
config.module.rule('scss').oneOf('normal-modules').use('vue-style-loader')
config.module.rule('scss').oneOf('normal').use('vue-style-loader')
config.module.rule('sass').oneOf('vue-modules').use('vue-style-loader')
config.module.rule('sass').oneOf('vue').use('vue-style-loader')
config.module.rule('sass').oneOf('normal-modules').use('vue-style-loader')
config.module.rule('sass').oneOf('normal').use('vue-style-loader')
config.module.rule('less').oneOf('vue-modules').use('vue-style-loader')
config.module.rule('less').oneOf('vue').use('vue-style-loader')
config.module.rule('less').oneOf('normal-modules').use('vue-style-loader')
config.module.rule('less').oneOf('normal').use('vue-style-loader')
config.module.rule('stylus').oneOf('vue-modules').use('vue-style-loader')
config.module.rule('stylus').oneOf('vue').use('vue-style-loader')
config.module.rule('stylus').oneOf('normal-modules').use('vue-style-loader')
config.module.rule('stylus').oneOf('normal').use('vue-style-loader')
So, we can set shadowMode: true for those configs in vue.config.js with this snippet:
function enableShadowCss(config) {
const configs = [
config.module.rule('vue').use('vue-loader'),
config.module.rule('css').oneOf('vue-modules').use('vue-style-loader'),
config.module.rule('css').oneOf('vue').use('vue-style-loader'),
config.module.rule('css').oneOf('normal-modules').use('vue-style-loader'),
config.module.rule('css').oneOf('normal').use('vue-style-loader'),
config.module.rule('postcss').oneOf('vue-modules').use('vue-style-loader'),
config.module.rule('postcss').oneOf('vue').use('vue-style-loader'),
config.module.rule('postcss').oneOf('normal-modules').use('vue-style-loader'),
config.module.rule('postcss').oneOf('normal').use('vue-style-loader'),
config.module.rule('scss').oneOf('vue-modules').use('vue-style-loader'),
config.module.rule('scss').oneOf('vue').use('vue-style-loader'),
config.module.rule('scss').oneOf('normal-modules').use('vue-style-loader'),
config.module.rule('scss').oneOf('normal').use('vue-style-loader'),
config.module.rule('sass').oneOf('vue-modules').use('vue-style-loader'),
config.module.rule('sass').oneOf('vue').use('vue-style-loader'),
config.module.rule('sass').oneOf('normal-modules').use('vue-style-loader'),
config.module.rule('sass').oneOf('normal').use('vue-style-loader'),
config.module.rule('less').oneOf('vue-modules').use('vue-style-loader'),
config.module.rule('less').oneOf('vue').use('vue-style-loader'),
config.module.rule('less').oneOf('normal-modules').use('vue-style-loader'),
config.module.rule('less').oneOf('normal').use('vue-style-loader'),
config.module.rule('stylus').oneOf('vue-modules').use('vue-style-loader'),
config.module.rule('stylus').oneOf('vue').use('vue-style-loader'),
config.module.rule('stylus').oneOf('normal-modules').use('vue-style-loader'),
config.module.rule('stylus').oneOf('normal').use('vue-style-loader'),
];
configs.forEach(c => c.tap(options => {
options.shadowMode = true;
return options;
}));
}
module.exports = {
// https://cli.vuejs.org/guide/webpack.html#chaining-advanced
chainWebpack: config => {
enableShadowCss(config);
}
}
Creating <projectroot>/vue.config.js with the snippet above enables Shadow CSS in development mode in your project. See https://github.com/snirp/vue-web-component/pull/1.

Resources