Что такое "require.context"

Webpack Docs

You can create your own context with the require.context() function. ,
Отлично. Что такое "контекст"? Что это на самом деле делает?

It allows you to pass in a directory to search, a flag indicating whether subdirectories should be searched too, and a regular expression to match files against. ,
Позволяет мне "искать"? Поиск файлов я предполагаю, и что тогда? Что в конечном итоге делает эта функция? Для чего его используют?

Ответы

Ответ 1

Одна из основных функций компилятора webpack - рекурсивный анализ всех модулей, начиная с записей, для построения графика всех зависимостей модулей путем анализа выражений require(), require.context(), import и import().

Обычная интерпретация "контекста" в веб-пакете и аналогично в Node.js - это некий каталог, который используется в качестве основы для разрешения путей к модулям. Например, текущий рабочий каталог используется в качестве контекста по умолчанию для веб-пакета для разрешения фактического пути к index.js ввода index.js; контекстом для запроса require.resolve('../../../foo.js') является __dirname.

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

Короче говоря, вы будете использовать require.context в точно такой же ситуации, когда в Node.js во время выполнения вы будете использовать globs для динамического построения списка требуемых путей к модулям. Возвращаемое значение - это вызываемый объект, который ведет себя как require, ключи которого содержат необходимые данные запроса модуля, которые могут быть переданы ему в качестве аргумента для запроса модуля.

Есть несколько способов его использования, но я думаю, что два наиболее распространенных варианта использования - это либо автоматически требовать некоторые хорошо известные some.test.js модулей (например, вы просто добавляете тестовый модуль some.test.js а в некоторых используемых вами модулях require.context для динамического обнаружения всех тестов, таким образом, не нужно документировать и не забывать делать это вручную каждый раз, когда вы добавляете новый тестовый модуль) или загружать статические ресурсы в хранилище для отправки файлов на вывод сборки (новые пользователи веб-пакетов приходят из других Инструменты сборки обычно удивляются, что их изображения, шрифты, аудиофайлы и другие ресурсы не появляются в выводе, если они не требуются от какого-либо модуля).

Ответ 2

Вот практичный, но длинный пример, так что терпите меня. Я собираюсь показать вам, как загружать фрагменты HTML из папки и выводить их на страницу, используя Webpack и require.context().

В наши дни существует множество способов создать веб-сайт с использованием шаблонов и языков шаблонов: у вас есть handlebars, mustache, markdown, jasmine, JSX, и множество статических генераторов для их работы, например, Eleventy, Hugo, Gatsby. И это не говоря уже о выборе ванильного HTML или какой-то фреймворк, такой как Vue.

Но иногда вам просто нужно взять HTML-код из некоторых файлов и выложить его на страницу. И есть способ загрузить фрагменты HTML из папки и вывести их на страницу, используя Webpack и require.context().

Зачем вообще использовать require.context или HTML-фрагменты?

Если вы хотите создать веб-сайт или даже небольшое веб-приложение, возможно, существуют более простые и масштабируемые методы.

Однако недавно я создавал простую компонентную библиотеку пользовательского интерфейса и хотел быстро получить простой HTML-код и включить его в конечную страницу - или серию страниц - чтобы показать живую версию библиотеки в действии.

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

Я использую Webpack, чтобы объединить все и справиться с обработкой CSS и JS, поэтому имело смысл попытаться найти простой способ задействовать Webpack для захвата этих файлов и их обработки., Конечно, есть и другие варианты, но некоторые из них не так уж и осуществимы... Но здесь мы концентрируемся на решении на основе Webpack

Выручите через Webpack и require.context()!

Итак, поскольку мы уже используем Webpack для создания этой вещи, давайте воспользуемся одной из замечательных функций Webpack: require.context().

Сначала настройте html-загрузчик для обработки наших файлов Во-первых, поскольку мы загружаем файлы HTML, нам нужно установить html-загрузчик Webpack; легкий подвиг с npm/пряжа:

npm i -D html-loader or yarn add --dev html-loader

Отсюда нам нужно добавить конфигурацию html-загрузчика в наш webpack.config.js

module: {
        rules: 
        [
            {
                test: /\.html$/,
                exclude: /node_modules/,
                use: {
                    loader: 'html-loader'
                }
            },
            ...
            {
            //other rules here
            }
        ]
      }

Теперь Webpack может распознавать и обрабатывать HTML файлы для нас, если мы сделаем что-то вроде этого:

require('/path/to/html/file.html');

Но это всего лишь один файл, нам нужно загрузить группу, которая будет растущим списком - нецелесообразно продолжать добавлять по одной строке за раз.

Теперь мы можем загружать HTML файлы, мы можем использовать require.context() для загрузки некоторых файлов в папке и обработки их содержимого.

Вот что я сделал, чтобы добиться именно этого:

// grab the element where we'll output the HTML to
const output = document.querySelector('#output');

// create a 'cache' where we can store our built up HTML from our fragments
let htmlFragmentCache = {};

// here, we're creating an anonymous function that loads up our HTML fragments
// then it adds them to our cache object
const importAll = requireContext => requireContext.keys().forEach(key => htmlFragmentCache[key] = requireContext(key));

// next, we call our importAll() function to load the files
// notice how this is where we call the require.context() function
// it uses our file path, whether to load subdirectories and what file type to get
importAll(require.context('./fragments', false, /.html$/));

// finally, we can loop over our cache keys and add the HTML to our output element
Object.keys(htmlFragmentCache).forEach(key => output.innerHTML += htmlFragmentCache[key]);

И это так просто! Конечно, даже эти скудные несколько строк могут быть сведены в анонимную функцию (на самом деле, пример Immediately Invoked Function Expression or IIFE) для создания еще более чистого, более короткого конечного результата:

(context => {
    // need to clear out the current element contents (just in case!)
    output.innerHTML = '';

    // now, load up the html fragments and add them to the page
    context.keys().forEach(key => output.innerHTML += context(key));
})(require.context('./fragments', false, /.html$/));

И у нас это есть. Действительно простой и простой способ загрузить несколько файлов HTML в папку, используя require.context() в файле JavaScript, загружать, обрабатывать и связывать с помощью Webpack. Чушь!