gatsby_使用Gatsby和Netlify函数构建无限滚动图片库

gatsby

What's the trend about static sites and decoupled development architectures with the JAMStack? Why are top sites and apps moving to build with "static site generators"? It's speed, security, affordability, developer experience and much more. We are here for it all.

JAMStack对静态站点和分离的开发架构有何趋势 ? 为什么热门网站和应用程序会迁移到使用“静态网站生成器”进行构建? 它的速度,安全性,可负担性,开发人员经验等等。 我们在这一切。

Static sites are known over time as fast sites which serve static content from a CDN without any web server or API interaction. Modern build tools currently furnish sites with the speed and security of static sites along with the dynamism of fetching and interacting with data from APIs during runtime.

随着时间的流逝,静态站点被称为快速站点,无需任何Web服务器或API交互即可提供CDN中的静态内容。 当前,现代构建工具为站点提供了静态站点的速度和安全性,以及在运行时从API获取数据并与之交互的动态性。

In this post, we'll build a performant Infinite Scroll Image gallery using Gatsby.js, which is served over a CDN and uses Netlify functions to serve data from an API during runtime.

在本文中,我们将使用Gatsby.js构建性能卓越的 Infinite Scroll Image画廊,该画廊通过CDN进行投放,并使用Netlify函数在运行时从API提供数据。

TL:DR ( TL : DR )

In this post, we will:

在这篇文章中,我们将:

  • Setup a Gatsby site locally using the Gatsby CLI.

    使用Gatsby CLI在本地设置Gatsby站点。
  • Create pages in the Gatsby site.

    在Gatsby网站中创建页面。
  • Handle consistent layout across the site.

    处理整个站点的一致布局。
  • Create an Infinite Scroll Image masonry.

    创建无限滚动图像砌体。
  • Create a Netlify function to fetch Images.

    创建一个Netlify函数来获取图像。
  • Deploy and consume Netlify functions locally.

    在本地部署和使用Netlify功能。
  • Render fetched images in a grid gallery.

    在网格库中渲染获取的图像。
  • Configure netlify.toml file.

    配置netlify.toml文件。
  • Deploy the app to Netlify.

    将应用程序部署到Netlify。

为什么选择盖茨比? ( Why Gatsby? )

Gatsby is an open-source static site generator for building modern static sites. Gatsby offers the ability to build performant, secure and affordable deployable sites. Absolving the need for a web server, this mitigates the risk of security breaches pertinent to web servers. Gatsby also offers the rich developer experience by way of building the sites in React.js, thus merging the existing vibrant React.js ecosystem.

Gatsby是用于构建现代静态站点的开源静态站点生成器。 Gatsby提供了构建高性能,安全和负担得起的可部署站点的功能。 消除了对Web服务器的需求,这减轻了与Web服务器相关的安全漏洞的风险。 Gatsby还通过在React.js中构建站点,从而合并了现有的充满活力的React.js生态系统,提供了丰富的开发人员经验。

Since developing with Gatsby is done in React, application logic including server calls can be written in the component lifecycle methods or even as application-wide logic. These will be executed at runtime, hence the notion "Static-Dynamic". On the data layer of Gatsby applications, Gatsby uses GraphQL to make data queries.

由于使用Gatsby进行开发是在React中完成的,因此包括服务器调用在内的应用程序逻辑可以写在组件生命周期方法中,甚至可以写成应用程序范围的逻辑。 这些将在运行时执行,因此称为“静态动态”。 在盖茨比应用程序的数据层上,盖茨比使用GraphQL进行数据查询。

Other static site generators abound the internet which allows the creation of static sites, the question is, how efficient are they at building these sites? With the Gatsby CLI, creating an optimized single-paged app is a command away, with little effort put towards performance optimizations.

Internet上还有许多其他静态站点生成器,可以创建静态站点,问题是,它们在构建这些站点方面的效率如何? 使用Gatsby CLI,创建优化的单页应用程序成为一项命令,而无需花大力气进行性能优化。

Performance Shenanigans: Scroll to the end of this post to see the lighthouse audit run on the deployed app.

Performance Shenanigans:滚动到这篇文章的末尾,以查看在已部署的应用程序上运行的灯塔审核。

为什么要Netlify? ( Why Netlify? )

Netlify offers a rich deployment experience for modern applications. Touting an intuitive CI/CD platform as well as utilizing and managing AWS Lambda functions directly on Netlify, deploying static-dynamic applications as we would in this tutorial becomes seamless.

Netlify为现代应用程序提供了丰富的部署体验。 宣传直观的CI / CD平台,以及直接在Netlify上利用和管理AWS Lambda函数,就像在本教程中一样,部署静态动态应用程序变得无缝。

