Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't import static files like images #1935

Closed
laoqiren opened this issue May 10, 2017 · 51 comments
Closed

Can't import static files like images #1935

laoqiren opened this issue May 10, 2017 · 51 comments

Comments

@laoqiren
Copy link

version: v2.1.1

additional webpack config to next.config.js:

config.module.rules.push(
        {test: /\.(png|jpeg)$/, loader: 'url-loader?limit=8192'}
    )

then in my component:
import image from '../static/enen.png'

it comes the error:

This module was not found:

* /static/enen.png in ./pages?entry

To install it, you can run: npm install --save /static/enen.png
{ Error: Cannot find module '/static/enen.png'
...

I have tried to change the url as '/static/enen.png' , and in the css-in-jsx:

p {
  background-image: url('../static/enen.png')
}
//or
p {
   background-image: $(require('../static/enen.png'))
}

all above comes the same error: can't find the module, I can get it using <img src="../static/enen.png"/>

hope your help.

@lededje
Copy link

lededje commented May 11, 2017

Images by default are not accessible via import. You would need to modify the babelrc to allow for this. What data are you expecting to get returned from importing an image like that? a base64 encoded version of it? A browser resolvable path to it?

@laoqiren
Copy link
Author

laoqiren commented May 11, 2017

@lededje thanks for reply. so how to config this ? I havn't find this in the document. I'd appreciate it if you can give me an example ( base64 & resolvable path)

@paulobarcelos
Copy link

I would also like to know that. It seems the next team has strong opinions about using webpack for processing images, but it seems very limiting that you can't do it if you want to...

@jpsc
Copy link
Contributor

jpsc commented May 17, 2017

If you add the image to the /static/ and then add the <img src="/static/image.png"/>?
There is no need to load the image via the import.

@laoqiren
Copy link
Author

@jpsc But this doens't work in css using styled-jsx.

@arunoda
Copy link
Contributor

arunoda commented May 18, 2017

@paulobarcelos it's not a strong opinion. With our SSR setup, it's kind a hard to it. (Since we don't run webpack in the server)
It's doable, but we've much important other stuff to do.

@laoqiren why it's not working simply use the image path like this:

background-image: url("/static/my-image.png")

@arunoda arunoda closed this as completed May 18, 2017
@laoqiren
Copy link
Author

@arunoda yes, It doens't work just using background-image: url("/static/my-image.png").

@manishoo
Copy link

manishoo commented Jul 2, 2017

@arunoda See, we have a problem here which we're trying to solve, we're not looking for workarounds in which you're suggesting to use static images. how can we achieve requiring images (png, jpg, etc...) ? I personally prefer to have a customizable web pack for better customizability.

@lededje
Copy link

lededje commented Jul 2, 2017

@mehdijjz what is it your are trying to achieve? It's difficult to know what to suggest when you don't explain what you want when importing images. The example given above doesn't have to be a CSS background image, it can be an image tag too.

@manishoo
Copy link

manishoo commented Jul 2, 2017

@lededje I want to use a webpack/babel loader to require images in my components.

e.g: <img src={require('./myImage.png')} />

@lededje
Copy link

lededje commented Jul 2, 2017

@mehdijjz That which runs on the server must also run on the client. This will not run on the client if you use webpack to perform this task. Here is a link to using a custom babel configuration but I must stress, I doubt you will find what you are looking for.

I ask once again, what do you expect require('./myImage.png') to return? I'm not trying to doubt your implemtation, just understand what you are trying to acheive to give you a better answer.

@lededje
Copy link

lededje commented Jul 2, 2017

yes, It doens't work just using background-image: url("/static/my-image.png").

@laoqiren The files must be within a /static/ directory relative to the pages directory. There are several examples of this working in the documentation.

@arunoda
Copy link
Contributor

arunoda commented Jul 3, 2017

Thanks @lededje for all those references and details.

@mehdijjz there are a lot of things we like to do. But sometimes, we can't do all of them.
But someday, we'll be able to do it.

In the meantime, you need live without those features.

@vzaidman
Copy link
Contributor

add the following babel plugin:
https://www.npmjs.com/package/babel-plugin-inline-import-data-uri

@timneutkens
Copy link
Member

You can actually use webpack loaders in v5, someone already made a plugin for handling images: https://github.com/arefaslani/next-images

@tomsoderlund
Copy link

See also: https://github.com/cyrilwanner/next-optimized-images

@tarang9211
Copy link

You can actually use webpack loaders in v5, someone already made a plugin for handling images: https://github.com/arefaslani/next-images

This doesn't really work. I tried it.

/* eslint-disable */
const withSass = require('@zeit/next-sass');
const withImages = require('next-images');
module.exports = withSass({
  sassLoaderOptions: {
    includePaths: ['./styles/']
  },
  cssModules: true,
  cssLoaderOptions: {
    importLoaders: 1,
    localIdentName: '[local]___[hash:base64:5]'
  },
  withImages: withImages()
});

@defi-engineer

This comment has been minimized.

@defi-engineer

This comment has been minimized.

@AndrewRayCode
Copy link

It looks like you can add static files in general by following the pattern of the withSass next-images plugin: https://github.com/twopluszero/next-images/blob/master/index.js and adding similar code for other file types in your next.config.js, or adding your own extension for it.

(I don't understand the hard coding of publicPath: '/_next/static/' into the above linked plugin, shouldn't this be from some config setting?)

I'm still playing with it, but I wish there was better first class support for this, or more documentation around it. Using a static/ folder defeats one of the core principles/reasons for using Webpack, which is a compile-time-provable dependency graph of all critical assets in your codebase. Using static/ by default is going back in time when we relied on global variables (path strings) to line up.

@arefaslani
Copy link

arefaslani commented Jan 31, 2019

@tarang9211 I've already responded it in this issue twopluszero/next-images#10

@olko404
Copy link

olko404 commented Feb 11, 2019

If you add the image to the /static/ and then add the <img src="/static/image.png"/>?
There is no need to load the image via the import.

how to add the image to static? what's the static? is it webpack config?

@arefaslani
Copy link

how to add the image to static? what's the static? is it webpack config?

@Ivanenko-O It's a directory inside your application's root directory. everything inside it will be served statically.

@msolimans
Copy link

You can actually use webpack loaders in v5, someone already made a plugin for handling images: https://github.com/arefaslani/next-images

this doesn't work well with amplify

@arefaslani
Copy link

@msolimans Can you provide an example to see why it doesn't work with Amplify?

@eugef
Copy link

eugef commented Aug 14, 2019

Unfortunately next-images doesn't work nicely with images rendered server-side if assetPrefix is dynamic twopluszero/next-images#12 (for CSR images it works fine)

@eugef
Copy link

eugef commented Sep 12, 2019

@Italox hardcoding image urls doesn't work in case images needs to be served from a different domain than the app itself (like CDN for example).

@iaurg
Copy link
Contributor

iaurg commented Sep 12, 2019

@Italox hardcoding image urls doesn't work in case images needs to be served from a different domain than the app itself (like CDN for example).

Yeah, I agree in this case.

@ruhaise
Copy link

ruhaise commented Oct 15, 2019

webpack loader fixed the problem, still typescript complains about it
Cannot find module '../images/me.png'.ts(2307)

@Schmerb
Copy link

Schmerb commented Oct 26, 2019

@ruhaise

Hey check this out, https://github.com/zeit/next.js/blob/master/errors/static-dir-deprecated.md

I just saw this in my console after digging for a good bit. Was able to get it working by adding a public folder instead of static and I am using next@v^9.1.1

@ruhaise
Copy link

ruhaise commented Oct 27, 2019

@Schmerb thanks dude, seems like it works :)

@AndrewRayCode
Copy link

In my app, I <img src={require('images/myfile.png');} /> with nextjs. The reasons I want to do this:

  • Use webpack to verify a file exists
  • Requiring static files is one of the main reason webpack was built in the first place
  • Do specific things with loaders at load time (for example, I have a custom JSON webpack loader to process some large JSON files that would otherwise be loaded as static files

In my next.config.js, here's an example of how i've added a rule for letting me require images in my source code

const config = {

  // See https://nextjs.org/docs/#customizing-webpack-config
  webpack: (webpackConfig, { isServer }) => {
    const { module } = webpackConfig;
    return {
      ...webpackConfig,
      module: {
        ...module,
        rules: [
          ...module.rules,
          {
            test: /\.(png|gif|jpg|jpeg)$/,
            use: [
              {
                loader: 'file-loader',
                options: {
                  emitFile: isServer,
                  publicPath: `/_next/static/`,
                  outputPath: `${isServer ? '../' : ''}static/`,
                  name: '[path][name].[ext]'
                }
              }
            ]
          }
        ]
      }
    };
  }
};

};

module.exports = config;

It's unclear to me when nextjs does things with webpack, so I added emitFile: isServer in the hope that files will only be processed by webpack when the server bundle is built, and not duplicate work when the client bundle is built.

It's unclear to me if this pattern adds any overhead to the build, because I'm not sure what webpack is doing under the hood with images/static assets in dev mode.

@samuelcastro
Copy link

I'm using next-optimized-images to import images, however it does not work in typescript, I'm getting messages like: Cannot find module './banner.png'. It does work with jsx though.

@arefaslani
Copy link

arefaslani commented Feb 3, 2020

@samuelcastro next-images also supports typescript and you can find how to use it with typescript in the readme.

@MaxmaxmaximusGitHub
Copy link

MaxmaxmaximusGitHub commented Apr 24, 2020

loaders not working with styled jsx

<style jsx global>{ `
    body {
      background-image url('./lol.png')
    }
<style>

url('./lol.png') must be replace to http://localhost:3000/_next/static/chunks/images/lol-3cb46b372ab77d032576b9f70c83d1ff.png but this does not happen

@gabooh
Copy link

gabooh commented Apr 24, 2020

If you're coming here from google, this is what seams best as of now : next-optimized-images

@bugproof
Copy link

bugproof commented Jun 24, 2020

I don't understand why would you want to use something like next-images or next-optimized-images if all they do is configuring file-loader/url-loader for you. These projects should be nothing more than gists people can contribute to and modify to their needs. Shouldn't it output these files to /public folder anyway according to https://nextjs.org/docs/basic-features/static-file-serving ? Because cmon... _next/static/ isn't even documented anywhere... This is definitely one hell of a mess looking at previous comments in this issue. Looking at the issues in linked projects I came to the assumption you're better off just configuring webpack yourself...

config.module.rules.push({
    test: /\.(png|jpe?g|gif|svg)$/i,
    loader: "file-loader",
    options: {
    outputPath: '../public/assets/', // if you don't use ../ it will put it inside ".next" folder by default
    publicPath: 'assets/',
    }
});

Tested this only in development so far but at least it outputs the files according to the official docs and it's clear to understand. I will update it in case it doesn't work in production.

Next.js can serve static files, like images, under a folder called public in the root directory. Files inside public can then be referenced by your code starting from the base URL (/).

By the way, static folder was deprecated: https://nextjs.org/blog/next-9-1#public-directory-support

@serv
Copy link

serv commented Jul 28, 2020

As @bugproof points out, you don't need packages like next-images or next-optimized-images.

Here are steps on how you can import images. I copied how create-react-app does this.

  1. npm i --save-dev url-loader
  2. touch next.config.js if you don't already have a next.config.js file.
  3. Add this.
module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    config.module.rules.push({
      test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
      loader: require.resolve("url-loader")
    });

    return config;
  }
};

@naeem1098
Copy link

As @bugproof points out, you don't need packages like next-images or next-optimized-images.

Here are steps on how you can import images. I copied how create-react-app does this.

  1. npm i --save-dev url-loader
  2. touch next.config.js if you don't already have a next.config.js file.
  3. Add this.
module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    config.module.rules.push({
      test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
      loader: require.resolve("url-loader")
    });

    return config;
  }
};

It didn't work in production!

@naeem1098
Copy link

I changed the file from .jpg to .jpeg and it worked fine. Before, it was working fine in development but wasn't showing the image in production.

@yohanelly95
Copy link

yohanelly95 commented Aug 12, 2020

Really struggling with this one, I mean I've created a public folder in the root of my directory and added an image there. I try this in any page or component
./components/common/Footer.js Module not found: Can't resolve '/dino.svg' in '/Users/xyz/xyz/components/common'

Not really sure to do here. My next version is the latest. And according to their docs, I only have to create public directory.
Can someone help me out please?

@abhijit-hota
Copy link

@Italox hardcoding image urls doesn't work in case images needs to be served from a different domain than the app itself (like CDN for example).

What is the correct way to serve images from a CDN?

@bugproof
Copy link

Really struggling with this one, I mean I've created a public folder in the root of my directory and added an image there. I try this in any page or component
./components/common/Footer.js Module not found: Can't resolve '/dino.svg' in '/Users/xyz/xyz/components/common'

Not really sure to do here. My next version is the latest. And according to their docs, I only have to create public directory.
Can someone help me out please?

Can you show us the code from footer.js where you try to use that file? You don't have to put it in public folder when you use import or require. If you configured the loader correctly it will put it there for you.

@Sugarcothe

This comment has been minimized.

@Vince-vegas
Copy link

@arunoda See, we have a problem here which we're trying to solve, we're not looking for workarounds in which you're suggesting to use static images. how can we achieve requiring images (png, jpg, etc...) ? I personally prefer to have a customizable web pack for better customizability.

How

@liubin915249126
Copy link

If you add the image to the /static/ and then add the <img src="/static/image.png"/>?
There is no need to load the image via the import.

but,when I want to deploy in a subfolder,the img is 404

@johnnybenson
Copy link

johnnybenson commented Feb 22, 2021

Have to second the sentiments from this comment #1935 (comment)

This Image component is a drag and an example of a framework being too heavy handed. Leave this abstraction up to the end user and get out of the way.

Related: #18393

https://nextjs.org/docs/api-reference/next/image

👀   Not asking for these inline styles at all

<Image src="/images/hero-banner-example.png" width="" height="" />
<img src="/_next/image?url=%2Fimages%2Fhero-banner-example.png&amp;w=3840&amp;q=75" decoding="async" srcset="/_next/image?url=%2Fimages%2Fhero-banner-example.png&amp;w=3840&amp;q=75 1x" style="visibility: inherit; position: absolute; inset: 0px; box-sizing: border-box; padding: 0px; border: none; margin: auto; display: block; width: 0px; height: 0px; min-width: 100%; max-width: 100%; min-height: 100%; max-height: 100%;">

image


How about a hook to build just the URL?

const imgSrc = useNextImage('path/to/image');

// thanks I'll take it from here

@pawanrana1992
Copy link

pawanrana1992 commented Jun 26, 2021

Dont't use any custom config for image load from public folder, I had face same issue with custom config but when I removed the code block, it is started working. Hope it helps some one with .less configuration.

`const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path')

module.exports = {
optimizeFonts: true,
reactStrictMode: true,
eslint: {
dirs: ["pages", "app"],
},
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, webpack }
) => {
config.module.rules.push({
test: /.less$/, // .less and .css
use: [
isServer ? MiniCssExtractPlugin.loader : 'style-loader',
{
loader: "css-loader",
options: {
sourceMap: true,
},
},
{
loader: 'less-loader',
options: {
sourceMap: true,
lessOptions: {
import: true,
strictMath: true,
paths: [path.resolve(__dirname, 'app')],
},
}
}
],
},)
// {
// test: /.(eot|woff|woff2|ttf|svg|png|jpg|gif)([?]?.*)$/,
// use: {
// loader: 'url-loader',
// options: {
// limit: false,
// }
// }
// })
// Add an instance of the MiniCssExtractPlugin to the plugins list
// But remember - only for production!
if (isServer) {
config.plugins.push(new MiniCssExtractPlugin())
}
// Important: return the modified config
return config;
},
};
`

@lokeshn011101
Copy link

@ruhaise

Hey check this out, https://github.com/zeit/next.js/blob/master/errors/static-dir-deprecated.md

I just saw this in my console after digging for a good bit. Was able to get it working by adding a public folder instead of static and I am using next@v^9.1.1

This is working! Thank you so much!

@mglavall
Copy link

In my case I want to do it to preload the image

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests