Ответ 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. Чушь!