在本教程中,您将学习如何使用 Medusa 和 11ty 构建现代电子商务店面。您将使用 Medusa 的无头商务引擎和管理面板创建我们商店的后端,并使用 11ty 框架和 tailwind CSS 创建商店的前端。

Medusa是开源的 Shopify 替代方案,提供专注于最大限度地提高开发人员灵活性的无头商务解决方案。11ty是一个非常灵活的简单静态站点生成器,用于构建现代网站。

在本教程中,您将学习如何:

1.设置美杜莎的后端服务器

  1. 安装 DigitalOcean 空间以便于文件管理

  2. 设置美杜莎的管理面板,更轻松地管理您的在线商店

  3. 使用 11ty 和 TailwindCSS 构建一个简单的店面

下面是我们将要构建的视频

先决条件

要完成本教程,请确保拥有:

  • Nodejs 和 NPM 安装在您的本地计算机上。您可以按照此链接](https://phoenixnap.com/kb/install-node-js-npm-on-windows)中的说明[在本地计算机上完全安装 Nodejs 和 npm。

  • 使用 GitHub 帐户在本地安装的 Git。按照说明这里安装git,这里创建一个GitHub账号。

  • DigitalOcean 帐户。在此处创建一个 DigitalOcean 帐户。

为什么是美杜莎?

  • 开源 - Medusa 是一款开源软件,可用作您的网上商店的商业后端,背后有一个庞大的支持社区,您可以在此处访问。

  • 无头架构 - Medusa 的无头架构可以轻松构建任何类型的前端(例如 11ty),并与您最喜欢的 CMS、支付、履行解决方案等集成。

  • 多市场支持 - Medusa 原生支持多种货币,并允许您设置使用本地运输和支付提供商进行全球设置。

  • 完全可定制 - 我们的可扩展架构可以轻松定制任何类型的高级用例,并可以轻松构建自定义逻辑和集成。

Medusa 后端安装和设置

本教程的第一步是设置 Medusa 服务器和管理面板。 Medusa 提供了 3 个核心组件来管理您的商务项目 - 一个为您的前端消费公开 REST API 的无头商务引擎、一个可定制的前端和一个用于管理您的商店的管理面板。

在这个项目中,我们将只使用无头商务引擎和管理面板,因为我们将使用 11ty 构建店面。要设置后端服务器,首先安装 Medusa CLI。

npm install -g @medusajs/medusa-cli

进入全屏模式 退出全屏模式

然后使用已安装的 CLI 创建一个新项目。

medusa new <my-medusa-store> --seed

进入全屏模式 退出全屏模式

更改为项目的首选名称。导航到生成的文件夹,并创建一个新用户。

cd <my-medusa-store>
medusa user -e <some@email.com> -p <some_password>

进入全屏模式 退出全屏模式

将 <****some@email.com> 更改为您的首选电子邮件和首选密码。

最后,启动创建的服务器。

medusa develop

进入全屏模式 退出全屏模式

可以通过http://localhost:9000访问服务器。

为图片上传设置 DigitalOcean 空间

安装完美杜莎服务器后,下一步将设置一个 DigitalOcean 空间来存储我们上传的图像。要做到这一点:

  • 打开您的 DigitalOcean 帐户。导航到空间。使用默认设置创建一个新空间。

  • 选择创建的空间,点击Manage Keys

[管理键](https://res.cloudinary.com/practicaldev/image/fetch/s--c4U7x0S9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh5.googleusercontent .com/sxBb9zs-qYVydjYV7-JzIq-S9LLlfmUwXPRSUdccOijJNFS_i2_K6P3FSKJUUXzjJu5Nf0WqG6jdfAwG2CkaJ7ovjOFaazfqReqL4MjvtUw2a3fL2WAmvE4YcU9o2ogyI_4N6R8H)

  • 单击生成新密钥。

[生成密钥](https://res.cloudinary.com/practicaldev/image/fetch/s--C6PQtx5P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent .com/HufHB9CC2SxWNi5XK0nr8vx8r-OUdTWxs90MCVuHF6FaWEEOJ5CGuRubt415S8QK6J5DjEViBI2Qorj5gaAlDZSQpSemaifBMa46AdCr8DjONj5CUsqfgERxpZrOwVVneHvAO3SC)

  • 添加密钥名称并保存。

[key-name](https://res.cloudinary.com/practicaldev/image/fetch/s--Bm9564aM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh4.googleusercontent .com/F3uFSUpIRZ6VGc7d95R5GnOy6j7LuOXYU8uilbF7BEfkf-QB3StFbYSBks4YTMRCEv6gso_bTVpJEm5eQgNXQPveJwWD12QsUjk8419nxWvscsNPxBQmvgasY9AdNZWNWwTY3T5k)

将自动生成密钥 ID 和密钥,将密钥复制到安全的地方。现在,导航回 medusa 项目文件夹,并安装 medusa-file-spaces 包。

npm install medusa-file-spaces

进入全屏模式 退出全屏模式

然后打开您的 medusa-config.js 文件,并将以下代码示例添加到插件部分。

{
    resolve: `medusa-file-spaces`,
    options: {
        spaces_url: "https://test.fra1.digitaloceanspaces.com",
        bucket: "test",
        endpoint: "fra1.digitaloceanspaces.com",
        access_key_id: "YOUR-ACCESS-KEY",
        secret_access_key: "YOUR-SECRET-KEY",
    },
},

进入全屏模式 退出全屏模式

将 spaes_url 更改为您创建的 DigitalOcean 空间的 URL,将 bucket 更改为空间名称,将 access_key_id 更改为生成的密钥 ID,并将 * secret_access_key* 到生成的密钥。

设置和安装美杜莎管理面板

Medusa 提供了一个管理面板,可以轻松配置和管理我们的商店。要设置管理面板,您应该首先从 GitHub 克隆管理存储库。

git clone https://github.com/medusajs/admin <medusa-admin>

进入全屏模式 退出全屏模式

更改为您喜欢的文件夹名称。然后导航到管理文件夹

cd <medusa-admin>

进入全屏模式 退出全屏模式

安装所有需要的包

npm install

进入全屏模式 退出全屏模式

最后,启动管理面板

npm start

进入全屏模式 退出全屏模式

管理面板将在http://localhost:7000/加载。

[管理面板](https://res.cloudinary.com/practicaldev/image/fetch/s--6WDU2_L8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh6.googleusercontent .com/KdvXVHuKL3YmNcOc4P76_ZrUscwLOocuS0OhEF-vyJrSE9CBDaZ-B25zimwv732O9dF5NRQ3ZztDjDUzdY_ezVFt6GneIxqi9PUYnmxVciBwNAk7Ku7_hNcozCiyU4OxWxyEnvzm)

使用服务器的用户邮件和密码登录以访问管理仪表板。

[登录](https://res.cloudinary.com/practicaldev/image/fetch/s--rWY1JNF2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh5.googleusercontent .com/FK3C1yVReUr7ritwN-_pTh65pPGXVA7ivI6HJJZFv-psUxdJj4kCcNgOCsyRxD_KKBFbSo1fbMWvltoBdAs1GxTrpK8cv9Fq4sxhzcDOF9AS7uwmx40cVWgU5jCYToiGNDapv1Vc)

将产品添加到商店

现在我们已经完全设置了 Medusa 服务器和管理面板,下一步就是将产品添加到我们的商店。我们将通过管理面板执行此操作,因为与直接向服务器发送 API 请求相比,管理面板更容易。

要将产品添加到商店:

  1. 在您的侧边菜单中选择产品,然后单击窗口右侧的新产品。

[选择产品](https://res.cloudinary.com/practicaldev/image/fetch/s--DbYb2wJi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh5.googleusercontent .com/Ov82tEhDE_bR7WjdPTE8R9SFEKYCm16-6eg3_g7emfxomqmlLns3gUooDqn0TBDvEgi8xKQOJaLXsvStz-3WUQt0zZfZmeDRPeZ3R4cvDYwjthxXH2Dkbwzwx2QMe7aWWvkZgGhZ)

  1. 添加您的产品信息并点击保存注册新产品。

[产品信息](https://res.cloudinary.com/practicaldev/image/fetch/s--F9JVkw6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent .com/e7heOmQ497__kFGq3lmf5an2qqtDvUdCtSTfDbWUwLwidTg8S0LyiKVuLV9xo6NH4ZW00p2J1t9MkHGhpVuDQJEQi3amqlNprr2kGkEzL758jQqMYr__K5NpY7-DZdGPlblsqISE)

3.点击下一步的发布发布新产品。

[发布](https://res.cloudinary.com/practicaldev/image/fetch/s--VWh1clnI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh6.googleusercontent.com /lxDM1qFrix-N_bifEc8gxUV1c6BPJ54oJv4-ij4w8SBh6x6k2ZbeK-F5I5vvKp_wqsvUllRhJIqS3D_9xAfG0jAV7M1K3O6JOiIGBaVoxDp0C9rIHkqwKkQ7QSulo2e_U0N_zApg)

确保向您的商店添加至少 3 个产品,这是完成本特定教程的前端设置所必需的。对于每个产品,请确保添加:

  • 缩略图

  • 4 个产品图片

  • 产品名称

  • 产品说明

  • 手柄(手柄应为 slug 格式,即 T 恤、面罩等)

创建产品集合

将产品添加到您的商店后,下一步是将它们分组到集合中。对于本教程,我们将使用:

  • 每周销售集合

  • 畅销书系列

要创建集合:

  1. 在侧边栏菜单中选择产品下的收藏。点击右上角的 New collection 创建新的收藏。

[新系列](https://res.cloudinary.com/practicaldev/image/fetch/s--HWZD1Qh---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh5. googleusercontent.com/qGn8dzpl9KNqVb9sStL_D4G-e9XjLFTXT-I_nPQkkYFWv_4NaUj32CMEFtuF5NzIDRt1L59pIK9kRFbxAqQv2HJ68VaIFkGznPjmdV2JNXcpveOaw-K5_RLWDGsIu9NpU--sOXTU)

  1. 添加收藏标题和句柄,然后点击保存。

[保存](https://res.cloudinary.com/practicaldev/image/fetch/s--wxRyU-dQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent .com/AOnxpcRHmv-zFYDtfABVjUFY9G3jAwYtOxePzZ3nAwer9Pl1VN26RyX1swjCyZ5ImQNq9ifdA8QKgTrAVVIsG-kFgavTZzH65XSi0-kQmIN8wYjyfXZImKTdLoHMai5GfieRFPtV)

要将产品添加到集合中,

  1. 单击产品页面上的产品以显示产品信息页面。

[产品信息](https://res.cloudinary.com/practicaldev/image/fetch/s--bblOnhGZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent .com/fxMzvSxvXi8MPq5-9KK4TJKMZYFA5MoQx4xfv6MntCqP4n-HupE4Im6k17oXJQYzebI9Sr5NOlg42au1pDjdKtZWP4S3vo3tooJePEFP8jCQpZoeAFewR8-6vbJF14jb6AbJ2INz)

  1. 单击集合下拉菜单并选择一个集合以将产品添加到该集合。

[下拉](https://res.cloudinary.com/practicaldev/image/fetch/s--wJ7eiOFi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh4.googleusercontent.com /A2YEmmK41QfmR8lVeFB7DK_9152X0xxVoaHsyCO23Qy2UbW-QVUvywFgmsON6LuTLNcN5LqJ9NQEeezQH3nFWpKchUx7knBeNToSGu6XSVq423gIcwyowOTurCXkHGNHc4xztQ)

  1. 单击 Save 以保存您的更改。确保将您的每个产品添加到集合中。

11ty店面安装设置

现在我们的 Medusa 设置已经完成并添加了产品,我们教程的下一步将是使用 11ty 前端框架为我们的商店创建一个店面。 11ty 是一个简单的静态站点生成器,默认为零配置,它是一个灵活的框架,允许同时使用多种模板语言,如 Nunjucks、Liquid、Javascript、markdown 等。

要安装 11ty,请使用您的店面首选名称创建一个新文件夹。导航到该文件夹并使用 npm 初始化该文件夹。

npm init -y

进入全屏模式 退出全屏模式

一个 package.json 文件将被添加到该文件夹中。然后使用以下命令将 11ty 安装到文件夹中。

npm install --save-dev @11ty/eleventy

进入全屏模式 退出全屏模式

使用以下命令确认您的安装。

npx @11ty/eleventy

进入全屏模式 退出全屏模式

如果安装成功,您应该会得到类似的响应。

Wrote 0 files in 0.03 seconds (v0.12.1)

进入全屏模式 退出全屏模式

现在我们已经完成了 11ty 设置,下一步是将 TailwindCSS 安装到前端。 TailwindCSS 是一个实用程序优先的 CSS 框架,用于构建现代网站。访问https://tailwindcss.com/了解有关 css 框架的更多信息。

将 TailwindCSS 添加到 11ty;首先,安装 TailwindCSS 及其依赖项。

npm install tailwindcss postcss-cli autoprefixer

进入全屏模式 退出全屏模式

然后使用以下命令生成您的顺风配置文件。

npx tailwind init

进入全屏模式 退出全屏模式

创建一个名为 postcss.config.js 的新文件,并将以下内容添加到文件中。

// postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  }
}

进入全屏模式 退出全屏模式

创建一个 css 文件夹,并在该文件夹中添加一个名为 index.css 的文件。然后将以下代码片段添加到 c*ss/index.css* 文件中。

@tailwind base;
@tailwind components;
@tailwind utilities;

进入全屏模式 退出全屏模式

最后,使用以下代码片段更新您的 package.json 文件。

 "scripts": {
   "dev": "postcss css/index.css -o _site/css/index.css && eleventy --serve --quiet",
   "build": "postcss css/index.css -o _site/css/index.css"
 },

进入全屏模式 退出全屏模式

要启动 11ty 服务器,请运行 npm run dev。服务器将在http://localhost:8080/打开。

创建店面文件结构

11ty 是一个非常灵活的框架,并且附带零配置。我们可以根据需要设置我们的项目。将 src 文件夹添加到您的根文件夹,这是存储我们文件的主文件夹。此外,将 _includes 和 _helper 文件夹添加到 src 文件夹。组件文件将存储在 src/_includes 文件夹中,而数据文件将存储在 src/_helpers 文件夹中。

将 .eleventy.js 文件添加到您的根文件夹,并将以下代码片段添加到 .eleventy.js。

const HtmlMin = require('html-minifier');
const ErrorOverlay = require('eleventy-plugin-error-overlay');
 module.exports = eleventyConfig => {
 eleventyConfig.setTemplateFormats(['md']);
 eleventyConfig.addPlugin(ErrorOverlay);
 eleventyConfig.addTransform('htmlmin', (content, outputPath) => {
   if (outputPath.endsWith('.html')) {
     const minified = HtmlMin.minify(content, {
       useShortDoctype: true,
       removeComments: true,
       collapseWhitespace: true,
     });
     return minified;
   }
   return content;
 });
 return {
   dir: {
   input: "src",
   output: "_site",
   includes: "_includes",
   data: "_helpers",
   },
   jsDataFileSuffix: '.data',
 };
};

进入全屏模式 退出全屏模式

.eleventy.js 文件是我们主要的 11ty 配置文件。代码示例简单地通知 11ty 我们的数据文件和包含文件的存储位置,以及输出数据的存储位置。我们还在项目中添加了一个 html-minifier 插件和 eleventy-plugin-error-overlay。

最后,使用以下命令安装这两个插件。

npm install html-minifier eleventy-plugin-error-overlay

进入全屏模式 退出全屏模式

完成设置后,您的文件结构应如下所示:

[文件结构](https://res.cloudinary.com/practicaldev/image/fetch/s--ksIUiAsy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent .com/YOx9-Qs5w7qXP8JDEAIL2lLe8Qlw7wge76e6STWMVCImYokoYccyXhWg2PPsmRy5tsXLdzvPbsV4uVwHEzGmbHvQ-LFxTvhV5lYHWL94rIuFBsMAOvHwv0Bo9tieWY_D4KNrK_66)

创建店面布局

下一步是创建店面的布局。我们将主要使用 Nunjucks 作为我们选择的模板引擎。

首先将 header.njk 和 footer.njk 文件添加到您的 _includes 文件夹中。将以下代码示例添加到 _includes/header.njk 文件中,

<header class="bg-white text-gray-900 body-font shadow w-full">
  <div
    class="
      container
      mx-auto
      flex flex-wrap
      p-5
      flex-col
      md:flex-row
      items-center
    "
  >
    <nav class="flex flex-wrap items-center text-base md:ml-auto">
      <a
        href="/"
        class="
          mr-5
          hover:text-gray-900
          cursor-pointer
          border-b border-transparent
          hover:border-blue-600
        "
        >Products</a
      >
      <svg
        class="h-5 w-5"
        viewBox="0 0 24 24"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
      >
        <path
          d="M3 3H5L5.4 5M7 13H17L21 5H5.4M7 13L5.4 5M7 13L4.70711 15.2929C4.07714 15.9229 4.52331 17 5.41421 17H17M17 17C15.8954 17 15 17.8954 15 19C15 20.1046 15.8954 21 17 21C18.1046 21 19 20.1046 19 19C19 17.8954 18.1046 17 17 17ZM9 19C9 20.1046 8.10457 21 7 21C5.89543 21 5 20.1046 5 19C5 17.8954 5.89543 17 7 17C8.10457 17 9 17.8954 9 19Z"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        />
      </svg>
    </nav>
    <a
      href="/"
      class="
        flex
        order-first
        lg:order-first lg:w-2/5
        title-font
        font-medium
        items-center
        lg:items-center
        mb-4
        md:mb-0
      "
    >
      <svg
        width="38"
        height="40"
        viewBox="0 0 38 40"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
      >
        <path
          d="M32.4865 6.48972L23.4254 1.28128C20.4607 -0.427092 16.8279 -0.427092 13.8631 1.28128L4.76024 6.48972C1.83728 8.19809 0 11.3648 0 14.7399V25.1984C0 28.6152 1.83728 31.7402 4.76024 33.4486L13.8214 38.6987C16.7861 40.4071 20.4189 40.4071 23.3836 38.6987L32.4448 33.4486C35.4095 31.7402 37.205 28.6152 37.205 25.1984V14.7399C37.2885 11.3648 35.4512 8.19809 32.4865 6.48972ZM18.6234 29.2819C13.4873 29.2819 9.31169 25.1151 9.31169 19.99C9.31169 14.8649 13.4873 10.6981 18.6234 10.6981C23.7594 10.6981 27.9768 14.8649 27.9768 19.99C27.9768 25.1151 23.8012 29.2819 18.6234 29.2819Z"
          fill="#56FBB1"
        /></svg>
    </a>
  </div>
</header>

进入全屏模式 退出全屏模式

然后,将以下内容添加到 _includes/footer.njk 文件中。

<footer class="bg-white h-30 flex items-end text-grey-900 pt-10 sm:mt-10 pt-10">
  <div
    class="
      w-full
      mx-auto
      text-gray-800
      flex flex-wrap
      justify-between
      inset-x-0
      bottom-0
      p-5
    "
  >
    <div>
      <a
        href="/"
        class="
          mr-5
          text-sm
          hover:text-gray-900
          cursor-pointer
          border-b border-transparent
          hover:border-blue-600
        "
        >Create Return</a
      >
      <a
        href="/"
        class="
          mr-5
          text-sm
          hover:text-gray-900
          cursor-pointer
          border-b border-transparent
          hover:border-blue-600
        "
        >FAQ</a
      >
      <a
        href="/"
        class="
          mr-5
          text-sm
          hover:text-gray-900
          cursor-pointer
          border-b border-transparent
          hover:border-blue-600
        "
        >Terms and Shipping</a
      >
    </div>
    <div>
      <a
        href="/"
        class="
          mr-5
          text-sm
          hover:text-gray-900
          cursor-pointer
          border-b border-transparent
          hover:border-blue-600
        "
        >Discord</a
      >
      <a
        href="/"
        class="
          mr-5
          hover:text-gray-900
          cursor-pointer
          border-b border-transparent
          hover:border-blue-600
        "
        >GitHub</a
      >
      <a
        href="/"
        class="
          mr-5
          text-sm
          hover:text-gray-900
          cursor-pointer
          border-b border-transparent
          hover:border-blue-600
        "
        >LinkedIn</a
      >
    </div>
  </div>
</footer>

进入全屏模式 退出全屏模式

最后,将 layout.njk 文件添加到您的 _incudes 文件夹中。将以下代码示例添加到 _includes/layout.njk 文件中。

    <html>
      <head>
        <title>medusa storefront</title>
        <link rel="stylesheet" href="css/index.css" />
      </head>
      <div>{% include "header.njk" %}</div>
      <div>
        <body>
          <div>
            {{ content | safe }}
          </div>
        </body>
      </div>
      <div>{% include "footer.njk" %}</div>
    </html>

进入全屏模式 退出全屏模式

在这段代码中,我们基本上导入了我们的 css 样式表,并且还用创建的 header.njk 和 footer.njk 文件包装了页面内容。要在页面上使用布局,只需将 layout.njk 文件添加到页面的 frontmatter。

将美杜莎服务器的内容导入店面

现在我们已经创建了商店的布局,下一步是将产品从 Medusa 服务器导入到店面。为此,我们必须将产品数据作为 11ty 全局数据变量导入。

将文件名 products.js 添加到您的 _helpers 文件夹,并将以下代码示例添加到 _helper/products.js 文件。

const { default: axios } = require('axios');
 module.exports = async () => {
 try {
   const res = await axios.get('http://localhost:9000/store/products');
   return res.data.products;
 } catch (error) {
   console.error(error);
 }
};

进入全屏模式 退出全屏模式

此代码向 Medusa 服务器发出 get 请求并返回要存储为 11ty 全局数据的响应。访问此链接以访问 Medusa 提供的 API 端点列表。

可以在店面的任何地方访问返回的数据。最后,安装 axios,因为我们将使用 axios 进行 api 调用。

npm install axios

进入全屏模式 退出全屏模式

创建店面的主页

店面主页将包括 2 个部分,一个英雄部分和一个用于展示我们产品的产品部分。

将 hero.njk 文件和 product.njk 文件添加到 _includes 文件夹。然后,将以下代码示例添加到 _includes/hero.njk 文件中。

    <div class="w-full mb-10">
      <div class="flex bg-white" style="height: 600px">
        <div
          class="hidden lg:block lg:w-1/2"
          style="clip-path: polygon(10% 0, 100% 0%, 100% 100%, 0 100%)"
        >
          <img
            class=""
            src="https://user-images.githubusercontent.com/59125401/144878845-da9d252a-abfb-4fa1-8fca-fa46c7b103b1.png"
            alt="hero photo"
          />
        </div>
        <div
          class="flex items-center text-center lg:text-left px-8 md:px-12 lg:w-1/2"
        >
          <div>
            <h2 class="text-5xl font-semibold text-gray-800 md:text-4xl">
              Get Free <span class="text-indigo-600">Merch</span>
            </h2>
            <p class="mt-2 text-2xl w-3/4 text-gray-500 md:text-base">
              Contribute to Medusa and get free merch as a token of our appreciation.
            </p>
            <div class="flex justify-center lg:justify-start mt-6">
              <a
                class="
                  px-4
                  py-3
                  bg-indigo-600
                  text-gray-200 text-xs
                  font-semibold
                  rounded
                  hover:text-indigo-600
                "
                href="#"
                >Get Started</a
              >
            </div>
          </div>
        </div>
      </div>
    </div>

进入全屏模式 退出全屏模式

将以下代码示例添加到 _includes/product.njk 文件。

    <div  class="
        grid grid-cols-1
        gap-y-10
        sm:grid-cols-2
        gap-x-6
        lg:grid-cols-3
        max-w-6xl
        mx-auto
      "
    >
    {%- for product in products -%}
      <a  key="{{ product.id }}"
              href="/{{ product.handle }}.html"
              class="group">
        <img
          src="{{ product.thumbnail }}"
          alt="{{ product.id }}"
          class="
            w-5/6
            h-60
            rounded-md
            border
            border-gray-500
            object-center object-cover
            group-hover:opacity-75
          "
        />
        <h3 class="w-1/2 mx-auto text-indigo-600">{{ product.title }}</h3>
        <h3 class="w-1/2 mx-auto text-gray-500">${{ product.variants.0.prices.0.amount }}</h3>
      </a>
    {%- endfor -%}
    </div>

进入全屏模式 退出全屏模式

在这段代码中,我们基本上使用液体模板引擎显示了我们的部分产品细节。将index.md文件添加到src文件夹,并将以下代码片段添加到**src/index.md**文件中。

    ---
    title: "Home"
    layout: layout.njk
    ---
    {% include hero.njk %}   
    {% include product.njk %}

进入全屏模式 退出全屏模式

在这段代码中,我们基本上使用 include 变量导入了 hero.liquid 文件和 product.liquid 文件。我们还通过将其作为前端添加到文件中来实现我们创建的布局。当你访问http://localhost:8080/时,你应该会看到类似这样的页面:

[home](https://res.cloudinary.com/practicaldev/image/fetch/s--1lMk8Khs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments.dropbox .com/s_EBF8B0A2FC688547110018FB7B38AA4A8C119B82A4B7456D02A381F06E97CB1_164167807207_Screen%2BShot%2B2022-01-08%2Bat%2B8.39.42%2BPM.png)

创建单个产品视图

最后一步是创建我们的单个产品视图,11ty 提供了一个分页变量,允许我们从单个模板创建多个文件。在名为 product.md 的 src 文件夹中创建一个新文件。将以下代码示例添加到 src/product.md 文件。


    ---
    layout: layout.njk
    pagination:
      data: products
      size: 1
      alias: product
    permalink: "/{{ product.handle }}.html"
    title: { { product.title } }
    ---

    <div
      class="
        mt-6
        max-w-2xl
        mx-auto
        sm:px-6
        lg:max-w-7xl lg:px-8 lg:grid lg:grid-cols-3 lg:gap-x-8
      "
    >
      <div class="hidden aspect-w-3 aspect-h-4 rounded-lg overflow-hidden lg:block">
        <img
          src="{{ product.thumbnail }}"
          alt="{{ product.id }}"
          class="w-full h-full object-center object-cover"
        />
      </div>
      <div class="hidden lg:grid lg:grid-cols-1 lg:gap-y-8">
        <div class="aspect-w-3 aspect-h-2 rounded-lg overflow-hidden">
          <img
            src="{{ product.images.0.url }}"
            alt="{{ product.id }}"
            class="w-full h-96 object-center object-cover"
          />
        </div>
        <div class="aspect-w-3 aspect-h-2 rounded-lg overflow-hidden">
          <img
            src="{{ product.images.1.url }}"
            alt="{{ product.id }}"
            class="w-full h-full object-center object-cover"
          />
        </div>
      </div>
      <div class="hidden lg:grid lg:grid-cols-1 lg:gap-y-8">
        <div
          class="
            aspect-w-4 aspect-h-2
            sm:rounded-lg sm:overflow-hidden
            lg:aspect-w-3 lg:aspect-h-4
          "
        >
          <img
            src="{{ product.images.2.url }}"
            alt="{{ product.id }}"
            class="w-full h-full object-center object-cover"
          />
        </div>
        <div
          class="
            aspect-w-4 aspect-h-2
            sm:rounded-lg sm:overflow-hidden
            lg:aspect-w-3 lg:aspect-h-4
          "
        >
          <img
            src="{{ product.images.3.url }}"
            class="w-full h-full object-center object-cover"
          />
        </div>
      </div>
    </div>
    <div
      class="
        max-w-2xl
        mx-auto
        pt-10
        pb-16
        px-4
        sm:px-6
        lg:max-w-4xl
        lg:pt-16
        lg:pb-24
        lg:px-8
      "
    >
      <div
        class="mt-4 space-y-3 lg:mt-0"
      >
        <h1
          class="
            flex
            justify-center
            mb-5
            text-2xl
            font-extrabold
            tracking-tight
            text-gray-900
            sm:text-3xl
          "
        >
          {{ product.title }}
        </h1>
        <div class="space-y-6">
          <p class="flex justify-center text-gray-900">{{ product.description }}</p>
          <div class="flex justify-center">
            <p class="text-sm font-bold text-gray-900">Product collection -</p>
            <p class="text-sm font-bold text-indigo-700">{{ product.collection.title }}</p>
          </div>
          <div class="flex justify-center">
            <p class="text-sm font-bold text-gray-900">Price -</p>
            <p class="text-sm font-bold text-indigo-700">${{ product.variants.0.prices.0.amount }}</p>
          </div>
         </div>
        <form>
          <div class="flex justify-center space-x-3 mb-5">
            <h1 class=" flex justify-center text-lg font-bold tracking-tight text-gray-900">Quantity -</h1>
            <input type="number" name="quantity" value="1" min="0" max="10" class="flex border-2 rounded-md text-blue-900 px-1 py-1 border-indigo-700" />
          </div>
          <h1 class=" flex justify-center mb-5 text-lg font-bold tracking-tight text-gray-900">Variants</h1>
          <div class="flex mt-2 max-w-xl mx-auto">
          {%- for variant in product.variants -%}
            <label for="{{ variant.id }}">
              {{ variant.title }}
              <span></span>
            </label>
            <input id="{{ variant.id }}" name="{{ variantId }}" type="radio" value="{{ variant.id }}" class="flex border -ml-24 mt-2 text-blue-900 border-indigo-700 w-full">
          {%- endfor -%}
          </div>
          <button
            type="submit"
            class="
              mt-10
              w-full
              bg-blue-900
              border border-transparent
              rounded-md
              py-3
              px-8
              flex
              items-center
              justify-center
              text-base
              font-medium
              text-white
              hover:bg-indigo-700
              focus:outline-none
              focus:ring-2
              focus:ring-offset-2
              focus:ring-indigo-500
            "
          >
            Add to cart
          </button>
        </form>
      </div>
    </div>

进入全屏模式 退出全屏模式

在此代码中,我们简单地迭代产品数据并为每个产品创建一个页面。产品的链接也是通过使用 permalink 变量的句柄生成的。要访问产品页面,只需单击主页中的产品,您应该会看到类似于以下内容的页面:

[产品](https://res.cloudinary.com/practicaldev/image/fetch/s--7x_R3e_---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://paper-attachments。 dropbox.com/s_EBF8B0A2FC688547110018FB7B38AA4A8C119B82A4B7456D02A381F06E97CB1_1641984609879_Screen%2BShot%2B2022-01-12%2Bat%2B11.50.05%2BAM.png)

结论

在本教程中,我们使用 Medusa 和 11ty 创建了一个店面。您可以在此 GitHub 存储库中访问此项目的代码 -https://github.com/Quadrisheriff/medusa-storefront

有关美杜莎的更多信息,请访问他们的文档或在他们的Discord上保持更新,社区已准备好为您提供支持。

有关 11ty 的信息,请访问他们的网页或在他们的Discord中获得帮助。

Logo

ModelScope旨在打造下一代开源的模型即服务共享平台,为泛AI开发者提供灵活、易用、低成本的一站式模型服务产品,让模型应用更简单!

更多推荐