In this post, we would create a netlify function to fetch images using the Unsplash API. This lambda function will be tested locally using netlify-lambda and deployed alongside the application to Netlify.

在本文中,我们将创建一个netlify函数来使用Unsplash API来获取图像。 该lambda函数将使用netlify-lambda在本地进行测试,并与应用程序一起部署到Netlify。

Functions ship with a memory capacity of 128MB, this is just enough to handle our use case, however for more computational power and workload, you can increase the memory capacity of your functions.

函数附带的存储容量为128MB,这足以应付我们的用例,但是为了获得更多的计算能力和工作量, 您可以增加函数的存储容量

You can find other amazing features offered by Netlify.

您可以找到Netlify提供的其他惊人功能

Here's what we'll be building in this article:

这是我们将在本文中构建的内容:

安装 ( Installation )

For this tutorial, knowledge of HTML, CSS, JavaScript, and React is required.

对于本教程,需要具备HTML,CSS,JavaScript和React的知识。

Node.js and its package manager NPM is required for this app. Check if you have them installed with:

此应用程序需要Node.js及其程序包管理器NPM。 检查是否安装了它们:

node -v&& npm -v

This command would output the versions of both node and npm. If not installed, proceed to Nodejs.org to download and install node and its package manager.

此命令将输出node和npm的版本。 如果未安装,请继续到Nodejs.org下载并安装节点及其包管理器。

Install the Gatsby CLI globally with:

通过以下方式全局安装Gatsby CLI:

npm i -g gatsby-cli

Once the CLI tool is installed, open a new folder and create a new Gatsby project using the default starter. Do this with:

一旦安装了CLI工具,请使用默认启动器打开一个新文件夹并创建一个新的Gatsby项目。 为此,请执行以下操作:

gatsby new gastify

This command clones the default Gatsby starter into the folder and installs all required dependencies specified in the project.

此命令会将默认的Gatsby启动器克隆到该文件夹​​中,并安装项目中指定的所有必需依赖项。

Gatsby ships with starters which are preset websites or apps with which you can quickly build your site off.

Gatsby附带了启动器,这些启动器是预置的网站或应用程序,您可以使用它们快速构建网站。

Change directory to the project directory and install the required dependencies with:

将目录更改为项目目录,并使用以下命令安装所需的依赖项:

cd gastify && npm i --save axios bulma react-infinite-scroll-component

Here's a summary of the components:

以下是这些组件的摘要:

Once these are installed, start a development server with:

一旦安装了这些,请使用以下命令启动开发服务器:

gatsby develop

This spins up a dev server on localhost:8000. Gatsby ships with a hot reloading feature, so any changes to the source file reload the page in the browser instantaneously.

这将在l ocalhost:8000上启动一个开发服务器。 Gatsby附带了热重载功能,因此对源文件的任何更改都会立即在浏览器中重载该页面。

The Gatsby project currently contains default files and configuration shipped with the starter. We will proceed to develop the layout and style.

Gatsby项目当前包含启动程序随附的默认文件和配置。 我们将继续开发布局和样式。

项目结构 ( Project Structure )

Everything in Gatsby, just like React, is a component. Gatsby is unique in the way that it serves individually exported JS files in the src/pages folder as a page in the app. Each page can be navigated to using the <Link/> component in Gatsby.

就像React一样,Gatsby中的所有内容都是组件。 Gatsby的独特之处在于它可以将src/pages文件夹中单独导出的JS文件作为应用程序中的页面提供。 可以使用Gatsby中的<Link/>组件将每个页面导航至。

In this project, individual components are written in src/components. Each exported component can be reused in the entirety of the app.

在这个项目中,各个组件都写在src/components 。 每个导出的组件都可以在整个应用程序中重复使用。

Gatsby provides other default files to extend the functionality further or configure the app. gatsby-config.js contains the config for all plugins used in the app. Those currently installed and configured were shipped along with the default starter.

Gatsby提供了其他默认文件以进一步扩展功能或配置应用程序。 gatsby-config.js包含应用程序中使用的所有插件的配置。 当前安装和配置的那些与默认启动器一起提供。

配置网站布局 ( Configure Site Layout )

The site layout will be developed as a component and reused across the application. The components/layout.js file currently exports the layout of the app as designed in the starter. Remove all the content of the layout.js file, import all required dependencies and components with:

网站布局将作为组件开发,并在整个应用程序中重复使用。 目前, components/layout.js文件会按照启动程序中的设计导出应用程序的布局。 删除layout.js文件的所有内容,并使用layout.js命令导入所有必需的依赖项和组件:

import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"

import Header from "./header"

Here, React and prop-types were imported alongside useStaticQuery and GraphQL. useStaticQuery, shipped in Gatsby v2 allows us to make GraphQL data queries in non-page components. This data fetching is static and happens during build, hence the term Static Query.

在这里,React和prop-types与useStaticQuery和GraphQL一起导入。 Gatsby v2中附带的useStaticQuery允许我们在非页面组件中进行GraphQL数据查询。 这种数据获取是静态的,并且在构建期间发生,因此称为“静态查询”。

The Header component which houses the navbar is also imported in the component. This Header component will be created shortly. Define and export the Layout component with the following:

容纳导航栏的Header组件也已导入到该组件中。 这个Header组件将很快创建。 使用以下内容定义和导出Layout组件:

const Layout = ({ children }) => {
  const data = useStaticQuery(graphql`query SiteTitleQuery {
      site {
        siteMetadata {
          title
        }
      }
    }`)

  return (
    <>
      <Header siteTitle={data.site.siteMetadata.title} />
      <div
        style={{
          margin: `0 auto`,
          maxWidth: 900,
          padding: `0px 1.0875rem 1.45rem`,
          paddingTop: 0,
        }}
      >
        <main>{children}</main>
      </div>
    </>
  )
}

Layout.propTypes = {
  children: PropTypes.node.isRequired,
}

export default Layout

Here the useStaticQuery hook is used to fetch the site title from the siteMetadata. This siteTitle is subsequently passed in the header component as props. The base style for the div enclosing the children of the layout is also configured.

在这里, useStaticQuery挂钩用于从siteMetadata获取网站标题。 随后,此siteTitle作为道具传递到标头组件中。 包含布局子级的div的基本样式也已配置。

Go on ahead to gatsby-config.js in the root directory to change the site title and description. Modify the siteMetada property to:

继续转到根目录中的gatsby-config.js ,以更改站点标题和描述。 将siteMetada属性修改为:

siteMetadata: {
    title: `Gastify`,
    description: `Here lies a doggo Infinite scroll Image gallery built with Gatsby, Netlify Functions and the Unsplash API`,
    author: `@iChuloo`,
  },

In components/header.js, import the required modules and components with:

components/header.js ,使用以下命令导入所需的模块和组件:

import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"

Create the Header functional component which defines a siteTitle prop with:

创建Header功能组件,该组件使用以下命令定义siteTitle道具:

const Header = ({ siteTitle }) => (
  <header>
    <nav className="navbar is-dark" style={{ marginBottom: "2em" }}>
      <div className="navbar-brand">
        <Link
          to="/"
          style={{
            marginLeft: "3em",
            padding: "10px",
          }}
          className="has-text-white is-size-3"
        >
          {siteTitle} 🐶
        </Link>
      </div>
      <div className="navbar-end" style={{ marginRight: "3em" }}>
        <div className="navbar-item">
          <Link
            to="/"
            style={{
              padding: "10px",
            }}
            className="has-text-white"
          >
            Home
          </Link>
          <Link
            to="/gallery/"
            style={{
              padding: "10px",
            }}
            className="has-text-white"
          >
            Gallery
          </Link>
        </div>
      </div>
    </nav>
  </header>
)

export default Header

Two routes were designated in the navbar, while / directs to the homepage, /gallery/ directs to the gallery page to be created shortly. The <Link/> component shipped with gatsby is used to navigate the routes in the single-paged app and ships with its own to attribute which accepts the slug of the route.

导航栏中指定了两条路线,而/指向首页, /gallery/指向即将创建的图库页面。 gatsby随附的<Link/>组件用于在单页应用程序中导航路线,并带有其自己的to属性,该属性接受路线的信息。

Bulma classes were used to style this component. For Bulma to work, we will import it in the index.js page shortly.

Bulma类用于设置此组件的样式。 为了让Bulma正常工作,我们很快会将其导入index.js页面。

Next, we will utilize this layout component on the homepage.

接下来,我们将在主页上使用此布局组件。

创建网站页面 ( Create Site Pages )

主页 (Home Page)

In src/pages/index.js, wipe the default starter code in the file and import required dependencies and components with:

src/pages/index.js ,擦除文件中的默认入门代码,并使用以下命令导入所需的依赖项和组件:

import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import "bulma/css/bulma.min.css"

Notice how the minified Bulma CSS file was imported. Also, the Layout component was imported alongside the SEO component, which was included in the starter by default.

请注意,如何导入缩小的布尔玛CSS文件。 另外,Layout组件是与SEO组件一起导入的,SEO组件默认情况下已包含在启动器中。

Define and export the page using the imported components with:

