Рубрики
Без рубрики

Давайте узнаем, как работают модуль Bundlers, а затем напишите один

Адамом Келли давайте узнаем, как работают модуль Bundlers, а затем написать один наульцеелло! Добро пожаловать, добро пожаловать, приятно у вас здесь! Сегодня мы собираемся строить действительно простой модуль JavaScript Bundler. Прежде чем мы начнем, я хочу дать несколько признаний. Эта статья рисует

Автор оригинала: FreeCodeCamp Community Member.

Адамом Келли

Привет! Добро пожаловать, добро пожаловать, приятно у вас здесь! Сегодня мы собираемся строить действительно простой модуль JavaScript Bundler.

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

Хорошо, давайте начнем с тем, что на самом деле это модуль Bundler.

Что такое модуль Bundler?

Модуль Bundler – это инструмент, который принимает кусочки JavaScript и их зависимости и связывает их в один файл, обычно для использования в браузере. Возможно, вы использовали такие инструменты, как Брасифицировать , WebPack , Роллап или один из многих других.

Обычно это начинается с файла ввода, и оттуда он сочиняет весь код, необходимый для этого файла ввода.

Есть два основных этапа Бандлера:

  1. Разрешение зависимостей
  2. Упаковка

Начиная с точки входа (например, app.js выше), целью разрешения зависимостей состоит в том, чтобы искать все зависимости вашего кода (другие кусочки кода, которые он должен функционировать) и построить график ( называется графиком зависимости).

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

Давайте начнем наш код с помощью некоторых импорта (я уточню причину позже).

Разрешение зависимостей

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

Представление модуля

Нам нужно понадобиться четыре вещи:

  • Имя и идентификатор файла
  • Откуда пришел файл (в файловой системе)
  • Код в файле
  • Какие зависимости которые нуждаются в файле

Структура графов устанавливается путем рекурсивно проверки на зависимости в каждом файле.

В JavaScript самый простой способ представить такой набор данных.

Глядя на CreateModuleObject Функция выше, заметная часть – это вызов функции, называемой детектив Отказ

Детектив это библиотека, которая может « Найти все призывы требуют () Неважно, насколько глубоко вложены И используя это означает, что мы можем избежать прохождения нашего собственного AST!

Одно следует отметить (и это то же самое практически во всех бингарах модуля) в том, что если вы попытаетесь сделать что-то странное, как:

const libName = 'lodash'const lib = require(libName)

Это не сможет найти его (потому что это будет означать выполнение кода).

Так Что работает эта функция с пути модуля?

Что дальше? Разрешение зависимостей.

Хорошо, еще не совсем. Во-первых, я хочу поговорить о том, что называется карта модуля.

Модуль карта

При импорте модулей в узле вы можете сделать относительный импорт, например требуют ('./utils') Отказ Поэтому, когда ваш код вызывает это, как Bundler знает, что правильно ./тилс Файл, когда все упаковано?

Это проблема, которую решает карту модуля.

Наш модуль объект имеет уникальный ID Ключ, который будет нашим «источником правды». Поэтому, когда мы делаем разрешение на зависимостью, для каждого модуля мы будем держать список названий того, что требуется вместе с их идентификатором. Таким образом, мы можем получить правильный модуль во время выполнения.

Это также означает, что мы можем хранить все модули в не вложенном объекте, используя идентификатор в качестве ключа.

Разрешение зависимостей

Хорошо, так что в GetModules функция. Его основная цель – начать в модуле корня/ввода, и искать и разрешать зависимости рекурсивно.

Что я имею в виду под «разрешать зависимости»? В узле есть вещь называется потребовать , и именно так узел, где требуется файл, который вы требуете. Это потому, что мы можем импортировать относительно или из node_modules папка.

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

Нам нужно выполнить это разрешение для каждой зависимости каждого модуля в проекте.

Мы также создаем карту модуля с именем карта что я упоминал ранее.

В конце функции мы остались с массивом, названным модули который будет содержать объекты модуля для каждого модуля/зависимости в нашем проекте.

Теперь, когда у нас есть это, мы можем перейти к последнему шагу: Упаковка!

Упаковка

В браузере нет такой вещи, как модули (вид). Но это означает, что нет нужной функции, а нет Module.exports Отказ Так что, хотя у нас есть все наши зависимости, у нас сейчас нет способа использовать их в качестве модулей.

Функция модуля фабрики

Введите заводскую функцию.

Функция заводская функция – это функция (это не конструктор), который возвращает объект. Это шаблон от объектно-ориентированного программирования, а одно из его применений – делать инъекцию инкапсуляции и зависимости.

Звучит неплохо?

Использование заводской функции мы можем ввести наших собственных требуется Функция и Module.exports Объект, который можно использовать в нашем комплектном коде и дать модуль свой собственный объем.

Упаковка

Ниже приведен функция пакета, которая используется для упаковки.

Большинство из этого – просто шаблонные литералы JavaScript, поэтому давайте обсудим, что это делает.

Во-первых, это Модульссуарс Отказ Здесь мы проходим через каждый из модулей и преобразуем их в строку источников.

Так что такое выход для объекта модуля?

Теперь немного прочитать, но вы можете видеть, что источник инкапсулируется. Мы предоставляем модули и требуется Использование функции завода, как я уже упоминал ранее.

Мы также включаем карту модулей, которые мы построили во время разрешения зависимости.

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

Следующая строка кода является IIFE, что означает, что при запуске этого кода в браузере (или где-либо еще) функция будет работать немедленно. IIFE – еще один рисунок для инкапсулирования, и используется здесь, поэтому мы не загрязняем глобальную область с нашими требуется и модули.

Вы можете видеть, что мы определяем два функция требуют, требуется и localrequire Отказ

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

После этого мы определяем Объект модуля что модуль может заполнить и передавать как функции на завод, после чего мы возвращаем Module.exports Отказ

Наконец, мы называем требовать (0) Для требуния модуля с идентификатором 0, который является нашим входом.

Вот и все! Наш модуль Bundler на 100% полный!

Поздравляю! ?

Таким образом, у нас сейчас есть рабочий модуль Bundler.

Это, вероятно, не должно использоваться в производстве, потому что оно отсутствует нагрузки функций (например, управление круговыми зависимостями, убедившись, что каждый файл делает только один раз, ES-модули и т. Д.) Но это, надеюсь, дал вам хорошее представление о том, как Модульные бундалы на самом деле работают.

На самом деле, этот работает около 60 линий, если вы удалите весь исходный код.

Спасибо за чтение, и я надеюсь, что вы понравились на разработку нашего простого модуля Bundler. Если бы вы сделали, убедитесь, что Clap? и поделиться.