Интерпретация ошибок сборки

Система сборки Parcel опирается на конвейерную модель, в которой каждый модуль проходит этапы резолвинга, трансформации, оптимизации и упаковки. Ошибка может возникнуть на любом этапе и всегда сопровождается диагностическим объектом, содержащим структурированное описание причины сбоя.

Ключевая особенность Parcel заключается в унифицированном формате ошибок: независимо от источника (плагин, трансформер, резолвер), сообщение приводится к единому виду с обязательными полями контекста. Это позволяет анализировать проблему без необходимости разбирать внутреннюю реализацию каждого плагина.


Структура диагностического сообщения

Типичное сообщение об ошибке включает несколько слоёв информации:

  • type — категория ошибки (например, BuildError, SyntaxError, DependencyNotFound)
  • message — краткое описание проблемы
  • codeFrame — фрагмент исходного кода с указанием позиции
  • stack — стек вызовов, часто включающий плагины и внутренние модули Parcel
  • filePath — путь к исходному файлу
  • hint — дополнительные сведения или рекомендации от системы

Пример условного диагностического объекта:

{
  "type": "BuildError",
  "message": "Cannot resolve module 'react-dom/client'",
  "filePath": "/src/index.js",
  "codeFrame": {
    "code": "import { createRoot } from 'react-dom/client';",
    "line": 1,
    "column": 25
  }
}

Ошибки резолвинга модулей

Наиболее частый класс проблем связан с этапом разрешения зависимостей. Parcel использует резолвер, который эмулирует Node.js алгоритм, но расширяет его поддержкой алиасов, условных экспоротов и нестандартных расширений.

Типичные сценарии

Отсутствие модуля

Сообщение вида:

Cannot resolve module 'lodash-es'

Возникает при отсутствии пакета в node_modules или при некорректной установке зависимостей.

Некорректный экспорт пакета

Package subpath './dist' is not defined by "exports" in package.json

Причина заключается в ограничениях ESM-экспорта. Parcel строго следует полю exports, игнорируя прямой доступ к внутренним путям пакета.

Конфликт алиасов

При использовании конфигурации .parcelrc или tsconfig.json возможны ситуации, когда алиасы перекрывают реальные пути, приводя к резолвингу несуществующих модулей.


Ошибки трансформации кода

После успешного резолвинга модуль проходит через цепочку трансформеров: Babel, TypeScript, PostCSS и другие плагины. На этом этапе ошибки чаще всего связаны с синтаксисом или несовместимостью версий.

Синтаксические ошибки

Parcel использует парсеры AST, и любая ошибка синтаксиса приводит к остановке трансформации:

Unexpected token (10:5)

CodeFrame обычно указывает точное место нарушения:

function test() {
  const a = ;
}

Ошибки TypeScript

При включённой проверке типов могут возникать ошибки компиляции:

Type 'string' is not assignable to type 'number'

Важно, что Parcel не всегда включает строгую проверку типов по умолчанию, поэтому такие ошибки появляются только при активной интеграции с tsc или соответствующим плагином.

Ошибки Babel

Babel-трансформеры могут конфликтовать с конфигурацией пресетов:

  • отсутствие нужного плагина
  • несовместимые версии @babel/core
  • некорректные targets в .browserslistrc

Ошибки плагинов Parcel

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

Пример ошибки плагина

@parcel/transformer-sass: Undefined variable "$primary-color"

Причины:

  • отсутствует импорт переменных SCSS
  • неправильный порядок файлов
  • некорректная конфигурация includePaths

Критические сбои плагинов

При некорректной реализации плагина возможны:

  • утечки асинхронных операций
  • возврат некорректного AST
  • нарушение контрактов Parcel Transformer API

Parcel в таких случаях завершает сборку с типом BuildError и изолирует проблемный плагин.


CodeFrame и локализация ошибки

CodeFrame представляет собой ключевой инструмент диагностики. Он показывает:

  • исходный файл
  • строку и колонку ошибки
  • контекст кода до и после проблемного участка

Пример:

  8 | import React from "react";
  9 |
>10 | const value = getData(
     |               ^
 11 |   undefinedVar
 12 | );

Особенность Parcel заключается в том, что CodeFrame формируется после трансформации, но с привязкой к исходным source maps, что позволяет отображать ошибки даже после Babel или TypeScript компиляции.


Source Maps и трассировка

При многоступенчатой сборке исходный код проходит через несколько трансформаций. Source maps обеспечивают обратное отображение ошибок на оригинальный файл.