使用导入的组件通过以下方式定义和导出页面:

const IndexPage = () => (
  <Layout>
    <SEO title="Home" />
    <div className="has-text-centered" style={{ marginTop: "20%" }}>
      <h1 className="is-size-2">Welcome to Pride Rock! . . . or nah 😹</h1>
      <p className="is-size-5" style={{ marginTop: "2%" }}>
        Find within, a fire doggo infinite image gallery built with Gatsby, and
        Images served using Netlify functions from Unsplash. Perfecto!
      </p>
      <button className="button is-dark is-large" style={{ marginTop: "10%" }}>
        <Link to="/gallery/" className="has-text-white">
          Open Sesame! 🔥
        </Link>
      </button>
    </div>
  </Layout>
)

export default IndexPage

Bulma classes were also used to style this page.

Bulma类也用于设置此页面的样式。

In the same src/pages directory, create a new folder named gallery.js. Similar to the index page, import the SEO component as well as the Layout component. Do this with:

在相同的src/pages目录中,创建一个名为gallery.js的新文件夹。 与索引页面类似,导入SEO组件以及Layout组件。 为此,请执行以下操作:

import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"

Create and export the page component with:

使用以下命令创建和导出页面组件:

const Gallery = () => {
  return (
    <Layout>
      <SEO title="Gallery" />
      <h1 className="is-size-3">Images from Unsplash...</h1>
      <p style={{ marginBottom: "5%" }}>
        Now this is the Law of the Jungle, as old and true as the sky, for as
        long as you keep scrolling, you shall find more doggo images 🐶 🐕.
      </p>
    </Layout>
  )
}

export default Gallery

Once you save the page, the browser should refresh with the complete pages though the gallery page will only have the text and no images yet.

保存页面后,浏览器应刷新整个页面,尽管图库页面仅包含文本,但没有图像。

You can restart the dev server to rebuild.

您可以重新启动开发服务器以进行重建。

Like we stated earlier, the good thing about building with tools like Gatsby is we can make API calls in components and pass the data to the DOM during runtime, giving the experience of a dynamic app in a static environment. The react-infinite-scroll-component will be used to create the infinite scroll whereas the Images will be fetched from Unsplash using netlify functions.

如我们前面所述,使用Gatsby之类的工具进行构建的好处是,我们可以在组件中进行API调用,并在运行时将数据传递给DOM,从而在静态环境中提供动态应用程序的体验。 react-infinite-scroll-component将用于创建无限滚动,而图像将使用netlify函数从Unsplash中获取。

In src/components create a new component named InfiniteImages.js. In the component, import the required dependencies with:

src/components创建一个名为InfiniteImages.js的新组件。 在组件中,使用以下命令导入所需的依赖项:

import React from "react"
import PropTypes from "prop-types"
import InfiniteScroll from "react-infinite-scroll-component"

For this gallery, we'll need two components:

对于此画廊,我们将需要两个组件:

  1. A component to hold the Image gallery view.

    用于保存图片库视图的组件。
  2. A component to handle state, data fetching and propagation to the Image gallery view.

    处理状态,数据获取以及传播到图库视图的组件。

These components can be split into further subcomponents but for the sake of simplicity, we'll leave it at these two and even have them co-located in the same file.

这些组件可以拆分为更多子组件,但是为了简单起见,我们将其保留在这两个组件中,甚至将它们放置在同一文件中。

In InfiniteImages.js, create a functional component after the dependency imports named ImageGallery. This is the gallery view. Define the components to accept props of images, loading, and fetchImages. Do this with:

InfiniteImages.js ,在名为ImageGallery的依赖项导入之后创建一个功能组件。 这是图库视图。 定义组件以接受imagesloadingfetchImages道具。 为此,请执行以下操作:

import ...

const ImageGallery = ({ images, loading, fetchImages }) => {
  // Create gallery here
  return (
    <InfiniteScroll
      dataLength={images.length}
      next={() => fetchImages()}
      hasMore={true}
      loader={
        <p style={{ textAlign: "center", marginTop: "1%" }}>
          More doggo incoming 🐕 🐕...
        </p>
      }
    >
      <div className="image-grid">
        {!loading
          ? images.map(image => (
              <div className="image-item" key={image.id}>
                <img src={image.urls.regular} alt={image.alt_description} />
              </div>
            ))
          : ""}
      </div>
    </InfiniteScroll>
  )
}

The InfiniteScroll component imported takes props of:

