使用环境变量破解“部署到 Netlify”按钮,创建可定制的网站生成器

Avatar of Cassidy Williams
Cassidy Williams

DigitalOcean 提供适合旅程各个阶段的云产品。使用 200 美元的免费积分 开始!

如果你像我一样,喜欢偷懒捷径。 “部署到 Netlify”按钮 让我(或你!)能够利用我这个可爱的个性特征,并用它来提高生产力。

Deploy to Netlify

点击上面的按钮,可以让我(或你!)立即克隆我的 Next.js 入门项目 并将其自动部署到 Netlify。哇!太容易了!我太高兴了!

现在,就像我经常做的那样,我前天晚上浏览按钮的文档时,注意到你可以 预填充环境变量 到使用按钮部署的网站。这让我思考……我可以用它定制什么样的网站呢?

啊,著名的“Link in Bio”,你在所有社交媒体上都能看到,当人们想让你看到他们生活中所有相关的链接时。你可以注册各种服务来为你创建这些网站,但如果你可以 自己 创建,而无需注册另一个服务,那岂不是更好?

但是,我们也很懒,喜欢捷径。听起来我们可以用“部署到 Netlify”(DTN) 按钮和环境变量来解决所有这些问题。

我们该如何构建这样的东西呢?

为了使我们的 DTN 按钮正常工作,我们需要创建两个相互协作的项目

  • 模板项目(这是将被克隆并根据传入的环境变量进行定制的仓库。)
  • 生成器项目(这是将创建应传递到按钮的环境变量的项目。)

我决定在我的示例中加入一些 spice,因此我用 Vite 创建了这两个项目,但模板项目使用 React,而生成器项目使用 Vue.

我将对如何构建这两个项目进行高级概述,如果你只想查看所有代码,可以跳到本文末尾 查看最终的仓库!

模板项目

要启动我的模板项目,我将引入 ViteReact.

npm init @vitejs/app

运行此命令后,你可以按照提示使用任何你喜欢的框架!

现在,完成整个 npm install 操作后,你需要添加一个 .local.env 文件,并添加要包含的环境变量。我想要一个网站所有者的姓名、他们的个人资料图片,以及他们所有相关的链接。

VITE_NAME=Cassidy Williams
VITE_PROFILE_PIC=https://github.com/cassidoo.png
VITE_GITHUB_LINK=https://github.com/cassidoo
VITE_TWITTER_LINK=https://twitter.com/cassidoo

你可以根据自己的喜好进行设置,因为这只是一个测试数据,我们将以此为基础进行构建!在构建自己的应用程序时,你可以随时引入环境变量,以便使用 import.meta.env 进行解析。Vite 允许你使用 VITE_ 从客户端代码访问这些变量,因此在使用变量时,请确保在变量前面加上此前缀。

最终,我创建了一个相当大的解析函数,并将它传递给我的组件,以便将其呈现到模板中

function getPageContent() {
  // Pull in all variables that start with VITE_ and turn it into an array
  let envVars = Object.entries(import.meta.env).filter((key) => key[0].startsWith('VITE_'))

  // Get the name and profile picture, since those are structured differently from the links
  const name = envVars.find((val) => val[0] === 'VITE_NAME')[1].replace(/_/g, ' ')
  const profilePic = envVars.find((val) => val[0] === 'VITE_PROFILE_PIC')[1]
  
  // ...
  
  // Pull all of the links, and properly format the names to be all lowercase and normalized
  let links = envVars.map((k) => {
    return [deEnvify(k[0]), k[1]]
  })

  // This object is what is ultimately sent to React to be rendered
  return { name, profilePic, links }
}

function deEnvify(str) {
  return str.replace('VITE_', '').replace('_LINK', '').toLowerCase().split('_').join(' ')
}

现在,我可以将这些变量引入一个 React 函数,该函数将渲染我需要的组件

// ...
  return (
    <div>
      <img alt={vars.name} src={vars.profilePic} />
      <p>{vars.name}</p>
      {vars.links.map((l, index) => {
        return <Link key={`link${index}`} name={l[0]} href={l[1]} />
      })}
    </div>
  )

// ...

!只需添加一些 CSS,我们便拥有了一个“Link in Bio”网站!

现在让我们将其转变为不依赖于硬编码变量的东西。是时候进行生成器了!

生成器项目

我将启动一个新的 Vite 网站,就像之前一样,但我将使用 Vue,为了好玩。

现在,在这个项目中,我需要生成上面提到的环境变量。因此我们需要一个用于输入名称的输入框、一个用于输入个人资料图片的输入框,以及一组用于用户可能要添加的每个链接的输入框。

在我的 App.vue 模板中,我将它们像这样分开

<template>
  <div>
    <p>
      <span>Your name:</span>
      <input type="text" v-model="name" />
	</p>
    <p>
      <span>Your profile picture:</span>	
      <input type="text" v-model="propic" />
    </p>
  </div>

  <List v-model:list="list" />

  <GenerateButton :name="name" :propic="propic" :list="list" />
</template>

在那个 List 组件中,我们将有两个输入框,用于收集用户可能要添加的所有链接

<template>
  <div class="list">
    Add a link: <br />
    <input type="text" v-model="newItem.name" />
    <input type="text" v-model="newItem.url" @keyup.enter="addItem" />
    <button @click="addItem">+</button>

    <ListItem
      v-for="(item, index) in list"
      :key="index"
      :item="item"
      @delete="removeItem(index)"
    />
  </div>
</template>

因此,在这个组件中,有两个输入框,它们将添加到名为 newItem 的对象中,然后 ListItem 组件列出所有已创建的链接,并且每个链接都可以自行删除。

现在,我们可以使用从用户那里获取的所有这些值,并填充 GenerateButton 组件,以使我们的 DTN 按钮正常工作!

GenerateButton 中的模板只是一个带有链接的 <a> 标签。它的力量在于 <script> 中的 methods 。

// ...
methods: {
  convertLink(str) {
    // Convert each string passed in to use the VITE_WHATEVER_LINK syntax that our template expects
    return `VITE_${str.replace(/ /g, '_').toUpperCase()}_LINK`
  },
  convertListOfLinks() {
    let linkString = ''
    
    // Pass each link given by the user to our helper function
    this.list.forEach((l) => {
      linkString += `${this.convertLink(l.name)}=${l.url}&`
    })

    return linkString
  },
  // This function pushes all of our strings together into one giant link that will be put into our button that will deploy everything!
  siteLink() {
    return (
      // This is the base URL we need of our template repo, and the Netlify deploy trigger
      'https://app.netlify.com/start/deploy?repository=https://github.com/cassidoo/link-in-bio-template#' +
      'VITE_NAME=' +
      // Replacing spaces with underscores in the name so that the URL doesn't turn that into %20
      this.name.replace(/ /g, '_') +
      '&' +
      'VITE_PROFILE_PIC=' +
      this.propic +
      '&' +
      // Pulls all the links from our helper function above
      this.convertListOfLinks()
    )
  },
}, 

信不信由你,就是这样。你可以添加任何你喜欢的样式,或者改变传递的变量(例如主题、切换等等),以使它真正可定制!

整合在一起

一旦这些项目部署完成,它们就可以和谐地协同工作!

这种项目可以真正说明,当你能够访问用户生成的環境變數时,定制化功能的强大之处。它可能很小,但当你想生成例如简历网站、电子商务主题、“/uses”网站、营销网站……时,它可以变成一种非常酷的样板方法,可能性是无限的。