Истории отладки: как скетч сломал CKEditor

16 февраля мне посчастливилось столкнуться с одной из самых странных ошибок, с которыми я когда-либо сталкивался. Давайте установим сцену:

(Это столкновение с кодером, и некоторые детали были изменены, чтобы защитить личность подопечного)

В один из субботних дней я получил сообщение от кодеров о проблеме с вебпаком. У нашего клиента, которого мы будем называть Джорджем, возникли проблемы с тем, как заменить значки в CKEditor некоторым выражением регулярного выражения. Немедленно, NormalModuleReplacementPlugin приходит на ум. API прост и позволяет вам заменить любой модуль, вызываемый require или импортировать с любым другим произвольным модулем.

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

У Джорджа есть несколько файлов, которые он хочет переопределить с помощью веб-пакета, поэтому мы решили собрать некоторые вспомогательные функции внутри веб-пакета.

Во-первых, мы определили некоторый четкий и последовательный API, который позволил бы нам настроить этот помощник. В итоге мы получили массив объектов конфигурации следующим образом

const replaceModules = [
  { match: /some-icon\.svg/, replace: path.resolve(__dirname, 'src/icons/new-icon.svg') } 
]

Большой! это позволило бы нам определить функцию, которая генерирует плагины для обработки каждого случая.

function createModuleReplacements(configurations) {
   return configurations.map( config => 
     new webpack.NormalModuleReplacementPlugin(config.match, config.replace)
   )
}

Затем мы интегрируем это в плагины веб-пакета, распространяя их в конфигурации плагинов. Все хорошо и хорошо.

Мы протестировали его с одним элементом конфигурации, и он работал плавно. Проблемы начались, когда мы добавили несколько элементов конфигурации. Внезапно иконки начали дублироваться. Каждый раз, когда мы добавляли новую конфигурацию, один и тот же значок начинал появляться в одном и том же месте.

Большой. Некоторая недетерминированная, связанная с порядком ошибка веб-пакета и разрешения модуля. Вероятно, это одни из самых сложных ошибок для отслеживания. Итак, мы решили выяснить, что происходит.

Идея 1. Возможно, у веб-пакета проблемы с обработкой всех этих копий плагина. Это натянуто, но что, если бы мы использовали один плагин, который принимает функцию, вместо того, чтобы распространять несколько плагинов.

new webpack.NormalModuleReplacementPlugin(/.+\.svg$/, resource => {
   // we first check if this resource matches one of the items in our config
   const configuration = replaceModules
     .find( configuration => configuration.match.test( resource.request ) )
  if (configuration) {
      resource.request = configuration.replace // re asign the configuration
    }
})

Итак, мы получаем это и даем ему сборку. Нет, та же проблема.

Идея 2. Может быть, мы совпадаем сами с собой. У нас было несколько сменных модулей, которые были подмножествами других запросов регулярных выражений. Может быть, мы перезаписывали себя

(мы даем этому шанс)

До сих пор нет кости.


На данный момент я клонировал исходный код библиотеки, начал воссоздавать среду сборки и копаться в node_modules.

Тут я замечаю нечто странное. Вот так выглядит иконка в библиотеке

<svg viewBox="0 0 20 20" xmlns=" d="M10... (truncated)"/></svg>

А вот так выглядели svg, которые были у нас в исходниках

<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns=" xmlns:xlink="
    <!-- Generator: Sketch 52.2 (67145) -  -->
    <title>👾 (...)</title>
    <desc>Created with Sketch.</desc>
    <defs>
        <path d="M5... (truncated)" id="path-1"></path>
    </defs>
    <g id="🌈(...)" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <rect id="Bounds" x="0" y="0" width="24" height="24"></rect>
        <rect id="Live-Area" x="2" y="2" width="20" height="20"></rect>
        <mask id="mask-2" fill="white">
            <use xlink:href="#path-1"></use>
        </mask>
        <use id="Text-Align-Right" fill="#293F4D" fill-rule="nonzero" transform="translate(11.842090, 11.752865) scale(-1, 1) translate(-11.842090, -11.752865) " xlink:href="#path-1"></use>
        <g id="🌈-(...)" mask="url(#mask-2)" fill="#293F4D">
            <rect x="0" y="0" width="24" height="24"></rect>
        </g>
    </g>
</svg>

Эскиз. экспорт. смайлики. в SVGS.

Хотя смайлики определенно не были проблемой, эта мысль все еще беспокоила меня.

Обычно это не было бы проблемой, если бы мы использовали какой-либо загрузчик файлов или другой механизм для объединения этих ресурсов вместе. К сожалению, мы использовали raw-loader чтобы включить эти активы в окончательную сборку js. Это означало, что эти файлы вставлялись байт за байтом в наш пакет js.

Я не совсем уверен, ПОЧЕМУ это сломало CKEditor. Все, что я знаю, это то, что удаление из этого файла всех дополнений исправило нашу сборку, и все отобразилось правильно.

Отличный способ провести 4 часа. 10/10 будет отлаживать снова.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *