SaaS 애플리케이션의 모의 스크린샷 기능

음, 최근 클라이언트를 위한 SaaS 애플리케이션을 작업하는 동안 애플리케이션을 통해 전체 페이지의 스크린샷을 찍어 이미지 또는 PDF 형식으로 요청된 사용자에게 이메일로 보낼 수 있는 기능을 발견했습니다. 저는 이 기능에 흥미를 느꼈고 여기에서 공유할 생각을 했습니다.

1단계: 설정 - Node.js 및 Express.js를 사용하여 디자인한 백엔드가 필요합니다. 이 백엔드는 스크린샷을 찍어 프런트엔드와 함께 메일로 보냅니다. 및 는 첨부된 저장소에서 찾을 수 있습니다.

2단계: UI - 솔직히 SasS 애플리케이션의 UI는 메트릭 카드, 목표 스코어카드, 차트 등으로 구성된 많은 지루한 데이터를 표시하기 때문에 상당히 지루할 수 있습니다. 따라서 이 블로그를 약간 흥미롭게 만들기 위해 UI 표시 Pokemons를 좋아하지 않는 사람이 있기 때문에 Pokemon 카드 모음입니다.


3단계: 백엔드 - 이제 UI가 있으므로 백엔드를 구축해 보겠습니다. 매우 간단할 것입니다. 프런트엔드에서 "스크린샷 내보내기"버튼을 클릭할 때 호출되는 경로가 있을 뿐입니다.

const express = require("express")
let cors = require("cors")

const { sendEmail } = require("./helpers/helper")

const app = express()
app.use(cors())
app.use(express.json())

app.get("/", (req, res) => {
  res.send("backend home route")
})

app.post("/send-screenshot", async (req, res) => {
  const { receiversEmail } = req.body

  try {
    await sendEmail(receiversEmail)
    res.status(200).send("Email sent successfully")
  } catch (err) {
    res.status(400).send("Error in sending the email with screenshot")
  }
})

app.listen(4000, () => {
  console.info("Backend is running on port 4000")
})


4단계: 스크린샷 - 이제 프런트엔드와 백엔드가 준비되었으므로 스크린샷 APIquery builder를 사용하여 스크린샷에 대한 쿼리를 설계해 보겠습니다.

여기서는 현재 페이지의 전체 페이지 스크린샷을 고해상도로 얻기 위해 쿼리를 설계했습니다.

다음은 내가 사용하고 있는 옵션에 대한 설명입니다.

  • 전체 페이지 스크린샷 - 스크롤 가능한 영역을 포함한 전체 페이지를 의미합니다.

  • Retina - 이렇게 하면 스크린샷이 고해상도로 캡처됩니다
  • .

  • 지연 로드 - 스크린샷을 찍기 전에 모든 콘텐츠가 로드되었는지 확인합니다
  • .

  • 새로운 스크린샷 - 스크린샷.api는 서버에 있는 모든 스크린샷을 캐시하므로 매번 새 스크린샷을 받을 수 있도록 이것을 사용합니다. 또는 표시된 데이터가 민감한 경우 스크린샷이 서버에 캐시되지 않도록 하는 "스크린샷 삭제"기능을 사용할 수 있습니다.

  • 로드 이벤트 - 이 기능에는 많은 미묘한 차이가 있으며 올바르게 사용하면 많은 시간을 절약할 수 있습니다. 기본적으로 "로드"로 설정되어 있지만 페이지에 많은 이미지가 있고 분명히 해당 이미지를 로드하는 데 시간이 걸리는 시나리오를 상상해 보십시오. 이제 페이지의 모든 이미지가 따라서 스크린샷은 여기에서 "networkidle"옵션을 사용해야 합니다. 즉, 기본적으로 API는 모든 네트워크 호출이 완료될 때까지 기다린 다음 스크린샷만 찍을 것입니다.

  • 또한 공개 웹사이트의 스크린샷을 찍고 싶다면 두 가지 옵션을 따르는 것이 가장 중요합니다. "광고 차단"및 "쿠키 배너 없음".

    마지막으로 쿼리는 다음과 같습니다.https://shot.screenshotapi.net/screenshot?token=<YOUR_API_TOKEN>&url=<FORNTEND_URL>&full_page=true&fresh=true&output=image&file_type=jpeg&lazy_load=true&retina=true&wait_for_event=networkidle
    추신. 프런트엔드 URLngrok의 경우 사용할 수 있습니다.

    5단계: 이메일 - nodemailer을 사용하여 스크린샷을 보냅니다. screenshot.api는 스크린샷의 URL을 포함하는 screenshot 키를 포함하는 JSON 응답을 다시 보냅니다. 이제 이미지를 이메일로 보내려면 먼저 이미지를 가져와서 fs 모듈을 사용하여 디스크에 쓴 다음 nodemailer를 사용하여 보내야 합니다. 아래에 코드를 첨부합니다.

    const nodemailer = require("nodemailer")
    const axios = require("axios")
    const fs = require("fs")
    
    const { SCREENSHOT_API_TOKEN } = require("./credentials")
    const path = require("path")
    
    const takeScreenshot = async () => {
      try {
        var query = "https://shot.screenshotapi.net/screenshot"
        let url = "<FRONTEND_URL>"
        query += `?token=${SCREENSHOT_API_TOKEN}&url=${url}&full_page=true&fresh=true&output=image&file_type=jpeg&lazy_load=true&retina=true&wait_for_event=networkidle`
        const response = await axios.get(query)
    
        console.info(JSON.stringify(response.data))
    
        const imageStream = await axios.get(screenshotURL, {
          responseType: "stream",
        })
        return imageStream
      } catch (err) {
        console.error("\nError while taking the screenshot", err)
        throw err
      }
    }
    
    const sendEmail = async (receiversEmail) => {
      try {
        let mailerConfig = {
          host: "smtp.gmail.com",
          port: 587,
          secure: false, // true for 465, false for other ports
          auth: {
            user: "<GMAIL_ID>", // user
            pass: "<APP_PASSWORD>", // password
          },
        }
    
        let transporter = nodemailer.createTransport(mailerConfig)
    
        const imageStream = await takeScreenshot()
    
        const imagePath = path.join(__dirname, "..", "output", "screenshot.png")
        imageStream.data
          .pipe(fs.createWriteStream(imagePath))
          .on("finish", () => {
            // send mail with defined transport object
            let info = await transporter.sendMail({
              from: "<SENDER'S EMAIL ADDRESS>", // sender address
              to: `${receiversEmail}`, // list of receivers
              subject: "Screenshot requested", // Subject line,
              attachment: [
                {
                  filename: imagePath,
                  content: imageBuffer,
                  encoding: "base64",
                },
              ],
              text: "Hello! find the screenshot that you requested attached", // plain text body
              html: "<b>Hello! find the screenshot that you requested attached</b>", // html body
            })
          })
          .on("error", (err) => {
            console.error("Stream closed with following error: ", err)
          })
        return true
      } catch (err) {
        console.error("\nError in sending the email", err)
        throw err
      }
    }
    
    module.exports = {
      sendEmail,
    }
    


    추신. Gmail 계정을 사용하려면 앱 비밀번호를 생성해야 합니다. 자세한 내용은 찾을 수 있습니다here.

    ❤ 이 블로그 게시물이 좋아요? 나를 팔로우하세요

    내 다른 블로그 게시물을 확인하세요.


  • 좋은 웹페이지 즐겨찾기