Coder Social home page Coder Social logo

niels-io / next-image-export-optimizer Goto Github PK

View Code? Open in Web Editor NEW
409.0 5.0 51.0 11.97 MB

Use Next.js advanced <Image/> component with the static export functionality. Optimizes all static images in an additional step after the Next.js static export.

JavaScript 67.03% CSS 4.06% TypeScript 28.91%
image-manipulation images nextjs react resize

next-image-export-optimizer's Introduction

Next-Image-Export-Optimizer

npm

Use Next.js advanced <Image/> component with the static export functionality. Optimizes all static images in an additional step after the Next.js static export.

  • Reduces the image size and page load times drastically through responsive images
  • Fast image transformation using sharp.js (also used by the Next.js server in production)
  • Conversion of JPEG and PNG files to the modern WEBP format by default
  • Serve the exported React bundle only via a CDN. No server required
  • Automatic generation of tiny, blurry placeholder images
  • Minimal configuration necessary
  • Supports TypeScript
  • Supports remote images which will be downloaded and optimized
  • Supports animated images (accepted formats: GIF and WEBP)
  • Note that only one global value can be used for the image quality setting. The default value is 75.

Placement of the images:

For images using a path string: (e.g. src="/profile.png")

Place the images in a folder inside the public folder like public/images

For images using a static import: (e.g. src={profileImage})

You can place the images anywhere in your project. The images will be optimized and copied to the export folder.

For remote images: (e.g. src="https://example.com/image.jpg")

Please refer to the section on remote images.

Installation

npm install next-image-export-optimizer

# Or
yarn add next-image-export-optimizer
pnpm install next-image-export-optimizer

Configuration

Basic configuration

Add the following to your next.config.js:

