import archive from '../data/articles.json' with { type: 'json' }; const archiveBySlug = new Map(archive.map((article) => [article.slug, article])); function p(text) { return '

' + text + '

'; } function h2(text) { return '

' + text + '

'; } function escapeHtml(value) { return value .replaceAll('&', '&') .replaceAll('<', '<') .replaceAll('>', '>'); } function codeBlock(lines) { return '
' + escapeHtml(lines.join('\n')) + '
'; } function table(headers, rows) { const head = '' + headers.map((item) => '' + item + '').join('') + ''; const body = '' + rows.map((row) => '' + row.map((item) => '' + item + '').join('') + '').join('') + ''; return '' + head + body + '
' + headers[0] + ': рабочая матрица проверки
'; } function orderedList(items) { return '
    ' + items.map((item) => '
  1. ' + item + '
  2. ').join('') + '
'; } function figure(src, alt, caption) { return '
' + alt + '
' + caption + '
'; } function sources(items) { return ''; } function plainText(content) { return content .replace(/<[^>]+>/g, ' ') .replace(/&(?:quot|amp|lt|gt|#039);/g, ' ') .replace(/\s+/g, ' ') .trim(); } function legacyBody(article, limit = 6600, omitPatterns = []) { const withoutSources = (article.contentHtml || '') .replace(/

Проверяемые источники<\/h2>[\s\S]*$/i, '') .replace(/
[\s\S]*?<\/figure>/gi, '') .replace(/]*>([\s\S]*?)<\/a>/gi, '$1') .replace(/<\/?div[^>]*>/gi, ''); const blocks = withoutSources.match(/<(?:p|h2|h3|pre|ul|ol)\b[\s\S]*?<\/(?:p|h2|h3|pre|ul|ol)>/gi) || []; const result = []; let length = 0; for (const block of blocks) { if (omitPatterns.some((pattern) => pattern.test(plainText(block)))) continue; const blockLength = plainText(block).length; if (result.length > 0 && length + blockLength > limit) break; result.push(block); length += blockLength; } return result.join('\n'); } const cases = { 'использование-jquery-в-webpack': { title: 'JavaScript. jQuery в Webpack: глобальная зависимость без скрытого порядка', excerpt: 'Как подключить jQuery к Webpack-проекту, когда часть кода ждёт window.jQuery, а новые модули используют import.', cover: '/assets/illustrations/jquery-webpack.svg', problem: 'Старая страница видит `$`, а новый модуль получает пустое значение. Цена ошибки — либо дублированная библиотека в каждом бандле, либо плагины, которые работают только из-за случайного порядка подключения.', context: 'Оригинальный материал правильно начинает с установки пакета и `ProvidePlugin`. В редактуре важно разделить две задачи: дать старому коду совместимое глобальное имя и оставить импорт явным в новых модулях. Если смешать их в одном правиле сборки, после смены entry-файла ошибка проявится только на части страниц.', mechanism: ['Webpack строит граф модулей из import и require. Глобальная переменная не входит в этот граф как обычная зависимость, поэтому старый плагин может работать только при дополнительном правиле ProvidePlugin или явной записи в window.', 'ProvidePlugin подставляет импорт в местах, где встречается идентификатор. Это не делает jQuery глобальной для любого скрипта, загруженного отдельно через HTML. Для такого скрипта нужен один согласованный entry и одна точка экспорта.', 'Если библиотека уже приходит с CDN, её следует объявить external и проверить, что глобальное имя появляется раньше потребителя. Две независимые копии jQuery дают разные объекты и ломают плагины, которые сравнивают `$.fn` или регистрируют обработчики.'], code: ['const webpack = require(\'webpack\');', '', 'module.exports = {', ' entry: {', ' legacy: \'./src/legacy-entry.js\',', ' modern: \'./src/modern-entry.js\'', ' },', ' plugins: [', ' new webpack.ProvidePlugin({', ' $: \'jquery\',', ' jQuery: \'jquery\'', ' })', ' ]', '};', '', '// В новом модуле зависимость остаётся видимой.', "import $ from 'jquery';", 'export function mount() {', ' return $.fn && $.fn.jquery;', '}'], rows: [['Слой', 'Что проверяем', 'Типичная ошибка'], ['Новый модуль', 'Есть `import $ from \'jquery\'`', 'Зависимость спрятана в window'], ['Старый плагин', 'Потребитель получает тот же объект', 'Созданы две копии jQuery'], ['Entry', 'Библиотека загружена до потребителя', 'Порядок зависит от HTML'], ['CDN', 'external и глобальное имя согласованы', 'Бандл ожидает модуль, а получает URL']], steps: ['Определить, какие файлы используют import, а какие обращаются к `$` или `window.jQuery`.', 'Оставить один способ доставки jQuery для каждого entry: пакет или external, но не случайную смесь.', 'Добавить ProvidePlugin только для legacy-кода и проверить итоговый граф сборки.', 'Запустить страницу с реальным старым плагином и убедиться, что объект jQuery один.', 'После миграции каждого потребителя удалить лишнее глобальное правило и зафиксировать это в тесте сборки.'], limits: ['ProvidePlugin не исправляет порядок независимых `