如何在 Netlify 重寫中處理尾斜線問題

Netlify 有一個很棒的功能,稱為 rewrites,可以讓我創建許多重複的頁面。但是有個限制。 在 Netlify 中,我們可以通過將這些頁面添加到專案的公共根目錄下的 _redirects 文件(例如在 Hugo 中是 public/_redirects)來進行重寫。 我將它用於一些網站。 假設我在 content/original 下有一堆頁面,我可以透過以下方法進行重寫: /copy/\* /original/:splat 200 這樣,當我訪問網址 /copy 時,內容實際上是儲存在 https://mysite.com/original,但網址並不會改變。雖然 _redirects 命名中有「導向」的意思,但實際上它是一個重寫,因為我使用的是 200 狀態碼。如果我使用了 301 狀態碼,那麼這就是一個 301 導向。 無論如何,我遇到的問題是:沒有辦法自動在網址末尾添加尾斜線。因此,如果你訪問 /copy 和 /copy/,並且在圖片和連結中使用相對 URL,沒有尾斜線的 URL 會導致 404 錯誤和圖片無法正常顯示。 我在靜態網站生成器中尋找解決方案,看看是否可以以其他方式實現重寫,但最終我找到的解決方案在客戶端實現。 而且非常簡單。 我只需在頁面底部添加以下 JavaScript 代碼: <script> (function() { if (!location.href.endsWith('/')) { window.location = location.href + '/'; } }()); </script> 這樣,如果網址末尾沒有尾斜線,頁面會立即重新載入,並在末尾添加尾斜線。 這個過程非常迅速,對使用者來說幾乎是不可見的。

如何在 Next.js 中在構建時在所有頁面上全局緩存數據

在我使用 Next.js 架構的網站中,需要在構建時從 API 中獲取數據。 我嘗試了多種解決方案,但都沒有成功。經過大量的研究和試誤,我找到了解決方案。 這個解決方案同樣適用於本地開發(localhost)和 Vercel(生產環境)。 以下是情景描述:我有一個存儲“成員”電子郵件的位置,可以是遠程數據庫、Airtable 或其他任何地方。 我只想下載這些數據一次,然後在網站上一直保持可用,直到我觸發下一次構建。 這個成員列表非常靜態,最多一天可能會變化一次。如果這個列表發生變化,我只需要使用 Vercel 的 Deploy Hooks 以編程方式觸發重新部署。 以下是操作計劃。我們將在 .members 文件中創建數據的本地緩存。 在 lib/members.js 文件中的一個函數將負責在第一次調用時從緩存中將數據提取並存儲為 JSON,以後每次調用時從緩存中讀取數據: import fs from 'fs' import path from 'path' function fetchMembersData() { console.log('正在獲取成員數據...') return [{ email: '[[email protected]](/cdn-cgi/l/email-protection)' }, { email: '[[email protected]](/cdn-cgi/l/email-protection)' }] } const MEMBERS\_CACHE\_PATH = path.resolve('.members') export default async function getMembers() { let cachedData try { cachedData = JSON.parse( fs.readFileSync(path.join(\_\_dirname, MEMBERS\_CACHE\_PATH), 'utf8') ) } catch (error) { console....

如何在 Next.js 中解析 Markdown

我有一個包含 Markdown 內容的欄位,然後我想在 Next.js 的頁面上將其顯示出來。 我使用了 marked、dompurify 和 jsdom 。以下是一個在 Next.js 的動態頁面中用於渲染項目描述的示例。 請注意,由於 DOMPurify.sanitize() 需要在伺服器端調用,因為它假設我們在 Node.js 環境中,所以我將它放在 getStaticProps() 中: import { useState, useEffect } from 'react' import Head from 'next/head' import Link from 'next/link' import { useRouter } from 'next/router' import { getJob, getJobs } from 'lib/data.js' import prisma from 'lib/prisma' import marked from 'marked' import createDOMPurify from 'dompurify' import { JSDOM } from 'jsdom' export default function Item({ item }) { return <p>{item....

如何在 Next.js 表單中上傳文件

我在 Next.js 頁面中有一個表單: <form method="post" action="/api/new" enctype="multipart/form-data">...</form> 該表單呼叫一個 API 端點。 在這個表單中,我有一個 file 輸入控制元件: <input name="logo" type="file" /> 然而在 API 路由中,我無法得到這個檔案。 我進行了一些搜索,結果發現 Next.js 預設並不允許這樣做。我嘗試了幾種解決方案,因為有些解決方案不能很好地上傳文件並同時傳送多個相同屬性的複選框。有些解決方案中,我能得到該檔案,但其餘部分的表單功能則無法正常工作。 我必須安裝兩個套件: npm install next-connect multiparty 我在 Next.js 專案的根目錄中創建了一個 middleware 資料夾,在其中創建了這個檔案: middleware/middleware.js import nextConnect from 'next-connect' import multiparty from 'multiparty' const middleware = nextConnect() middleware.use(async (req, res, next) => { const form = new multiparty.Form() await form.parse(req, function (err, fields, files) { req.body = fields req.files = files next() }) }) export default middleware 然後我將 API 路由從通常的結構改為:...

如何在 Next.js 表單中添加 ReCaptcha

ReCaptcha 是 Google 對表單垃圾郵件和濫用的解決方案。 這是一個非常有價值的工具。如果您還沒有在 https://www.google.com/recaptcha 創建帳戶,請先創建並添加您的網站域名。 選擇 v2,並選擇「我不是機器人」複選框: 你會獲得一個站點金鑰和站點密鑰。 將密鑰儲存在您的.env文件中: RECAPTCHA_SECRET=<....> 現在,在您的 Next.js 網站中使用 npm 安裝react-google-recaptcha: npm install react-google-recaptcha 現在,在具有表單的頁面中引入它: import ReCAPTCHA from 'react-google-recaptcha' 並將其添加到 JSX 中: <ReCAPTCHA size="normal" sitekey="<YOUR SITE KEY>" /> 您應該在表單中看到它: 現在,如果您嘗試提交表單,它能正常工作,因為它什麼都不做。任何人,包括機器人,在不點擊「我不是機器人」按鈕的情況下都可以成功提交表單。 您需要在服務器端驗證驗證碼,以使其有用。 假設您將表單發送到 Next.js API 路由。在其中,添加一個validateCaptcha方法: const validateCaptcha = (response_key) => { return new Promise((resolve, reject) => { const secret_key = process.env.RECAPTCHA_SECRET const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${response_key}` fetch(url, { method: 'post' }) .then((response) => response.json()) .then((google_response) => { if (google_response....

如何在 Next.js 應用程式中在伺服器端獲取 Cookie

在 Next.js 中,在伺服器端渲染時存取 Cookie 可能比你想像中困難。以下是我解決這個問題的方法。 我遇到了這個問題。我的應用程式依賴於Cookie進行身份驗證,在使用 Next.js 時,顯然我的 Cookie 在首頁初始化時未被設置。 以下是負責使用Axios對一個 GET 端點進行請求的程式碼: Bookings.getInitialProps = async ctx => { const response = await axios.get('http://localhost:3000/api/bookings/list') return { bookings: response.data } } 我在伺服器端的端點上有 Passport.js,但它無法在 SSR 頁面上對用戶進行身份驗證,因為它找不到任何 Cookie。 我必須將程式碼更改為以下形式,將 Cookie 添加到 headers 中: Bookings.getInitialProps = async ctx => { const response = await axios({ method: 'get', url: 'http://localhost:3000/api/bookings/list', headers: ctx.req ? { cookie: ctx.req.headers.cookie } : undefined }) return { bookings: response.data } } 讓 Cookie 在後端中可用的關鍵是添加:...

如何在 Node 中從 URL 下載圖片

import os from 'os'; import fs from 'fs'; import https from 'https'; async function downloadFileFromURL(url, fileLocation) { return await new Promise((resolve, reject) => { https .get(url, (response) => { const code = response.statusCode ?? 0; if (code >= 400) { return reject(new Error(response.statusMessage)); } // 處理重定向 if (code > 300 && code < 400 && !!response.headers.location) { return await downloadFile(response.headers.location); } // 將文件保存到磁碟 const fileWriter = fs .createWriteStream(fileLocation) .on('finish', () => { resolve({ fileLocation, contentType: response....

如何在 Node.js 中生成子進程

了解如何在 Node.js 中生成子進程 Node.js 提供了child_process模組,它提供了生成子進程的功能。 引入該模組,並從中獲取spawn函數: const { spawn } = require('child\_process') 然後你可以調用spawn()函數,並傳遞2個參數。 第一個參數是要運行的命令。 第二個參數是一個包含選項列表的數組。 這是一個例子: spawn('ls', ['-lh', 'test']) 在這個例子中,你運行ls命令,並指定了2個選項:-lh和test。這將生成命令ls -lh test,結果會顯示有關該文件的詳細信息: -rw-r--r-- 1 flaviocopes staff 6B Sep 25 09:57 test spawn()函數的返回值是ChildProcess類的實例,用於識別生成的子進程。 這是一個稍微複雜一些的例子,完全可運行。我們在test文件上設置監聽,每當它發生變化時,就在它上運行ls -lh命令: 'use strict' const fs = require('fs') const { spawn } = require('child\_process') const filename = 'test' fs.watch(filename, () => { const ls = spawn('ls', ['-lh', filename]) }) 還有一個缺少的步驟。我們必須將子進程的輸出 pipe 到主進程,否則我們將無法看到它的任何輸出。 我們可以通過在子進程的stdout屬性上調用pipe()方法來實現: 'use strict' const fs = require('fs') const { spawn } = require('child\_process') const filename = 'test' fs....

如何在 Node.js 中使用 import 語法引入 .env 檔案

假設您已經設定了一個使用 ES 模塊的 Node.js 項目,並且想要使用 .env 檔案來存儲一個密碼,格式如下: PASSWORD=secret 您希望在 Node.js 腳本中能夠訪問這個密碼。 以下是如何實現的方法。 首先,安裝 dotenv 包: npm i dotenv 然後在代碼中使用以下內容: import * as dotenv from 'dotenv' dotenv.config() console.log(process.env.PASSWORD) 這需要假設您使用 ES 模塊(如果不是,只需在 package.json 文件中添加 "type": "module", 即可)。

如何在 Node.js 中執行 Shell 命令

以下介紹如何在 Node.js 腳本中執行 Shell 命令。 首先,從 child_process 中導入 child 模組: import * as child from 'node:child_process'; // 或者 const child = require('node:child_process'); 然後,你可以像這樣調用 child.exec(): child.exec(`mkdir test`);