// next.config.js
module.exports = {
  output: "export",
  images: {
    loader: "custom",
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
  transpilePackages: ["next-image-export-optimizer"],
  env: {
    nextImageExportOptimizer_imageFolderPath: "public/images",
    nextImageExportOptimizer_exportFolderPath: "out",
    nextImageExportOptimizer_quality: "75",
    nextImageExportOptimizer_storePicturesInWEBP: "true",
    nextImageExportOptimizer_exportFolderName: "nextImageExportOptimizer",
    nextImageExportOptimizer_generateAndUseBlurImages: "true",
    nextImageExportOptimizer_remoteImageCacheTTL: "0",
  },
};

Update the build command in package.json

{
-  "build": "next build",
+  "build": "next build && next-image-export-optimizer"
}

Replace the <Image /> component with the <ExportedImage /> component:

Example:

// Old
import Image from "next/image";

<Image
  src="images/VERY_LARGE_IMAGE.jpg"
  alt="Large Image"
  width={500}
  height={500}
/>;

// Replace with either of the following:

// With static import (Recommended)
import ExportedImage from "next-image-export-optimizer";
import testPictureStatic from "PATH_TO_IMAGE/test_static.jpg";

<ExportedImage src={testPictureStatic} alt="Static Image" />;

// With dynamic import
import ExportedImage from "next-image-export-optimizer";

<ExportedImage
  src="images/VERY_LARGE_IMAGE.jpg"
  alt="Large Image"
  width={500}
  height={500}
/>;

Advanced configuration

Remote images

For remote images, you have to specify the src as a string starting with either http or https in the ExportedImage component.

import ExportedImage from "next-image-export-optimizer";

<ExportedImage src="https://example.com/remote-image.jpg" alt="Remote Image" />;

In order for the image optimization at build time to work correctly, you have to specify all remote image urls in a file called remoteOptimizedImages.js in the root directory of your project (where the next.config.js is stored as well). The file should export an array of strings containing the urls of the remote images. Returning a promise of such array is also supported.

Example:

// remoteOptimizedImages.js
module.exports = [
  "https://example.com/image1.jpg",
  "https://example.com/image2.jpg",
  "https://example.com/image3.jpg",
  // ...
];
// Or with a promise
module.exports = new Promise((resolve) =>
  resolve([
    "https://example.com/image1.jpg",
    "https://example.com/image2.jpg",
    "https://example.com/image3.jpg",
    // ...
  ])
);

// Or with an async API call
module.exports = fetch("https://example.com/api/images").catch((error) => {
  console.error(error);
  return []; // return an empty array in case of error
});

At build time, the images will be either downloaded or read from the cache. The image urls will be replaced with the optimized image urls in the Exported Image component.

You can specify the time to live of the cache in seconds by setting the nextImageExportOptimizer_remoteImageCacheTTL environment variable in your next.config.js file. The default value is 0 seconds (as the image might have changed).

Set it to:

  • 60 for 1 minute
  • 3600 for 1 hour
  • 86400 for 1 day
  • 604800 for 1 week
  • 2592000 for 1 month
  • 31536000 for 1 year

If you want to hide the remote image urls from the user, you can use the overrideSrc prop of the ExportedImage component. This will replace the src attribute of the image tag with the value of the overrideSrc prop.

Beware that the Image component cannot fall back to the original image URL if the optimized images are not yet generated when you use the overrideSrc prop. This will result in a broken image link.

Custom next.config.js path

If your Next.js project is not at the root directory where you are running the commands, for example when you are using a monorepo, you can specify the location of the next.config.js as an argument to the script:

"export": "next build && next-image-export-optimizer --nextConfigPath path/to/my/next.config.js"

Custom export folder path

Specify the output folder path either via environment variable:

// next.config.js
{ "env": {
"nextImageExportOptimizer_exportFolderPath": "path/to/my/export/folder"
}}

Or by passing the argument to the script:

 "export": "next build && next-image-export-optimizer --exportFolderPath path/to/my/export/folder"

Base path

If you want to deploy your app to a subfolder of your domain, you can set the basePath in the next.config.js file:

module.exports = {
  basePath: "/subfolder",
};

The ExportedImage component has a basePath prop which you can use to pass the basePath to the component.

import ExportedImage from "next-image-export-optimizer";
import testPictureStatic from "PATH_TO_IMAGE/test_static.jpg";

<ExportedImage
  src={testPictureStatic}
  alt="Static Image"
  basePath="/subfolder"
/>;

Placeholder images

If you do not want the automatic generation of tiny, blurry placeholder images, set the nextImageExportOptimizer_generateAndUseBlurImages environment variable to false and set the placeholder prop from the <ExportedImage /> component to empty.

Custom export folder name

If you want to rename the export folder name, set the nextImageExportOptimizer_exportFolderPath environment variable to the desired folder name. The default is nextImageExportOptimizer.

Image format

By default, the images are stored in the WEBP format.

If you do not want to use the WEBP format, set the nextImageExportOptimizer_storePicturesInWEBP environment variable to false.

Good to know

  • The <ExportedImage /> component is a wrapper around the <Image /> component of Next.js. It uses the custom loader feature to generate a srcset for different resolutions of the original image. The browser can then load the correct size based on the current viewport size.

  • The image transformation operation is optimized as it uses hashes to determine whether an image has already been optimized or not. This way, the images are only optimized once and not every time the build command is run.

  • The <ExportedImage /> component falls back to the original image if the optimized images are not yet generated in the development mode. In the exported, static React app, the responsive images are available as srcset and dynamically loaded by the browser.

  • The static import method is recommended as it informs the client about the original image size. When widths larger than the original image width are requested, the next largest image size in the deviceSizes array (specified in the next.config.js) will be used for the generation of the srcset attribute. When you specify the images as a path string, this library will create duplicates of the original image for each image size in the deviceSizes array that is larger than the original image size.

  • You can output the original, unoptimized images using the unoptimized prop. Example:

    import ExportedImage from "next-image-export-optimizer";
    
    <ExportedImage
      src={testPictureStatic}
      alt="Original, unoptimized image"
      unoptimized={true}
    />;
  • You can still use the legacy image component next/legacy/image:

    import ExportedImage from "next-image-export-optimizer/legacy/ExportedImage";
    
    import testPictureStatic from "PATH_TO_IMAGE/test_static.jpg";
    
    <ExportedImage src={testPictureStatic} alt="Static Image" layout="fixed" />;
  • Animated images: You can use .gif and animated .webp images. Next-image-export-optimizer will automatically optimize the animated images and generate the srcset for the different resolutions.

    If you set the variable nextImageExportOptimizer_storePicturesInWEBP to true, the animated images will be converted to .webp format which can reduce the file size significantly. Note that animated png images are not supported by this package.

Live example

You can see a live example of the use of this library at reactapp.dev/next-image-export-optimizer

Warning Version 1.0.0 is a breaking change. It follows the changes introduced in Next 13.0.0 which replaces the next/image component with next/future/image. If you are using Next 12 or below, please use version 0.17.1.

next-image-export-optimizer's People

Contributors

emmaccen avatar fretimmerman avatar itrich avatar matobeno1 avatar niels-io avatar nielsapp avatar nvh95 avatar peterkottas avatar srmagura avatar stefangoor avatar stooit avatar tmlamb avatar wpoynter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

next-image-export-optimizer's Issues

Pipeline fail at next-image-export-optimizer script

Configuration used:

"next": "^12.2.3",
"react": "^18.2.0",
"next-image-export-optimizer": "^0.12.1",

I'm currently trying to run the image export opti in my pipeline (is pretty generic, nothing special going on in there) but for some reason it fails after yarn export at next-image-export-optimizer/src/optimizeImages.js:89

Which is const legacyPath = nextjsConfig.images?.nextImageExportOptimizer;

With an error SyntaxError: Unexpected token '.' after the question mark.

Could you please help me out, and point me at what I'm doing wrong here :)

(locally it runs fine, of course haha)

TIA

next export failing

/Users/vittaljk/poc/home/node_modules/next-image-export-optimizer/src/optimizeImages.js:89
if (nextjsConfig.images?.nextImageExportOptimizer?.imageFolderPath) {
^

SyntaxError: Unexpected token '.'
at wrapSafe (internal/modules/cjs/loader.js:915:16)
at Module._compile (internal/modules/cjs/loader.js:963:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
at Module.load (internal/modules/cjs/loader.js:863:32)
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
at internal/main/run_main_module.js:17:47

importing ExportedImage gives below error

Unhandled Runtime Error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Check the render method of ForwardRef(LoadableComponent).

Disagreement between README and actual behavior in development mode

First let me say, thank you so much for this project!

The README says:

In the development mode, the original image will be served. The optimized images are created at build time only.

But the code tries to use optimizedLoader regardless of whether Next is running in development mode or production mode.

Whether the original or optimized image is rendered is determined by whether the optimized image exists in public.

Which is correct, the README or the code? I am happy to create a PR.

Here is a screenshot showing the problem. The image src is an optimized .WEBP file and you can tell it's development mode because of <script> tag for react-refresh.js.

image

"priority" prop not working properly in ExportedImage

Hi @Niels-IO,

It's me again. The ExportedImage has worse LCP performance then the native Image when using priority.

I am performing the following Lighthouse testing in the browser:
seetings

When using Image without priority:
ImageNoPriority

ImageNoPrioritySpeed

When using Image with priority set:
Image

ImageSpeed

However using ExportedImage with priority makes no difference in the LCP time:
ExportedImage

ExportedImageSpeed

This is my next.config.js file:
nextjs_config

Even lowering the quality did not help. To me it look like the priority attribute does not get set properly,
can you take a look at this?

Thanks!

Segmentation fault (macos M1, sharp v0.31.0)

Hi,

I am getting segfaults from next-image-export-optimizer.

---- next-image-export-optimizer: Begin with optimization... ----
Found 44 supported images in public/images, static folder and subdirectories.
Using sizes: 10,16,32,48,64,96,128,256,384,640,750,828,1080,1200,1920,2048,3840
Start optimization of 44 images with 17 sizes resulting in 748 optimized images...
โ–ˆโ–ˆ 5% | ETA: 117s | 42/748 | Total size: 6.5 MBsh: line 1: 25707 Segmentation fault: 11  next-image-export-optimizer

I am on macos M1. There is an issue on sharp: lovell/sharp#3048
but that looks like it was resolved with the latest release v0.31.0 which is what your package uses, and what did get installed.

Sometimes it even segfaults during next build:

info  - Creating an optimized production build .sh: line 1: 27459 Segmentation fault: 11  next build

It only gets through 8 resizings before it happens

.rw-r--r--    82 crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-10.WEBP
.rw-r--r--   120 crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-16.WEBP
.rw-r--r--   322 crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-32.WEBP
.rw-r--r--   600 crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-48.WEBP
.rw-r--r-- 1,012 crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-64.WEBP
.rw-r--r-- 2.1Ki crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-96.WEBP
.rw-r--r-- 3.5Ki crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-128.WEBP
.rw-r--r--  13Ki crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-256.WEBP
.rw-r--r--     0 crucialfelix 22 Sep 09:24 aaron-burden-1381021-unsplash-opt-384.WEBP

(last one is size 0)

I have just local images, config is simple:

{
 // ...
  images: {
    loader: "custom",
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
  env: {
    nextImageExportOptimizer_imageFolderPath: "public/images",
    nextImageExportOptimizer_exportFolderPath: "out",
    nextImageExportOptimizer_quality: 75,
    nextImageExportOptimizer_storePicturesInWEBP: true,
    nextImageExportOptimizer_generateAndUseBlurImages: true,
  },
}

Thank you!

Possibility of changing export path based on provided argument

I have this setup in package.json

    "build": "next build && next export -o ../api/Web/wwwroot && next-image-export-optimizer",
    "build:docker": "next build && next-image-export-optimizer && next export -o .export",

How do I change the nextImageExportOptimizer_exportFolderPath dynamically based on the command?

image has both width and fill properties on dev server

I am upgrading to v13 of Next.js and v1 of this package. Building my static website works fine, but running the next dev server gives me errors when using fill images:

Error: Image with src "/_next/static/media/bol.4615d14b.png" has both "width" and "fill" properties. Only one should be used.

I am not specifying a width in the image:

<ExportedImage
  src={project.logoPath}
  alt={project.organization}
  useWebp
  fill
  style={{ objectFit: "scale-down", objectPosition: "right top" }}
/>

It only happens on the dev server, but it makes development much more cumbersome. It also happens to fill images in other places. My other images, which don't use fill, do not cause any errors. I use the legacy component for fill images now as a workaround.

Any ideas on how this can be fixed?

Version 0.14.x broken due to '.next/static/media'

Afternoon, the latest version 0.14.0 seems to be broken with my nextjs application.

When running on the latest version of everything I see the following issue

Error: ENOENT: no such file or directory, stat '.next/static/media'

When running nextjs this folder does not exist within the .next output, I have no static assets as they are all dynamically imported and then ran with the tool

Looks related to this PR - https://github.com/Niels-IO/next-image-export-optimizer/pull/36/files

Let me know what you need, or want me to look into and I can come back to this issue

My next.config.js looks like this

const packageVersion = require("./package.json");

const nextConfig = {
  poweredByHeader: false,
  generateBuildId: async () => {
    // You can, for example, get the latest git commit hash here
    return packageVersion.version;
  },
  async rewrites() {
    return [
      {
        source: "/:slug*.html", // Old url with .html
        destination: "/:slug*", // Redirect without .html
      },
    ];
  },
  reactStrictMode: true,
  images: {
    domains: ["localhost"],
    loader: "custom",
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920], 
  },
  env: {
    nextImageExportOptimizer_imageFolderPath: "public/images",
    nextImageExportOptimizer_exportFolderPath: "out",
    nextImageExportOptimizer_quality: 75,
    nextImageExportOptimizer_storePicturesInWEBP: true,
    nextImageExportOptimizer_generateAndUseBlurImages: true,
  },
};

module.exports = nextConfig;

Include images stored in subfolders

First of all, thank you for writing this plugin and finally bringing a solution to the next.js image export shenanigan! โค๏ธ

From the docs and tryouts I understand that images have to be stored in a folder like public/images.
It would be super nice if subfolders would get included in the optimization process, too, so that

next-app/
โ”œโ”€ public/
โ”‚  โ”œโ”€ images/
โ”‚  โ”‚  โ”œโ”€ hero-image.jpg
โ”‚  โ”‚  โ”œโ”€ project-1/
โ”‚  โ”‚  โ”‚  โ”œโ”€ project-cover.jpg
โ”‚  โ”‚  โ”œโ”€ project-2/
โ”‚  โ”‚  โ”‚  โ”œโ”€ project-cover.jpg/
โ”‚  โ”‚  โ”œโ”€ .../

gets compiled into

next-app/
โ”œโ”€ out/
โ”‚  โ”œโ”€ images/
โ”‚  โ”‚  โ”œโ”€ nextImageExportOptimizer/
โ”‚  โ”‚  โ”‚  โ”œโ”€ hero-image-32.webp
โ”‚  โ”‚  โ”‚  โ”œโ”€ hero-image-16.webp
โ”‚  โ”‚  โ”‚  โ”œโ”€ ...
โ”‚  โ”‚  โ”‚  โ”œโ”€ project-1/
โ”‚  โ”‚  โ”‚  โ”‚  โ”œโ”€ project-cover-16.webp
โ”‚  โ”‚  โ”‚  โ”‚  โ”œโ”€ project-cover-32.webp
โ”‚  โ”‚  โ”‚  โ”‚  โ”œโ”€ ...
โ”‚  โ”‚  โ”‚  โ”œโ”€ project-2/
โ”‚  โ”‚  โ”‚  โ”‚  โ”œโ”€ project-cover-16.webp/
โ”‚  โ”‚  โ”‚  โ”‚  โ”œโ”€ project-cover-32.webp
โ”‚  โ”‚  โ”‚  โ”‚  โ”œโ”€ ...
โ”‚  โ”‚  โ”‚  โ”œโ”€ .../

Like this, the public image folder would stay nice and organised for bigger projects without having to worry about conflicting image names.

Images components are not exported after a next build

Hey there,
just discovered your (seems like :p) awesome package.

I had a try on it but when I export my site by running next build && next export && next-image-export-optimizer, I can see that all my images are well optimised in different sizes and copied into the out folder but when I inspect the resulting html, no img tag at all are injected. Images appears well on next dev.

I'm definitely doing something wrong but I don't find what. I followed the instructions here with the exact same config. My images are in the public folder and I wrote a basic component like this:

<ExportedImage src="images/destination/image-europa.png" layout="fill" />

Any ideas on what I'm doing wrong ?

Edit: I uploaded this training project here https://github.com/johann-taberlet/space-tourism-website

allow image export to remote edge server

Hi,

First, thanks for making this project.

I have a use case where I am trying to host the next-exported files (html, js, css, etc) separately from the images. I'd like to host the images on a remote edge server (eg, S3 or similar) and was wondering if there might be a way to:

  1. make it so the next-image-export-optimizer renders all versions of the static images into one folder. That might be happening already, but it seems like there are duplicate nextImageExportOptimize folders that may be copied from the /public build
  2. allow the substitution of all image sources with a remote URL (eg. replace source images '/nextImageExportOptimizer' with 'https://myedgeserver/path/to/file'

I've tried doing a simple find | sed on the output, but it's not clear to me if the source sets are even being used.

I guess my questions are:

  • How to test if the source sets are being used? I can't see in the browser. It appears as if '_next/static/path/to/full/file' is being used instead of 'nextImageExportOptimize' ones
  • How would you go about doing the above? Do you reckon a string replace work on the output?
  • Is there maybe a better way?

thanks for any input you might have and for this great project.

Image path not resolved if used with the basePath property

Hi and congrats for taking the initiative of this package!

I'm often facing use-case where I have to deploy static pages under a subfolder in a shared hosting.
Unfortunately it doesn't work with the needed next.conf.js basePath property, to resolve asset. The built path doesn't take that into account.

I would like to help but I'm not sure being skilled enough for this ๐Ÿคญ.

Tell me if you have recommandation regarding this bug or needed contribution, I'm really interested to get this package working.

Types not working in new release

import Image from "next-image-export-optimizer/future/ExportedImage";

TS2307: Cannot find module 'next-image-export-optimizer/future/ExportedImage' or its corresponding type declarations.

Does this work without specifying width/height?

one of the advantages of using next/image is that it can suss out width/height.

It seems like this library doesn't work unless you specify width/hight or have a containing div where the width and height are specified.

eg, the following works fine with next/image but will just show up empty (zero width and height):

          <div className='md:float-right md:relative w-full md:w-1/3 md:ml-4 md:mb-2'>                                                         
            <ExportedImage                                                                
              className="rounded"                                                                                     
              placeholder='blur'                                                          
              src={profile.src}                        
              alt={profile.alt}                                                                        
              sizes="(max-width: 768px) 100vw,                                            
              (max-width: 1200px) 50vw,         
              33vw"                      
            />       
          </div>    

`imageSizes` are ignored if they are in a conditional `process.env.NODE_ENV === "production"`

Hi,

I've noticed that conditional config parameters are ignored and default were used.

For example, this one with changed imageSizes will work as expected

next.config.js:

module.exports = {
  images: {
    loader: "custom",
    imageSizes: [16, 48, 54, 64, 100, 128, 144, 384],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920],
  },
  env: {
    // ...
  },
}

but having a conditional in there, will ignore the changes and load the defaults:

module.exports = {
 images:
    process.env.NODE_ENV === "production"
      ? {
          loader: "custom",
          imageSizes: [16, 48, 54, 64, 100, 128, 144, 384],
          deviceSizes: [640, 750, 828, 1080, 1200, 1920],
        }
      : { 
         // ...
        },
  env: {
    // ...
  },
}

I think it might be helpful to output a warning when the process isn't finding the values, so that one can see it will use defaults (like it warns when it doesn't find a next.config.js)

Thanks you! <3

Just wanted to say thanks for this awesome lib โค๏ธ

Add support for next version 13

Next.js version 13 was released yesterday - at the moment the next peer dependency is pinned at v12.x, meaning it conflicts when version 13 is installed. Can this be upgraded? The fact that next/future/image is the new default might have to be dealt with before upgrading though

Convert to AVIF

Hi, is there a specific reason why there is only conversion to WEBP available? AVIF is supposed to be even better. I'm thinking about coding it up, but I wanted to ask first. There could be the option to convert to avif by default, with the fallback to webP / orginal, if the browser doesn't support AVIF.

v1.0.0 not working next 13

I'm having this error below after upgrading to version 1.0.0 on next 13.0.0 with appDir enabled. Next suggests it's an issue with the package.json, but I can't figure it out... Can this be fixed? Thanks

Error: Module not found: Package path . is not exported from package node_modules\next-image-export-optimizer (see exports field in node_modules\next-image-export-optimizer\package.json)
2 | import Heading from '@components/heading'
3 |
4 | import ExportedImage from 'next-image-export-optimizer'
5 |
6 | import styles from './Links.module.css'
7 |

Jest failing on ExportedImage.d.ts

Hi There,

Since updating to v1.0 my Jest tests are failing with the following:

Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     โ€ข If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     โ€ข If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     โ€ข To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     โ€ข If you need a custom transformation specify a "transform" option in your config.
     โ€ข If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /development/myproject/node_modules/next-image-export-optimizer/dist/ExportedImage.d.ts:2
    import { ImageProps, StaticImageData } from "next/image";
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      1 | import { Grid, Typography } from '@mui/material';
    > 2 | import ExportedImage from 'next-image-export-optimizer';
        | ^
      3 | import { useContext } from 'react';
      4 |
      5 | import BrandContext from '../../contexts/BrandContext';

      at Runtime.createScriptFromCode (../../node_modules/jest-runtime/build/index.js:1796:14)
      at Object.<anonymous> (components/USP/USP.tsx:2:1)

I have tried adding a the transformIgnorePatterns to the jest.config.js to ignore the ExportedImage.d.ts but I still keep getting the error on all code importing ExportedImage.

I'm not sure how to resolve the issue so any advice would be great.

Many thanks,
Stefan

Query parameters confuse the replacement with optimized images

I use notion which has expiration dates on all files fetched through its API.

The URL's look something like the following:

[hash]/image.png?X-Amz-Algorithm=...&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=...%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=....&X-Amz-Expires=3600&X-Amz-Signature=...&X-Amz-SignedHeaders=host&x-id=GetObject

It took me some time to realize that while these images are downloaded just fine, they aren't being replaced on the site.

Removing the query parameter from the requests fixes this, but it would be nice if this tool could handle it (or mention it in the readme) to avoid unnecessary pitfalls for others.

Thanks for a great project.

Yarn berry error: react not in dependencies

Version affected: v0.15.2 and below
In my case using [email protected] with workspaces, PnP, and zero installs


When using yarn berry, starting a dev server or build fails with the following error:

Error: next-image-export-optimizer tried to access react, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.

Workaround is to explicitly add the dependency to .yarnrc.yml followed by a new yarn install:

packageExtensions:
  "next-image-export-optimizer@*":
    dependencies:
      "react": "*"

Adjusting deviceSizes breaks srcSet

I ran into an issue when trying to adjust the image and device sizes in next.config.js.

For my specific use case I do not need all default imageSizes: [16, 32, 48, 64, 96, 128, 256, 384] and deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], and as a way to speed up the build time tried to adjust the list of sizes to something more suitable, like deviceSizes: [640, 750, 1080, 1920].

It might also be that I do not understand the configuration properly. However, if they are not meant to be customised, then I also do not see the need to specify them in next.config.js๐Ÿ™‚

Expected behaviour

The plugin only generates new, optimised images for the specified imageSizes and deviceSizes, and adjusts the srcSet of the image tag to make use of the new sizes.

Observed behaviour

The plugin indeed only generated the sizes specified, but does not adjust the image tag properly so that it includes non-existent files. This breaks the image when the browser window gets too wide or too small.

image

image


Ways to reproduce the bug

1. Change next.config.js

module.exports = {
  images: {
    loader: "custom",
    nextImageExportOptimizer: {
      imageFolderPath: "public/images",
      exportFolderPath: "out",
      imageSizes: [16, 32],
      deviceSizes: [1920, 2048],
      quality: 75,
    },
  },
  env: {
    storePicturesInWEBP: true,
  },
};

2. Run npm run export
3. Resulting out/images folder
image

4. Resulting img tag

<img id="test_image" alt="test_image" sizes="100vw" 
srcset="images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-640.WEBP 640w,
images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-750.WEBP 750w,
images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-828.WEBP 828w,
images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-1080.WEBP 1080w,
images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-1200.WEBP 1200w,
images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-1920.WEBP 1920w,
images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-2048.WEBP 2048w,
images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-3840.WEBP 3840w" 
src="images/nextImageExportOptimizer/chris-zhang-Jq8-3Bmh1pQ-unsplash-opt-3840.WEBP" 
decoding="async" data-nimg="fill" style="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%; object-fit: cover;">

Uppercase extensions don't load up on safari

I have noticed that the optimized versions have uppercase extensions like .PNG/.WEBP but these don't seem to load up on Safari for some reason. Is there any specific reason to have them in uppercase?
image

"next-image-export-optimizer": "^0.6.0",

img tag is not inside exported html

Hi Niels,

Thank you for the great library, it's awesome! I wonder why my statically exported HTML doesn't contain any img tag.
It seems that javascript is required to display the image on the page, is this normal?

By default, NextJs is able to export the generated HTML :

image

Best regards,

Unexpected token '.' during production build on Cloudflare

I'm trying to deploy a Next.js SSG site on Cloudlfare. Below is my configuration and error output. I'm not sure if the next-image-export-optimizer is configured correctly or if it's Cloudflare with the issue.

package.json

  "scripts": {
    "dev": "next",
    "build": "next build",
    "preexport": "npm run build",
    "export": "next build && next export && npx next-image-export-optimizer",
    "prestart": "npm run export",
    "start": "serve out"
  },

Cloudflare build settings

Build command: next build && next export && npx next-image-export-optimizer
(*note: I've also tried just next build && next export by itself to see if that would fix the issue but no joy)
Build output directory: /out
Root directory: /

stacktrace:

12:51:45.508 | info  - Checking validity of types...
-- | --
12:51:50.892 | info  - Creating an optimized production build...
12:52:01.071 | info  - Compiled successfully
12:52:01.071 | info  - Collecting page data...
12:52:02.982 | info  - Generating static pages (0/5)
12:52:03.017 | info  - Generating static pages (1/5)
12:52:03.022 | info  - Generating static pages (2/5)
12:52:03.029 | info  - Generating static pages (3/5)
12:52:03.038 | info  - Generating static pages (5/5)
12:52:03.044 | info  - Finalizing page optimization...
12:52:03.047 | ย 
12:52:03.056 | Page                                       Size     First Load JS
12:52:03.056 | โ”Œ โ—‹ /                                      3.06 kB        86.2 kB
12:52:03.056 | โ”œ   /_app                                  0 B            83.2 kB
12:52:03.056 | โ”œ โ—‹ /404                                   194 B          83.4 kB
12:52:03.056 | โ”œ โ—‹ /photography                           607 B          90.7 kB
12:52:03.056 | โ”” โ— /photography/photo/[slug]              1.87 kB          92 kB
12:52:03.056 | โ”” /photography/photo/stairway
12:52:03.056 | + First Load JS shared by all              83.2 kB
12:52:03.056 | โ”œ chunks/framework-5f4595e5518b5600.js   42 kB
12:52:03.056 | โ”œ chunks/main-7d0be5702b1cad24.js        27.6 kB
12:52:03.056 | โ”œ chunks/pages/_app-1851968b312786ab.js  12.8 kB
12:52:03.056 | โ”œ chunks/webpack-fd82975a6094609f.js     727 B
12:52:03.056 | โ”” css/7eb7ceb2ca28c6b8.css               3.75 kB
12:52:03.056 | ย 
12:52:03.056 | โ—‹  (Static)  automatically rendered as static HTML (uses no initial props)
12:52:03.056 | โ—  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)
12:52:03.056 | ย 
12:52:03.788 | info  - using build directory: /opt/buildhome/repo/.next
12:52:03.793 | info  - Copying "static build" directory
12:52:03.796 | info  - No "exportPathMap" found in "/opt/buildhome/repo/next.config.js". Generating map from "./pages"
12:52:03.797 | info  - Launching 1 workers
12:52:03.797 | info  - Exporting (0/3)
12:52:03.797 | info  - Copying "public" directory
12:52:04.385 | info  - Exporting (3/3)
12:52:04.399 | Export successful. Files written to /opt/buildhome/repo/out
12:52:04.681 | Unexpected token '.'
12:52:04.832 | Failed: build command exited with code: 1

ExportedImage return 404 status

Screen Shot 2022-10-28 at 09 26 49
Screen Shot 2022-10-28 at 09 31 59

Hi, I have an issue that the ExportedImage cannot optimze image size as well as return 404 status (see the image).

import bannerImg2 from '@assets/images/Home/banner-2.jpg' // store at the path "public/assets/images/Home"

<ExportedImage src={bannerImg2} alt='text' layout='responsive' useWebp={true} />

Please help me how to fix this issue. Thanks for your help.

`src` does not reflect `basePath` for statically-imported images

Next allows you to configure a basePath so you can serve your site from a subpath. For example, we deploy our Next.js site to www.spotvirtual.com/_preview so we can test changes before making them live at www.spotvirtual.com.

I noticed that the generateImageURL code from ExportedImage.tsx does not take basePath into account for statically-imported images. Ideally, it would prepend the basePath since this is what next/image does.

It should be easy to fix. I may send a PR for this, though I am leaning towards changing our deployment so that the preview site is served from a different subdomain, e.g. www-preview.spotvirtual.com. This would prevent issues like this from arising in the first place.

There is a related next.config.js property called assetPrefix. Ideally the PR for this would take assetPrefix into account too. If both basePath and assetPrefix are set, I'm not sure which one "wins".

Image Quality on per image base

Hi, first of all thank you for your amazing library and the perfect docs.
I have a feature request. I would love to have the image quality as a an (optional) prop on . I wonderf if this would be possible.
Many thanks in advance and kind regards

Next Config imageSizes Prop Ignored?

Hi!

First of all, this is an incredibly useful tool - thank you for all the work you've put in!

I noticed that the imageSizes property setting in my next.config are being ignored during the next-image-export-optimizer process.

Here is what next-image-export-optimizer is showing:
image

Here's what my next.config.js file looks like:

module.exports = {
  images: {
    loader: "custom",
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
  trailingSlash: true,
  env: {
    nextImageExportOptimizer_imageFolderPath: "public/pokemon-images",
    nextImageExportOptimizer_exportFolderPath: "out",
    nextImageExportOptimizer_quality: 75,
    nextImageExportOptimizer_storePicturesInWEBP: "true",

    // If you do not want to use blurry placeholder images, then you can set
    // nextImageExportOptimizer_generateAndUseBlurImages to false and pass
    // `placeholder="none"` to all <ExportedImage> components.
    //
    // If nextImageExportOptimizer_generateAndUseBlurImages is false and you
    // forget to set `placeholder="none"`, you'll see 404 errors for the missing
    // placeholder images in the console.
    nextImageExportOptimizer_generateAndUseBlurImages: true,
  },
  experimental: {
    workerThreads: false,
    cpus: 1,
  },
};

And here are the two instances of ExportedImage in my app:

<ExportedImage
  src={`/type_svgs/${type.name.toLowerCase()}.svg`}
  alt={`${type.name} Type icon`}
  width={25}
  height={25}
  placeholder={"empty"}
/>
<ExportedImage
  src={`/pokemon-images/${pokemonData.pokemonApiName}.png`}
  alt={`Picture of the Pokemon ${pokemonData.name}`}
  width="350"
  height="350"
  useWebp={process.env.nextImageExportOptimizer_storePicturesInWEBP === "true"}
  priority
/>

Requests for 10px images cause 404 errors

The definition of automaticallyCalculatedBlurDataUrl generates a URL for a 10px image:

// otherwise use the generated image of 10px width as a blurDataURL
return generateImageURL(_src, 10, useWebp);

But the default imageSizes array does not contain 10, so you get a 404 when the browser tries to load the URL.

It seems like replacing the hardcoded 10 with the smallest number in imageSizes would fix this. Let me know what you think.

nextImageExportOptimizer folder leftover

Hey!

First of all, thank you very much for this!

I'm using your package for the first time and I'm facing a problem:

After I run npm export, next-image-export-optimizer creates a 'nextImageExportOptimizer' folder and a 'next-image-export-optimizer-hashes.json' file in my public dir.

I understand that the hashes are probably used to check if the images have already been optimized. I don't get why I get the 'nextImageExportOptimizer' leftover folder, though. In my understanding, it should be cleaned up after it's contents have been copied to the 'out' folder.

I'm I doing something wrong? Is this the expected behavior?

SyntaxError: Unexpected token '.'

Thanks for writing this plugin!

When using export build I get the following error.

Export successful. Files written to /project/websites//out
/project/websites//node_modules/next-image-export-optimizer/src/optimizeImages.js:78
    if (nextjsConfig.images?.nextImageExportOptimizer?.imageFolderPath) {
                            ^

SyntaxError: Unexpected token '.'
    at wrapSafe (internal/modules/cjs/loader.js:915:16)
    at Module._compile (internal/modules/cjs/loader.js:963:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

Setting placeholder from "empty" to lowest possible image size of optimised images

One nice thing about the Next.js Image component is the placeholder functionality, but it requires a blurDataURL to use for the blur effect.

Of course it would be an option to assume that the optimised images will be at the specific location, and add the blurDataURL with something like this:

const image = '/example.jpg'
const imageName = 'example'

<ExportedImage
    src= { image } // "image.jpg"
    alt="Large Image"
    width='720'
    height='960'
    layout='responsive'
    placeholder="blur"
    blurDataURL= {`/nextImageExportOptimizer/${imageName}-opt-16.WEBP`} // "/nextImageExportOptimizer/example-opt-16.WEBP"
/> 

However, this can become tedious if you have to provide both the full image path for the src and the image file name (to not end up with a broken path like /nextImageExportOptimizer/example.jpg-opt-16.WEBP), or include extra script to automatically strip the file ending from the image.

Is there an easier way to add the URL (let's say example-opt-16.WEBP) to each <ExportedImage /> component that has the property placeholder="blur"?

Thanks!

v0.10.0 release is broken, tests failing

0.10.0 causes Runtime Errors in previously working project during dev with the next command, export does not produce a working output either. Release 0.9.6 is working fine.

If this occures on my particular setup only, I can provide more information to pinpoint the issue.

npm test reports 2 snapshots failing, is this known?
Proper passing/failing tests should be established before proceeding with further releases.
Let me know if you need any help ๐Ÿ‘

Typescript Types?!

Hey, really appreciate this library!

I'm using typescript and I was wondering if it would be easy to add them myself or add them to the resource here @types/next-image-export-optimizer

Any input appreciated!

Again thank you for this library, I think its a problem that next doesn't allow image exporting with using their image component.

Potential optimization that could make builds much faster

I have an image called engagement.png that has a width of 732px. Naturally, all of the generated images with width >= 732px are the exact same image, as evidenced by the file sizes:

image

If I am reading the code correctly, sharp is run for each image, for each width. This means we are doing a lot of duplicate work if the image is much smaller than the max device size (3840 by default).

What if we optimized this so that the 828px, 1080px, 1200px, .etc images were created by simply copying the 750px image? (obviously this depends on the width of the original image)

Happy to PR if you are interested.

Error: ENOENT: no such file or directory, mkdir ...

Great work, just a minor error.
Easy to fix by creating the said directory manually.

Export successful. Files written to /Users/sonium/gitlab/fusionmetrics/landingpage/out
---- next-image-export-optimizer: Begin with optimization... ---- 
Error: ENOENT: no such file or directory, mkdir 'public/images/nextImageExportOptimizer'
    at Object.mkdirSync (node:fs:1357:3)
    at nextImageExportOptimizer (/Users/sonium/gitlab/fusionmetrics/landingpage/node_modules/next-image-export-optimizer/src/optimizeImages.js:122:10)
    at Object.<anonymous> (/Users/sonium/gitlab/fusionmetrics/landingpage/node_modules/next-image-export-optimizer/src/optimizeImages.js:320:3)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Module._load (node:internal/modules/cjs/loader:827:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47 {

Found 0 supported images in public/images

Getting the below output. All config are as per example

---- next-image-export-optimizer: Begin with optimization... ---- 
Found 0 supported images in public/images
Copy optimized images...
---- next-image-export-optimizer: Done ---- 

Add support for changing export directory name

Was wondering if you might be able to add support for changing the name of the directory where the images export to something other than nextImageExportOptimizer/ via configuration.

If it's not in scope for you, I may be able to open a PR.

Thanks for the great project!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.