node-canvas registerFont не может найти файл шрифта после развертывания (работает локально) - PullRequest
1 голос
/ 07 февраля 2020

У меня есть сервер Node.js, который использует node-canvas для визуализации текста на изображении на стороне сервера. Вот репозиторий: https://github.com/shawninder/meme-generator (просто git clone, npm i и npm run dev для локального запуска).

Как вы заметите в коде, я загружаю шрифт Anton , который я получил от здесь с документированной функцией registerFont, предоставленной node-canvas

registerFont('./public/fonts/Anton-Regular.ttf', { family: 'Anton' })

Все работает локально, как шарм, но при развертывании на Vercel (ранее известном как zeit) эта строка выдает ошибку ENOENT:

нет такого файла или каталога

  • Можно ли здесь использовать путь, который успешно загрузит шрифт из функции Vercel?
  • Можно ли найти один путь, который будет работать как локально, так и после развертывания?

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Я думаю, вы были очень близки с registerFont. Вот что я получил, работая с вашим репо:

В img.js:

import { registerFont, createCanvas, loadImage } from 'canvas'

// …

// Where 'Anton' is the same font-family name you want to use within
// your canvas code, ie. in writeText.js.
registerFont('./pages/fonts/Anton/Anton-Regular.ttf', { family: 'Anton' })

// Make sure this goes after registerFont()
const canvas = createCanvas()

//…

Я добавил в pages/ новую папку с именем fonts/ и добавил скачанную папку Anton от Google Fonts. Нажмите «Download Family», чтобы получить файл шрифта отсюда: https://fonts.google.com/specimen/Anton?query=Anton&selection.family=Anton&sidebar.open

Другой загруженный вами файл (https://fonts.googleapis.com/css?family=Anton&display=swap) на самом деле CSS файл, который вы хотите использовать в браузере для клиентской части на стороне клиента шрифтов.

Сначала я бы продолжил использовать размещенную версию, предоставляемую Google Fonts. Вы можете добавить это к компоненту PreviewMeme.js:

<link href="https://fonts.googleapis.com/css2?family=Anton" rel="stylesheet" />
<canvas id='meme' ref={canvas}></canvas>

(Вы также можете использовать что-то вроде FontFaceObserver на стороне клиента, чтобы убедиться, что шрифт загружен перед рендерингом вашего холста. в первый раз.)

В writeText.js вы также замените fontFamily на Anton:

const fontFamily = 'Anton'

, что сделает Антона доступной на стороне клиента через размещенные Google Fonts, и он должен быть доступен вам в виде файла на сервере для рендеринга с помощью серверного холста.

“Top” “Bottom” sample image output from provided code

Надеюсь, это полезно!

0 голосов
/ 04 мая 2020

Недавно у меня была такая же проблема, и я наконец нашел решение. Я не гуру, поэтому кто-то, вероятно, сможет предложить лучший способ, но вот что сработало для меня.

Из-за того, как Vercel выполняет свои функции без сервера, функция на самом деле ничего не знает о остальная часть проекта или папка publi c. Это имеет смысл (потому что безопасность), но это усложняет, когда вам нужен фактический путь к файлу. Вы можете импортировать файл шрифта без проблем, процесс сборки даст ему новое имя и поместит его на диск (в /var/task), но вы не сможете получить к нему доступ. path.resolve(_font_name_) может видеть его, но вы не можете получить к нему доступ.

Я закончил тем, что написал очень плохую отдельную страницу API, которая использовала path.join и fs.readdirSync, чтобы увидеть, какие файлы действительно видны из страница API. Одна вещь, которая видна, это папка node_modules, которая содержит файлы для модулей, используемых на этой странице API.

fs.readdirSync(path.join(process.cwd(), 'node_modules/')

Итак, я написал локальный модуль, установил его в свой проект и импортировал в моя страница API. В локальном модуле package.json у меня есть строка "files": ["*"], поэтому он объединит все файлы модуля в свою папку node_modules (вместо просто файлов. js). В моем модуле у меня есть файл шрифта и функция, которая копирует его в /tmp (/tmp доступен для чтения и записи), а затем возвращает путь к файлу /tmp/Roboto-Regular.ttf.

На своей странице API я включаю этот модуль, затем запускаю его и передаю результирующий путь в registerfont.

Он работает. Я бы поделился своим кодом, но сейчас он довольно небрежный, и я хотел бы сначала очистить его и попробовать пару вещей (например, я не уверен, нужно ли мне копировать его в / tmp, но у меня нет Я проверил это без этого шага). Когда я это улажу, я отредактирую этот ответ.

...