Было время, когда фронтенд-разработчики считали хорошей практикой использовать jQuery для всего. В то время мы начали создавать веб-приложение Trayn. С тех пор многое изменилось, в том числе и то, что считается хорошей практикой. Что ж, лучшие практики в области JavaScript меняются каждый второй месяц или около того, но хорошо в этом случае мне достаточно.
В продолжающейся борьбе за модернизацию нашей кодовой базы я недавно начал поэтапно отказываться от jQuery. Что я имею в виду под поэтапным отказом? Приложение слишком большое, чтобы за один раз переписать весь код, основанный на jQuery. Но так как базовый функционал приложения (управление сессиями, маршрутизация, локализация и т.д.) уже был модернизирован в последние месяцы, то только детальные представления (их много) используют jQuery и различные его плагины. Итак, план состоит в том, чтобы портировать/модернизировать одно из этих представлений за другим.
Но почему?
Зачем вообще удалять jQuery? Он все еще работает…
Что ж, мы хотим удалить не только jQuery, но и дополнительные плагины и фреймворки, а точнее — то, как мы их используем. Огромные части этих представлений используют устаревшие версии can.js, Bootstrap и FullCalendar, и одновременное обновление всего этого кода кажется более сложным, чем миграция представления за представлением на более современную компонентную архитектуру.
Укрощение наших плагинов jQuery
Использование плагинов jQuery вместе с Webpack может быть затруднительным, поскольку они обычно регистрируют их в любом экземпляре jQuery, к которому они относятся. Поскольку Webpack помещает все в свою собственную область видимости, каждый плагин окажется в другом экземпляре jQuery. Чтобы справиться с этим, Webpack предоставляет параметр конфигурации externals
, который можно использовать для исключения некоторых пакетов из сборки, если они загружены откуда-то еще. Это позволяет нам использовать один глобальный экземпляр jQuery и не ломать плагины.
Кроме того, мы копируем уменьшенный файл jQuery в наш выходной каталог для последующего использования:
// webpack.config.js const CopyWebpackPlugin = require('copy-webpack-plugin') module.exports = { externals: { jquery: 'jQuery' }, plugins: [ new CopyWebpackPlugin([{ from: 'node_modules/jquery/dist/jquery.min.js'}]) ] }
Использовать jQuery или не использовать jQuery?
Это оставляет проблему фактической загрузки jQuery, когда это необходимо. Попробовав некоторые вещи, я решил сделать это на нашем уровне маршрутизации, который использует Vue Router. Я добавил логический флаг jquery
в поле meta
маршрутов, которые все еще используют устаревший код. Проверяем его в хуке beforeEach: если флаг присутствует, навигация блокируется до загрузки jQuery. Мы не можем использовать здесь import()
или require()
, потому что мы проинструктировали Webpack рассматривать jQuery как внешнюю зависимость, поэтому мы используем scriptjs:
import $script from 'scriptjs' const ensurejQuery (route) => new Promise((resolve) => { if(route.matched.some(record => record.meta.jquery)) { $script('/jquery.min.js', resolve) } else { resolve() } }) router.beforeEach((to, from, next) => { ensurejQuery(to).then(next) })
Вывод
Используя этот подход, мы смогли отложить загрузку jQuery до тех пор, пока она действительно не понадобится. Теперь нам нужно поддерживать эти флаги jquery
в нашей конфигурации маршрута, когда мы модернизируем представления, но нам не нужно было адаптировать какой-либо из нашего устаревшего кода и уменьшить размер загрузки модернизированных частей нашего веб-приложения.
А слово «jQuery» я употребил в этой статье всего 15 раз (не считая заголовков и примеров кода), не придумав для него никаких псевдонимов.