Многоуровневая трассировка

  1. TypeScript → JavaScript
  2. Babel трансформация
  3. Minification
  4. Bundling

Parcel агрегирует source maps на каждом этапе, что позволяет:

  • определить исходную строку ошибки
  • восстановить цепочку трансформаций
  • сопоставить проблему с оригинальным модулем

При повреждении source map возможны ложные позиции ошибок или смещение координат.


Ошибки кеширования

Parcel активно использует файловый кеш для ускорения сборки. Однако кеш может становиться источником нестабильных ошибок.

Типичные ситуации

  • изменение конфигурации без очистки кеша
  • обновление плагинов
  • переключение версий Node.js

Симптомы:

  • ошибки в ранее корректных модулях
  • несоответствие версий зависимостей
  • странные ошибки резолвинга

Parcel идентифицирует часть таких случаев как CacheMiss или автоматически инвалидирует кеш, но не всегда корректно.


Асинхронные ошибки и динамические импорты

Динамические импорты (import()) создают отдельные чанки, которые проходят собственный цикл сборки.

Ошибки на этом этапе часто связаны с:

  • отсутствием файла в динамическом пути
  • некорректными переменными в пути импорта
  • невозможностью статического анализа

Пример проблемного кода:

import(`./pages/${pageName}.js`);

Parcel может не определить возможные значения pageName, что приводит к ошибке во время сборки или предупреждению о невозможности статического анализа.


Ошибки параллельной обработки

Parcel использует многопоточную архитектуру Worker Threads. Ошибки могут возникать внутри worker-процессов и агрегироваться в главный процесс.

Особенности:

  • стек вызовов может быть урезан
  • исходная причина может находиться в другом worker
  • диагностика включает идентификаторы задач

Сообщения вида:

Worker crashed while processing asset

обычно указывают на критическую ошибку в трансформере или нативном модуле.


Конфликты версий зависимостей

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

Примеры:

  • разные версии postcss
  • конфликтующие версии @babel/core
  • несовместимость typescript и трансформера Parcel

Parcel пытается изолировать такие конфликты, но иногда ошибка проявляется только на этапе выполнения трансформации.


Интерпретация stack trace

Stack trace в Parcel содержит как пользовательские, так и внутренние вызовы:

Error: Cannot find module
    at Resolver.resolve (parcel:resolver-default)
    at async Transformer.process (parcel:transformer-babel)
    at async Pipeline.run (parcel:core)

Особенность анализа заключается в отделении:

  • пользовательского кода (верх стека)
  • плагинов (средний уровень)
  • ядра Parcel (нижний уровень)

Практическое значение имеет первый релевантный фрейм, относящийся к исходному файлу проекта.


Неоднозначные ошибки и деградация диагностики

Некоторые ошибки не имеют точной локализации:

  • сбои во время оптимизации
  • повреждение промежуточных AST
  • ошибки нативных бинарных зависимостей

В таких случаях Parcel возвращает обобщённые сообщения:

Build failed unexpectedly

или

Internal error occurred during bundling

Диагностика в подобных ситуациях опирается на:

  • исключение недавно добавленных плагинов
  • анализ кеша
  • поэтапное отключение трансформаций

Ошибки конфигурации проекта

Файл конфигурации .parcelrc напрямую влияет на цепочку сборки. Ошибки в нём приводят к полной деградации пайплайна.

Типичные проблемы:

  • отсутствующие пресеты
  • циклические зависимости плагинов
  • неправильный порядок transformers

Пример:

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.js": ["@parcel/transformer-babel", "@parcel/transformer-sass"]
  }
}

Конфликт типов трансформеров приводит к невозможности корректной обработки файлов.


Ошибки валидации входных данных

Parcel строго проверяет корректность входных файлов:

  • повреждённые JSON
  • некорректные SVG
  • бинарные файлы с неверным MIME

Такие ошибки обычно фиксируются на раннем этапе пайплайна и предотвращают дальнейшую обработку.


Локализация проблем в больших проектах

В масштабных проектах с сотнями модулей ошибки часто проявляются каскадно. Первичная ошибка вызывает цепочку последующих.

Характерные признаки:

  • множество одинаковых сообщений
  • повторяющиеся ошибки резолвинга
  • нестабильное воспроизведение

Parcel группирует такие ошибки по первопричине, но при сложных графах зависимостей это не всегда очевидно.