Представить интерфейс Canvas в общем коде на сервере и клиенте

Я пытаюсь написать общий код (который работает как на сервере, так и на клиенте), который использует холст HTML.

На клиенте это должно прекрасно работать. На сервере Node нет холста (или DOM), поэтому я бы хотел использовать плагин node-canvas: https://github.com/Automattic/node-canvas.

Однако я не могу найти способ получить к нему доступ, который не заставляет веб-пакет пытаться связать узел-холст с моим клиентским кодом (который приводит к сбою веб-пакета). Есть ли способ загрузки node-canvas таким образом, чтобы я мог ссылаться на него с тем же кодом, который я буду использовать в браузере, и без ужасного сбоя webpack?


Мои текущие усилия, которые не сработали:

canvas.server.js

import Canvas from 'canvas';

const createCanvas = (width, height) => new Canvas(width, height);

export default createCanvas;

canvas.client.js

const createCanvas = (width, height) => {
  const canvas = document.createElement('canvas');
  canvas.width = width;
  canvas.height = height;

  return canvas;
};

export default createCanvas;

canvas.js

let createCanvas;

if (typeof document === 'undefined') {
  // SERVER/node
  createCanvas = require('./canvas.server.js');
} else {
  // BROWSER
  createCanvas = require('./canvas.client.js');
}

export default createCanvas;

в использовании:

import createCanvas from './canvas';

const canvasElement = createCanvas(width, height);
const ctx = canvasElement.getContext('2d');

К сожалению, webpack все еще входит в node-canvas.

1 ответ

Вы пробовали требовать node-canvas только когда код работает в узле?

Если вы на самом деле не вызываете require в коде переднего плана, webpack не будет связывать его. Это означает, что вызов фактического require внутри вышеупомянутого условного заявления, а не в верхней части вашего файла. Это важно. Также убедитесь, что вы не ставили node-canvas в качестве точки входа в веб-упаковке.

Пример:

// let's assume there is `isNode` variable as described in linked answer
let canvas;
if (isNode) {
  const Canvas = require('canvas');
  canvas = new Canvas(x, y);
else {
  canvas = document.getElementById('canvas');
}
// get canvas context and draw on it

Изменить после OP предоставленный пример кода:

Я воспроизвел точную структуру в этом WebpackBin, чтобы доказать, что это должно работать, как описано выше. В конце концов, это особенность common.js (и других загрузчиков модулей) и поэтому поддерживается в веб-пакете.

Мои изменения в коде:

  1. Заменил код в canvas.client.js а также canvas.server.js с console.log о том, что будет называться в этой строке
  2. Исправлено неправильное использование require с export default (должно быть require(...).default). Не имеет значения, но должен был сделать это, чтобы код работал.
  3. Удалил canvasElement.getContex вызов. Не будет работать в примере кода и в любом случае не имеет значения, поэтому нет смысла насмехаться над ним.
Другие вопросы по тегам