website-logomedcode

Next.js 15 Image Upload: Full Guide to Server-Side Image Compression

Discover how to upload images in Next.js 15 while implementing server-side compression for optimal performance. This video walks you through the entire process, including key concepts, practical examples, and pro tips to handle file uploads and compress images on the server.Boost your Next.js app's speed and efficiency with these powerful techniques. If you find this content helpful, don’t forget to hit the subscribe button and turn on notifications for more tutorials like this!
alejandro coutinho| December 2, 2024
tools
Next.js 15 Image Upload: Full Guide to Server-Side Image Compression

#server_action #upload_image #image_compression

Introduction to Next.js 15

Next.js is one of those frameworks that make building React applications a breeze. With the release of Next.js 15, developers got even more exciting features to improve their workflow. This version introduced various enhancements, including a robust server-side image compression function that makes handling images simpler and more efficient. If you’ve ever struggled with uploading and compressing images in your web applications, this guide is here to help! We will take you through the steps for setting up a Next.js app, installing the necessary packages for image compression, and exploring the fantastic features of server actions.

Features of Server Action

The server-side image compression feature in Next.js 15 is a game changer for those who work with many images. Here are a few standout features:

  • Performance: Compressing images on the server can significantly improve loading times. Users typically appreciate faster loading pages, and search engines reward these efforts with better rankings.

  • Quality Control: With sharp, you can adjust the quality and format of your images. It supports multiple formats like JPEG, PNG, and WebP, allowing you to choose the best fit for your needs.

  • Automatic Resizing: Whether your images are too large or too small, server actions allow you to automatically resize them during upload. This keeps your application responsive and looking great on different devices.

  • Create a Next.js app: Open your terminal and run

  • npx create-next-app@latest my-next-app 

    Create FormUser.jsx component


  • "use client";
    import Form from "next/form";
    import Image from "next/image";
    import React, { useState } from "react";
    
    const FormUser = () => {
      const [imageUrl, setImageUrl] = useState("");
      return (
        <div>
          <Form
            className="max-w-md mx-auto mt-20 p-2 bg-white border rounded-lg shadow-lg"
          >
            <div className="max-w-md mx-auto px-10 p-2 rounded-md flex flex-col justify-center items-center">
              <Image
                className="block rounded-full shadow-xl mx-auto -mt-16 h-48 w-48 object-cover"
                src={imageUrl}
                width={300}
                height={300}
                alt="user image"
              />
              <label className="text-base text-gray-500 font-semibold mb-2 block">
                Upload Image
              </label>
              <input
                type="file"
                accept="image/*"
                readOnly
                className="w-min text-gray-400 font-semibold text-sm bg-white border file:cursor-pointer cursor-pointer file:border-0 file:py-3 file:px-4 file:mr-4 file:bg-gray-100 file:hover:bg-gray-200 file:text-gray-500 rounded"
              />
            </div>
            <div className="mb-4">
              <input
                className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                name="name"
                type="text"
                placeholder="Enter your name"
              />
            </div>
            <div className="mb-4">
              <input
                className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                name="email"
                type="email"
                placeholder="Enter your email"
              />
            </div>
            <div className="mb-4">
              <input
                className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                name="job"
                type="text"
                placeholder="Enter your job"
              />
            </div>
            <button
              className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
              type="submit"
            >
              add user
            </button>
          </Form>
        </div>
      );
    };
    
    export default FormUser;

    Install browser-image-compression

  • npm i browser-image-compression

  • Create HandelChangeImage function

  • "use client";
    import Form from "next/form";
    import Image from "next/image";
    import React, { useState } from "react";
    import imageCompression from "browser-image-compression";
    import { addUser } from "./action";
    
    const FormUser = () => {
      const [imageUrl, setImageUrl] = useState("");
      const handelChangeImage = async (e) => {
        const input = e.target;
        if (input.files && input.files[0]) {
          const file = input.files[0];
          const options = {
            maxSizeMB: 0.1,
            maxWidthOrHeight: 800,
            useWebWorker: true,
          };
          try {
            const compressImage = await imageCompression(file, options);
            const reader = new FileReader();
            reader.onload = () => {
              const imageUrlCompress = reader.result;
              setImageUrl(imageUrlCompress);
            };
            reader.readAsDataURL(compressImage);
          } catch (error) {
            console.log(error.message);
          }
        }
      };
      return (
        <div>
          <Form
            action={addUser}
            className="max-w-md mx-auto mt-20 p-2 bg-white border rounded-lg shadow-lg"
          >
            {/* Image for mobile view */}
            <div className="max-w-md mx-auto px-10 p-2 rounded-md flex flex-col justify-center items-center">
              <Image
                className="block rounded-full shadow-xl mx-auto -mt-16 h-48 w-48 object-cover"
                src={imageUrl}
                width={300}
                height={300}
                alt="user image"
              />
              <label className="text-base text-gray-500 font-semibold mb-2 block">
                Upload Image
              </label>
              <input
                type="file"
                accept="image/*"
                readOnly
                onChange={handelChangeImage}
                className="w-min text-gray-400 font-semibold text-sm bg-white border file:cursor-pointer cursor-pointer file:border-0 file:py-3 file:px-4 file:mr-4 file:bg-gray-100 file:hover:bg-gray-200 file:text-gray-500 rounded"
              />
              <input hidden value={imageUrl} readOnly name="imageUrl" />
            </div>
            <div className="mb-4">
              <input
                className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                name="name"
                type="text"
                placeholder="Enter your name"
              />
            </div>
            <div className="mb-4">
              <input
                className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                name="email"
                type="email"
                placeholder="Enter your email"
              />
            </div>
            <div className="mb-4">
              <input
                className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                name="job"
                type="text"
                placeholder="Enter your job"
              />
            </div>
            <button
              className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
              type="submit"
            >
              add user
            </button>
          </Form>
        </div>
      );
    };
    
    export default FormUser;

    Create addUser.js as a server function

  • 1.create action.js file in app directory

  • "use server";
    import connect from"./mongo";
    import User from"./User";
    import { revalidatePath } from "next/cache";
    import { redirect } from "next/navigation";

  • export const addUser=async (formData) => {
      const { id, name, email, imageUrl } =Object.fromEntries(formData);
      try {
        connect();
        const newUser=newUser({
          id,
          name,
          email,
          imageUrl,
        });
        await newUser.save();
      } catch (error) {
        console.log(error);
      }
      revalidatePath("/");
      redirect("/success");
    };

    Create success page in app directory

  • 1. inside folder create page.jsx

  • import React from "react";
    
    const page = () => {
      return (
        <div className="w-screen h-screen">
          <div
            className="bg-green-200 border-green-600 text-green-600 border-l-4 p-4"
            role="alert"
          >
            <p className="font-bold">Success</p>
            <p>Congratulations, you are creating user successfully.</p>
          </div>
        </div>
      );
    };
    export default page;

    Create mongo.js file

  • 1.install MongoDB & mongoose

    npm i mongoose && npm i mongodb
  • 2.create connect function

  • import mongoose from "mongoose";
    const connect=async () => {
      try {
        await mongoose.connect(process.env.MONGO);
        console.log("connect good");
      } catch (err) {
        throw new Error("connection failed !");
      }
    };
    export default connect;

    create User.js modal for mongoDb collection


    import mongoose from "mongoose";
    const { Schema } =mongoose;

    const userSchema=newSchema(
      {
        name: {
          type:String,
          unique:true,
          required:true,
          min:3,
          max:20,
        },
        email: {
          type:String,
          unique:true,
          required:true,
          match: /.+\@.+\..+/,
        },
        imageUrl: {
          type:String,
          required:false,
        },
        job: {
          type:String,
          required:false,
        },
      },
      { timestamps:true }
    );

    const User=mongoose.models?.users||mongoose.model("users", userSchema);
    export default User;

    Conclusion

    By integrating server-side image upload and compression in Next.js 15, you can significantly enhance your application's performance and user experience. This guide has provided all the necessary steps to set up and optimize the process effectively.

    If you want to read more information about how to boost traffic on your Website just visit -->other videos


Explore the latest insights, articles,free components, and expert advice on programming and software development

© Copyright 2024 MED DAKIR. All rights reserved./privacy policyTerms & Conditions