导入的InfiniteScroll组件具有以下特性:

  • dataLength: The length of the rendered data.

    dataLength:呈现的数据的长度。
  • next: A function to be called once a scroll threshold is reached.

    next:一旦达到滚动阈值,便要调用的函数。
  • hasMore: A boolean to indicate the existence of more data to be rendered on fetch.

    hasMore:一个布尔值,指示存在更多要在获取时呈现的数据。
  • Loader: A component or string to the displayed when images are being fetched.

    加载程序:获取图像时显示的组件或字符串。

In the infinite scroll, the array of images passed through the images prop is traversed and Images rendered in a grid. Properties of each image object are passed as data to the key, alt value and ultimately the image src.

在无限滚动中,遍历通过images属性的images数组,并在网格中呈现图像。 每个图像对象的属性都作为数据传递给keyalt值,最后传递给图像src

The masonry is styled with css-grid. Create a custom CSS file named gallery.css in the components folder and edit it to:

砌体采用css-grid样式。 在components文件夹中创建一个名为gallery.css的自定义CSS文件,并将其编辑为:

.image-grid {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  grid-auto-rows: minmax(50px, auto);
}

.image-grid .image-item:nth-child(5n) {
  grid-column-end: span 2;
}

.image-grid img {
  display: flex;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Import the CSS file to the InfiniteImages.js component with:

使用以下命令将CSS文件导入到InfiniteImages.js组件中:

import "./gallery.css"

With the view complete, let's set up the parent component handling fetch from the API.

完成视图后,让我们设置处理从API提取的父组件。

Create a component in InfiniteImages.js named InfiniteImages.

InfiniteImages.js创建一个名为InfiniteImages的组件。

This functional component uses the React useState and useEffect hooks to handle state and lifecycle computation, respectively. Axios is also used to make HTTP requests. Import Axios and the hooks in InfiniteImages.js with:

该功能组件使用React的useStateuseEffect钩子分别处理状态和生命周期计算。 Axios也用于发出HTTP请求。 使用以下命令导入Axios和InfiniteImages.js的钩子:

import React, { useState, useEffect } from "react"
import axios from "axios"

// Component logic below

With hooks imported, define the InfiniteImage component with:

导入钩子后,使用以下命令定义InfiniteImage组件:

const InfiniteImages = () => {
  // Hold state
  const [images, setImages] = useState([])
  const [loading, setLoading] = useState(true)

  // Fetch images on component mount
  useEffect(() => {
    fetchImages()
  }, [])


    // API endpoint
    const endpoint = "<Endpoint here once available>"

    // Fetch Images from functions
  const fetchImages = () => {
    axios(endpoint).then(res => {
      setImages([...images, ...res.data.images])
      setLoading(false)
    })
  }
  return (
    <ImageGallery images={images} loading={loading} fetchImages={fetchImages} />
  )
}

Here, we created state variables to hold the fetched images and also to store the state of the fetch operation. The images variable defaults to an empty array while the loading variable defaults to true as we assume by default, the images are loading once the component mounts.

在这里,我们创建了状态变量来保存获取的图像并存储获取操作的状态。 像我们默认假定的那样, images变量默认为空数组,而load变量默认为true因为我们默认情况下,一旦安装了组件,图像就会加载。

The useEffect hook is used to call the fetchImages function once the component is mounted. An empty array as a second argument signifies that the function will only run when the component mounts.

挂载组件后, useEffect挂钩用于调用fetchImages函数。 空数组作为第二个参数表示该函数仅在安装组件时运行。

A fetchImages function is created which uses axios to make a GET request to a specified API. The returned data is spread in the images array in state. Thus any new data fetched is added to existing ones in state. The loading variable is also set to false as the fetch operation is complete.

创建了一个fetchImages函数,该函数使用axios向指定的API发出GET请求。 返回的数据以状态散布在images数组中。 因此,将获取的任何新数据添加到状态中的现有数据中。 当获取操作完成时, loading变量也设置为false。

The ImageGallery component earlier created is used to render the gallery with the required data.

先前创建的ImageGallery组件用于使用所需数据渲染图库。

Assign the Proptypes to the ImageGallery component and export the InfiniteImage module with:

将Proptypes分配给ImageGallery组件,并使用以下命令导出InfiniteImage模块:

import...

const ImageGallery = ({ images, loading, fetchImages }) => {
  // Create gallery here
  return (
    // Component logic here
  )
}

const InfiniteImages = () => {
  // Component logic here
}

ImageGallery.propTypes = {
  images: PropTypes.array,
  loading: PropTypes.bool,
  fetchImages: PropTypes.func,
}

export default InfiniteImages

With this, we have the gallery set up, what's missing is the API endpoint. We'll proceed to define a Netlify function to handle that.

这样,我们就可以建立图库,而缺少API端点。 我们将继续定义一个Netlify函数来处理它。

创建Netlify函数 ( Create The Netlify Function )

Netlify functions are AWS lambdas managed directly on Netlify. With this, we abstract the management and scaling of a traditional server. Multiple functions can be created and used across an application after the application is built.

Netlify函数是直接在Netlify上管理的AWS Lambda。 这样,我们就抽象了传统服务器的管理和扩展。 构建应用程序后,可以在应用程序中创建和使用多种功能。

These functions in JavaScript are .js files stored in any designated directory in the project's repository and specified on Netlify or in the netlify.toml config file in the root directory of a project.

JavaScript中的这些函数是.js文件,它们存储在项目资源库中任何指定的目录中,并在Netlify或项目根目录中的netlify.toml配置文件中指定。

Creating a Netlify function is seamless. It is either created in a functions directory or a build tool is used to create the function from a source folder into the functions folder.

创建Netlify函数是无缝的。 它可以在功能目录中创建,也可以使用构建工具从源文件夹到功能文件夹中创建功能。

If you are familiar with backend development, creating node servers and APIs would probably be a breeze, for Netlify Functions written in JavaScript, knowledge of Nodejs is not compulsory as Netlify ships Netlify-lambda. This is a tool to help with building Netlify functions from modern JavaScript workflows using webpack/babel.

如果您熟悉后端开发,那么创建节点服务器和API可能会轻而易举,对于用JavaScript编写的Netlify函数,由于Netlify提供了Netlify-lambda,因此对Node.js的了解并不是强制性的。 这是一个使用webpack / babel从现代JavaScript工作流中构建Netlify函数的工具。

We will employ this in this tutorial to build functions written in ES6 syntax into a functions directory.

在本教程中,我们将利用它来将以ES6语法编写的函数构建到functions目录中。

For this gallery, we will query a free Unsplash API to obtain super cute images of dogs and display them in a masonry. Head to Unsplash, signup to create a new app and get an access key.

对于这个画廊,我们将查询一个免费的Unsplash API,以获取超可爱的狗的图像并将其显示在砌体中。 前往Unsplash,注册以创建新应用并获取访问密钥

While this API can be consumed directly in the app, we would like to abstract this image fetching process to our API, thus securing access/private keys or any other backend logic. In other applications, business or other logic can also go in our API.

虽然可以直接在应用程序中使用此API,但我们希望将此图像提取过程抽象到我们的API中,从而确保访问/私钥或任何其他后端逻辑的安全。 在其他应用程序中,业务或其他逻辑也可以包含在我们的API中。

安装功能构建工具 (Install Functions Build tool)

netlify-lambda CLI is used to run functions locally as well as create a deployable build. These functions can be written with modern JS workflows before being bundled into a single build using webpack/babel. For this project, we'll create a folder to house the locally written functions as well as the deployable functions.

netlify-lambda CLI用于在本地运行功能以及创建可部署的内部版本。 这些功能可以在使用webpack / babel捆绑到单个版本中之前,用现代JS工作流编写。 对于此项目,我们将创建一个文件夹来容纳本地编写的函数以及可部署的函数。

Install the netlify-lambda CLI with:

使用以下命令安装netlify-lambda CLI:

npm i -g netlify-lambda

With this we can serve the functions locally with:

这样,我们可以通过以下方式在本地提供功能:

netlify-lambda serve<path-to-source-folder>

A deployable build can be created with :

可以使用以下命令创建可部署的构建:

netlify-lambda build<path-to-source-folder>

创建功能和源目录 (Create a Function and Source Directory)

Create a folder in the src directory named lambda. This serves as the source folder will contain all the functions as written. Create a second folder in the root directory of the project named functions. This, in turn, will hold all deployable functions. For Netlify to recognize the functions folder, we need to specify it in the Netlify config file. Create a file in the root directory of the project named netlify.toml. Add this config with:

src目录中创建一个名为lambda的文件夹。 这用作源文件夹,其中将包含所有编写的功能。 在项目的根目录中创建第二个文件夹,命名为functions 。 反过来,它将保留所有可部署的功能。 为了使Netlify能够识别功能文件夹,我们需要在Netlify配置文件中指定它。 在名为netlify.toml的项目的根目录中创建一个文件。 使用以下命令添加此配置:

[build]
  Functions = "functions"

This specifies that the functions for the app can be found in the functions directory in the app root. Once this app is deployed, each function will be available on:

这指定可以在应用程序根目录的功能目录中找到该应用程序的功能。 部署此应用后,每个功能将在以下位置可用:

https://<root-url-of-app>/.netlify/functions/<function-name>

定义获取功能 (Define The Fetch Function)

Lambda functions are JS files which export a handler method. Each function takes three parameters:

Lambda函数是JS文件,可导出处理程序方法。 每个函数都有三个参数:

  • event: This is an object received when the function is triggered.

    事件:触发功能时收到的对象。
  • context: This contains the conditions in which the function was called.

    上下文:这包含调用函数的条件。
  • callback: This is returned on function execution and contains the error if any, as the first parameter. It also contains a response payload as the second.

    callback:函数执行后返回,并包含错误(如果有)作为第一个参数。 它还包含一个响应有效负载作为第二个。

In the project, create a file named fetch.js in src/lambda, configure the function with:

在项目中,在src/lambda创建一个名为fetch.js的文件,并使用以下命令配置功能:

import axios from "axios"
import config from "../../config"

exports.handler = function(event, context, callback) {
  const apiRoot = "https://api.unsplash.com"
  const accessKey = process.env.ACCESS_KEY || config.accessKey

  const doggoEndpoint = `${apiRoot}/photos/random?client_id=${accessKey}&count=${10}&collections='3816141,1154337,1254279'`

  axios.get(doggoEndpoint).then(res => {
    callback(null, {
      statusCode: 200,
      body: JSON.stringify({
        images: res.data,
      }),
    })
  })
}

In here, axios which is imported is used to make an API call to the Unsplash API, and the returned data is sent in the callback with a status code of 200. The API Key will be stored as an environment variable on Netlify and also in a config file for local usage.

在这里,导入的axios用于对Unsplash API进行API调用,返回的数据以状态代码200发送到回调中。API密钥将作为环境变量存储在Netlify以及用于本地使用的配置文件。

Create a file named config.js in the root directory and add the API key from Unsplash with:

在根目录中创建一个名为config.js的文件,并使用以下命令从Unsplash添加API密钥:

const config = {
  accessKey: "<Add access key>",
}

export default config

Be sure to add the config file to .gitignore so it's not added to your repository if public.

确保将配置文件添加到.gitignore以便在公共情况下不会将其添加到您的存储库中。

State a dev server for the functions with:

为以下功能说明开发服务器:

netlify-lambda serve src/lambda

This creates a server on http://localhost:9000.

这将在http://localhost:9000上创建服务器。

Navigate to http://localhost:9000/fetch to see the data fetched from the API being displayed on the browser.

导航到http://localhost:9000/fetch以查看从API显示的数据正在浏览器中显示。

To create a build in the functions folder, run:

要在functions文件夹中创建构建,请运行:

netlify-lambda build src/lambda

This creates a build in the functions folder ready to be deployed.

这将在functions文件夹中创建一个准备部署的内部版本。

We have the functions set up and running, let's configure it for local usage.

我们已经设置并运行了功能,让我们对其进行配置以供本地使用。

配置本地使用功能 (Configure Function for Local Usage)

Using the function as is in the local dev server on Gatsby would throw a CORS error. Advanced proxying in Gatsby.js, affords us the ability to use a proxy middleware to proxy the functions in our local environment consequently bypassing CORS. Install http-proxy-middleware with:

在Gatsby上的本地开发服务器中按原样使用该函数将引发CORS错误。 Gatsby.js中的高级代理使我们能够使用代理中间件来代理本地环境中的功能,从而绕过CORS。 使用以下命令安装http-proxy-middleware

npm i --save-dev http-proxy-middleware

Configure the proxy middleware in gatsby-config.js with:

使用以下命令在gatsby-config.js中配置代理中间件:

let proxy = require("http-proxy-middleware")

module.exports = {
  siteMetadata: {
    // define site metadata
  },
  // Enables the use of function URLs locally
  developMiddleware: app => {
    app.use(
      "/.netlify/functions/",
      proxy({
        target: "http://localhost:9000",
        pathRewrite: { "/.netlify/functions/": "" },
      })
    )
  },
  plugins: [
    // define plugins
  ],
}

The /.netlify/functions/ endpoint in development is proxied to [http://local:9000](http://local:9000) and the path is re-written, this way [http://localhost:9000/fetch](http://localhost:9000/fetch) becomes /.netlify/functions/fetch which is also the valid local endpoint for the function.

正在开发中的/.netlify/functions/端点被代理到[http://local:9000](http://local:9000)并以这种方式重写路径[http://localhost:9000/fetch](http://localhost:9000/fetch)变为/.netlify/functions/fetch ,这也是该函数的有效本地端点。

Pass the API endpoint to the axios request in the InfiniteImages function in src/components/InfiniteImages.js. Do this with:

src/components/InfiniteImages.js中的InfiniteImages函数中,将API端点传递给axios请求。 为此,请执行以下操作:

import // ...

const ImageGallery = ({ images, loading, fetchImages }) => {
  // Component logic here
}

const InfiniteImages = () => {
  // Hold state
  const [images, setImages] = useState([])
  const [loading, setLoading] = useState(true)

  // Fetch images on component mount
  useEffect(() => {
    fetchImages()
  }, [])

  // Fetch Images from functions
  const fetchImages = () => {
    axios("/.netlify/functions/fetch").then(res => {
      setImages([...images, ...res.data.images])
      setLoading(false)
    })
  }
  return (
    <ImageGallery images={images} loading={loading} fetchImages={fetchImages} />
  )
}

ImageGallery.propTypes = {
    // Define proptypes
}

export default InfiniteImages

Restart the Gatsby dev server, while ensuring the server of the local function is running. Here's what the app looks now:

重新启动Gatsby dev服务器,同时确保本地功能的服务器正在运行。 以下是该应用的外观:

部署到Netlify ( Deploying to Netlify )

At this point, the app works on our local environment. Before deploying to Netlify, re-build the functions with:

此时,该应用程序可以在我们的本地环境中运行。 部署到Netlify之前,请使用以下方法重新构建功能:

netlify-lambda build src/lambda

Run a Gatsby build to verify the build process works without errors. Do this with:

运行Gatsby构建,以验证构建过程是否正常进行。 为此,请执行以下操作:

gatsby build

Next is to deploy to a Git provider.

接下来是部署到Git提供程序。

推送到Git提供商 (Push to Git Provider)

Create a new repository on a remote git provider. Initialize the repository on your local machine, stage all your files, commit and push to the new remote repository.

在远程git提供程序上创建一个新的存储库。 在本地计算机上初始化存储库,暂存所有文件,提交并推送到新的远程存储库。

Ensure the config.js file in the root directory is added to .gitignore.

确保将根目录中的config.js文件添加到.gitignore

在Netlify上部署 (Deploy On Netlify)

Go on to Netlify and create an account. Use the "New site from Git" button to add a new site.

继续到Netlify并创建一个帐户。 使用“来自Git的新站点”按钮添加一个新站点。

On the "Connect to Git Provider" tab, select GitHub or whichever provider you used and authorize your account. In the next tab, pick the repository you deployed to or use the search function to search for the repository.

在“连接到Git提供商”选项卡上,选择GitHub或您使用的任何提供商并授权您的帐户。 在下一个选项卡中,选择部署到的存储库,或使用搜索功能搜索存储库。

Configure the deploy settings with the build command as gatsby build and publish directory as public. Click the "Show advanced" button then the "new variable" button to add a new environment variable.

使用build命令将部署设置配置为gatsby build并将目录发布为public 。 单击“显示高级”按钮,然后单击“新变量”按钮以添加新的环境变量。

Hit the "Deploy site" button to deploy.

点击“部署站点”按钮进行部署。

Netlify deploys the site and utilizes the functions in the functions directory after build. These functions are not exposed on the client side except the functions directory is in the publish directory.

Netlify在构建后部署站点并利用functions目录中的功能。 这些功能不会在客户端公开,除非功能目录位于发布目录中。

Note that the build command, publish directory and environment variables can also be set in the netlify.toml file of the project.

请注意,还可以在项目的netlify.toml文件中设置构建命令,发布目录和环境变量。

You can find the final deployed site at https://gastify.netlify.com

您可以在https://gastify.netlify.com上找到最终部署的站点。

You can find the repository here: https://github.com/Chuloo/gatsby-netlify-functions

您可以在这里找到存储库: https : //github.com/Chuloo/gatsby-netlify-functions

Here's a peek on lighthouse audit scores of the deployed site:

以下是部署站点的灯塔审核分数:

结论 ( Conclusion )

In this post, we saw an overview of static sites, their features, importance, going dynamic with fetching dynamic content using serverless functions and an overview of serverless functions.

在这篇文章中,我们看到了静态站点的概述,它们的功能,重要性,使用无服务器功能获取动态内容而变得动态以及无服务器功能的概述。

We also built an Infinite Scroll Image gallery using Gatsby with data from a Netlify function. While the free tier of Netlify functions is substantial for building applications, it's essential to increase the memory capacity of functions to accommodate larger workloads.

我们还使用Gatsby和来自Netlify函数的数据构建了一个无限滚动图像库。 Netlify功能的免费层对于构建应用程序非常重要,但增加功能的内存容量以容纳更大的工作量至关重要。

翻译自: https://scotch.io/tutorials/build-an-infinite-scroll-image-gallery-with-gatsby-and-netlify-functions

gatsby

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值