Скомпилируйте и объедините свои файлы MDX и их зависимости. БЫСТРЫЙ.
У вас есть строка MDX и различных файлов TS/JS, которые он использует, и вы хотите получить комплексную версию этих файлов для оценки браузера.
Это асинхронная функция, которая будет компилировать и объединить ваши файлы MDX и их зависимости. Он использует MDX V3 и ESBUILD, поэтому он очень быстрый и поддерживает файлы TypeScript (для зависимостей ваших файлов MDX).
Ваши исходные файлы могут быть локальными, в репонировании удаленного GitHub, в CMS или где -то еще, и это не имеет значения. Все, что заботится о mdx-bundler
, это то, что вы передаете все необходимые файлы и исходный код, и он позаботится о том, чтобы закупить все для вас.
MDX позволяет вам объединить синтаксис маркировки TERSE для вашего контента с мощностью компонентов React. Для сайтов, страдающих контентом, написание контента с прямым HTML может быть досадно условно. Часто люди решают это, используя редактор Wsywig, но слишком часто те, кто не хватает, в картировании намерения писателя на HTML. Многие люди предпочитают использовать Marckdown, чтобы выразить свой источник контента, и проанализировались в HTML, чтобы отображаться.
Проблема с использованием Markdown для вашего контента заключается в том, что если вы хотите, чтобы в ваш контент был встроен какую -то интерактивность, вы довольно ограничены. Вам либо нужно вставить элемент, на который целевой JavaScript (что раздражающе косвенно), либо вы можете использовать iframe
или что -то в этом роде.
Как указывалось ранее, MDX позволяет вам объединять синтаксис Markdown Terse для вашего контента с мощностью компонентов React. Таким образом, вы можете импортировать компонент React и представить его в самой парке. Это лучший из обоих миров.
next-mdx-remote
?" mdx-bundler
на самом деле связывает зависимости ваших файлов MDX. Например, это не сработает с next-mdx-remote
, но это будет с mdx-bundler
:
--- Название: Пример после публикации: 2021-02-13description: Это некоторое описание ---# wahooimport demo от './demo' Вот ** аккуратная ** демонстрация: <Демо />
next-mdx-remote
задыхается от этого импорта, потому что это не пучок, это просто компилятор. mdx-bundler
является компилятором MDX и Bundler. Это разница.
Эти инструменты предназначены для запуска «во время сборки», а затем вы разверните встроенную версию ваших файлов. Это означает, что если у вас есть какой -то контент в MDX и вы хотите изменить опечатку, вы должны восстановить и перераспределить весь сайт. Это также означает, что каждая страница MDX, которую вы добавляете на ваш сайт, увеличит ваш разборщик, поэтому она не так хорошо масштабируется.
mdx-bundler
определенно может быть использован во время сборки, но он более мощно используется в качестве пучка времени выполнения. Распространенным вариантом использования является маршрут для вашего содержания MDX, и когда этот запрос входит, вы загружаете содержание MDX и передали его mdx-bundler
для объединения. Это означает, что mdx-bundler
бесконечно масштабируется. Ваша сборка не будет больше, независимо от того, сколько у вас контента MDX. Кроме того, mdx-bundler
довольно быстрый, но для того, чтобы сделать это по требованию еще быстрее, вы можете использовать соответствующие заголовки кеша, чтобы избежать ненужного переосмысления.
WebPack/Rollup/ETC также требует, чтобы все ваши файлы MDX находились в локальной файловой системе для работы. Если вы хотите сохранить свой контент MDX в отдельном репо или CMS, вам не повезло или вам нужно сделать гимнастику времени на сборку, чтобы получить файлы для сборки.
С mdx-bundler
не имеет значения, откуда берется ваш контент MDX, вы можете объединить файлы из любого места, вы просто несете ответственность за попадание контента в память, а затем вы передаете его mdx-bundler
за объединение.
Полностью. Это работает с любым из этих инструментов. В зависимости от того, поддерживает ли ваша мета-обратная работа рендеринг на стороне сервера, вы реализуете его по-разному. Вы можете решить использовать подход встроенного времени (для Gatsby/CRA), но, как уже упоминалось, истинная сила mdx-bundler
приходит в форме объединения по требованию. Так что он лучше всего подходит для фреймворков SSR, таких как Remix/Next.
Почему нет?
Esbuild предоставляет услугу, написанную в Go, с которой он взаимодействует. Только один экземпляр этой службы может работать за раз, и он должен иметь идентичную версию в пакет NPM. Если бы это была жесткая зависимость, вы могли бы использовать только использующую версию ESBUILD MDX-Bundler.
Установка
Использование
Параметры
Возврат
Типы
Компонентная замена
Фронтальная и Конста
Доступ к именованным экспортам
Обработка изображения
Объединить файл.
Пользовательские компоненты в нижестоящих файлах
Известные проблемы
Вдохновение
Другие решения
Проблемы
? Ошибки
Запросы функций
Участники
ЛИЦЕНЗИЯ
Этот модуль распределен через NPM, который связан с узлом и должен быть установлен в качестве одной из dependencies
вашего проекта:
npm install --save mdx-bundler esbuild
Одна из зависимостей MDX-Bundler требует, чтобы работающая настройка узла-GYP была способна правильно установить.
Import {bundlemdx} из 'mdx-bundler'const mdxsource = `--- Название: Пример после публикации: 2021-02-13description: Это некоторое описание ---# wahooimport demo от' * Демо: <demo /> `.trim() const result = await bundlemdx ({ Источник: mdxsource, Файлы: {'./demo.tsx': `import * as React from 'React'function demo () {return <viv> quic demo! </div>} Экспорт Демо по умолчанию`, },}) const {code, frontmatter} = результат
Оттуда вы отправляете code
своему клиенту, а затем:
Import * AS React From 'React'Import {getMdxComponent} из' mdx-bundler/client'function post ({code, frontmatter}) { //, как правило, хорошая идея запоминать этот вызов функции // Избегайте воссоздания компонента каждого рендеринга. const component = React.usememo (() => getmdxcomponent (code), [code]) return (<> <Header> <h1> {FrontMatter.title} </h1> <p> {FrontMatter.description} </p> </header> <main> <component/> </main> </> )}
В конечном счете, это отображается (в основном):
<заголовок> <h1> это название </h1> <p> Это некоторое описание </p> </header> <main> <div> <h1> wahoo </h1> <p> Вот <strong> aeat </strong> demo: </p> <div> quice demo! </div> </div> </main>
string
источника вашего MDX.
Не может быть установлено, если file
установлен
Путь к файлу на вашем диске с MDX. Вы, вероятно, также захотите установить CWD.
Не может быть установлено, если source
установлен
Конфигурация files
является объектом всех файлов, которые вы объедините. Ключ - это путь к файлу (по сравнению с источником MDX), а значение - строка исходного кода файла. Вы можете получить их из файловой системы или из удаленной базы данных. Если ваш MDX не ссылается на другие файлы (или импортирует только вещи из node_modules
), то вы можете полностью пропустить это.
Это позволяет изменить встроенную конфигурацию MDX (передаваемой @mdx-js/esbuild
). Это может быть полезно для указания ваших собственных замечаний/регипеплугинс.
Функция передается по умолчанию MDXOPTIONS и FrontMatter.
bundlemdx ({ Источник: mdxsource, Mdxoptions (Options, FrontMatter) {// Это рекомендуемый способ добавить пользовательские плагины замечания/rehype: // Синтаксис может выглядеть странно, но он защищает вас в случае, если мы добавляем/снимаем // плагины в будущем. = [... (options.remarkplugins ?? []), myremarkplugin] опции. },})
Вы можете настроить любой из вариантов Esbuild с помощью опции esbuildOptions
. Это принимает функцию, которая выполняется по умолчанию параметров Esbuild и передней панели и ожидает возврата объекта параметров.
bundlemdx ({ Источник: mdxsource, Esbuildoptions (Options, FrontMatter) {options.minify = falseOptions.Target = ['es2020', 'chrome58', 'firefox57', 'safari11', 'edge16', 'node12',] варианты возврата },})
Более подробную информацию о доступных вариантах можно найти в документации Esbuild.
Рекомендуется использовать эту функцию для настройки target
на ваш желаемый вывод, в противном случае ESBUILD по умолчанию в esnext
, который должен сказать, что он не составляет какие -либо стандартизированные функции, поэтому возможные пользователи старых браузеров будут испытывать ошибки.
Это говорит ESBUILD, что заданный модуль доступен извне. Например, если ваш файл MDX использует библиотеку D3, и вы уже используете библиотеку D3 в вашем приложении, вы в конечном итоге вы отправите d3
дважды (один раз для вашего приложения и один раз для этого компонента MDX). Это расточительно, и вам было бы лучше просто сказать Esbuild не связывать d3
, и вы можете передать его компоненту самостоятельно, когда вы называете getMDXComponent
.
Глобальные параметры внешней конфигурации: https://www.npmjs.com/package/@fal-works/esbuild-plugin-global-externals
Вот пример:
// код на стороне сервера или время сборки, который работает в узле: import {bundlemdx} из 'mdx-bundler'const mdxsource = `# Это левая панель TitleImport от« левой падки »<div> {Leathpad (" aeat demo ! ", 12, '!')} </Div>` .trim () const result = await bundlemdx ({ Источник: mdxsource, // Примечание: это * только * необходимо, если вы хотите поделиться DEP между MDX // пакет файлов и приложение хоста. В противном случае все DEPS будут просто связаны. // так это будет работать в любом случае, это просто оптимизация, чтобы избежать отправки // Несколько копий одной и той же библиотеки для ваших пользователей. Globals: {'Left-Pad': 'myleftpad'},})
// Сервер-Рендерированный и/или Код на стороне клиента, который может работать в браузере или узле: импорт * как реагировать из «react'import Lewpad от 'Left-pad'import {getmdxcomponent} от' mdx-bundler/client'function Mdxpage ({code}: {code: string}) { const component = React.usememo (() => getmdxcomponent (result.code, {myLeftPad: Leathpad}), [result.code, LewingPad], ) return (<main> <component /> < /main> )}
Установка cwd
( текущий рабочий каталог ) в каталог позволит ESBuild разрешить импорт. Этот каталог может быть каталогом, который был прочитал содержание MDX, или в каталоге, в котором должен быть запущен вне диска MDX.
Содержание/Страницы/ДЕМО.tsx
Импорт * как реагировать из 'React'function demo () { Вернуть <Div> аккуратная демонстрация! </div>} экспорт демо по умолчанию
src/build.ts
Import {bundlemdx} из 'mdx-bundler'const mdxsource = `--- Название: Пример после публикации: 2021-02-13description: Это некоторое описание ---# wahooimport demo от' * Демо: <demo /> `.trim() const result = await bundlemdx ({ Источник: mdxsource, CWD: '/users/you/site/_content/pages',}) const {code, frontmatter} = результат
Это позволяет настроить параметры серого материала.
Ваша функция выполняется текущая конфигурация серого материала для изменения. Верните свой модифицированный объект конфигурации для серого вещества.
bundlemdx ({ graymatteroptions: options => {options.excerpt = truereturn Options },})
Это позволяет вам установить выходной каталог для пакета и публичного URL в каталог. Если один вариант установлен, другой должен быть тоже.
Пакет JavaScript не записан в этот каталог и до сих пор возвращается как строка от bundleMDX
.
Эта функция лучше всего использовать с настройками mdxOptions
и esbuildOptions
. В примере ниже .png
файлы записываются на диск, а затем обслуживаются из /file/
.
Это позволяет вам хранить активы с MDX, а затем заставлять их обрабатывать их, как и все остальное.
Рекомендуется, чтобы каждый пакет имел свой собственный bundleDirectory
, чтобы несколько пучков не перезаписывали активы друг друга.
const {code} = await bundlemdx ({ Файл: '/path/to/site/content/file.mdx', CWD: '/path/to/site/content', bundledirectory: '/path/to/site/public/file', BundlePath: '/file/', mdxoptions: options => {options.remarkplugins = [armentmdximage] Параметры возврата }, esbuildoptions: options => {options.loader = {... options.loader, '.png': 'file',} параметры возврата },})
bundleMDX
возвращает обещание для объекта со следующими свойствами.
code
- пакет вашего MDX в качестве string
.
frontmatter
- object
переднего мельницы от серых веществ.
matter
- весь объект, возвращенный серым веществом
mdx-bundler
поставляет полные типики в своем собственном пакете.
bundleMDX
имеет параметр одного типа, который является типом вашего переднего мастера. По умолчанию по умолчанию {[key: string]: any}
и должен быть объектом. Затем это используется для ввода возвращаемой frontmatter
, и передняя мешка передается в esbuildOptions
и mdxOptions
.
const {FrontMatter} = bundlemdx <{title: string}>> ({source}) frontmatter.title // имеет тип строки
MDX Bundler проходит на способность MDX заменять компоненты через опору components
на компоненте, возвращаемого getMDXComponent
.
Вот пример, который удаляет теги P со всех изображений.
Import * AS React из 'React'Import {getMdxComponent} из' mdx-bundler/client'const paragraph: recact.fc = props => { if (typeof props.children! == 'string' && props.children.type === 'img') {return <> {props.children} </> } return <p {... props} />} function mdxpage ({code}: {code: string}) { const component = React.usememo (() => getmdxcomponent (code), [code]) return (<main> <component components = {{p: paragraph}} /> < /main> )}
Вы можете ссылаться на Meta или Consts в содержании MDX.
--- Название: Пример сообщения --- export const anvessimage = 'https://example.com/image.jpg'# {frontmatter.title} <img src = {exampleImage} alt = "Image Alt Text"/>
Вы можете использовать getMDXExport
вместо getMDXComponent
для обработки файла MDX как модуля вместо просто компонента. Требуется те же аргументы, что и getMDXComponent
.
--- Название: Пример поста --- export const toc = [{debult: 1, значение: 'title'}]# Название
Import * AS React From 'React'Import {getMdxexport} из' mdx-bundler/client'function mdxpage ({code}: {code: string}) { const mdxexport = getmdxexport (код) console.log (mdxexport.toc) // [{глубина: 1, значение: 'title'}] const component = React.usememo (() => mdxexport.default, [code]) return <component />}
С CWD и Plugin Plagin Plagin Rame-MDX-Images вы можете объединить изображения в своем MDX!
В Esbuild есть два погрузчика, которые можно использовать здесь. Самым простым является dataurl
, который выводит изображения в качестве встроенных URL -адресов данных в возвращенном коде.
Import {armentMdximage} от 'arment-mdx-imageS'const {code} = await bundlemdx ({{{{{{{{{{ Источник: mdxsource, CWD: '/users/you/site/_content/pages', mdxoptions: options => {options.remarkplugins = [... (options.remarkplugins ?? }, esbuildoptions: options => {options.loader = {... options.loader, '.png': 'datairl',} параметры возврата },})
Загрузчик file
требует немного больше конфигурации, чтобы получить работу. При загрузке file
ваши изображения копируются в выходной каталог, поэтому ESBUILD необходимо установить для записи файлов, и необходимо знать, где их поместить плюс URL -адрес папки, которая будет использоваться в источниках изображения.
Каждый вызов
bundleMDX
изолирован от других. Если вы установите каталог одинакового для всего,bundleMDX
будет перезаписать изображения без предупреждения. В результате каждый пакет нуждается в своем собственном выходном каталоге.
// для файла `_content/pages/ae.mdx`const {code} = await bundlemdx ({ Источник: mdxsource, CWD: '/users/you/site/_content/pages', mdxoptions: options => {options.remarkplugins = [... (options.remarkplugins ?? }, EsbuildOptions: Options => {// установить `utrewnir` в общедоступное место для этого bundle.options.outdir = '/users/you/site/public/img/about'options.loader = {... options.loaderer , // Скажите Esbuild использовать загрузчик файла для pngs '.png': 'file',} // Установить публичный путь в commg/aboutoptions.publicpath = '/img/about' // set witch на true true Таким образом, ESBUILD выведет файлы.options.write = },})
Если ваш файл MDX находится на вашем диске, вы можете сэкономить время и код, если mdx-bundler
прочитал файл для вас. Вместо того, чтобы поставлять source
строку, вы можете установить file
на путь MDX на диске. Установите cwd
в папку, чтобы относительный импорт работал.
Import {bundlemdx} от 'mdx-bundler'const {code, frontmatter} = waw bundlemdx ({ Файл: '/users/you/site/content/file.mdx', CWD: '/users/you/site/content/',})
Чтобы убедиться, что пользовательские компоненты доступны в нижестоящих файлах MDX, вы можете использовать MDXProvider
из @mdx-js/react
для передачи пользовательских компонентов в свой вложенный импорт.
npm install --save @mdx-js/react
const globals = { '@MDX-JS/React': {varName: 'mdxjsreact', natedExports: ['usemdxcomponents'], defaultexport: false, },}; const {code} = bundlemdx ({ источник, глобальные, mdxoptions (параметры: запись <string, any>) {return {... options, providerimportsource: '@mdx-js/react',}; }});
Оттуда вы отправляете code
своему клиенту, а затем:
Import {mdxprovider, usemdxcomponents} от '@mdx-js/react'; const mdx_global_config = { Mdxjsreact: {usemdxcomponents, },}; export const mdxcomponent: React.fc <{ Код: строка; FrontMatter: record <string, any>;}> = ({code}) => { const component = usememo (() => getmdxcomponent (code, mdx_global_config), [code], ); return (<mdxprovider components = {{{text: ({kids}) => <p> {дети} </p>}}> <component/> </mdxprovider> );};
Мы хотели бы , чтобы это работало у работников CloudFlare. К сожалению, у Cloudflares есть два ограничения, которые мешают mdx-bundler
работать в этой среде:
Рабочие не могут управлять двоичными файлами. bundleMDX
использует esbuild
(двоичный) для объединения вашего кода MDX.
Рабочие не могут управлять eval
или аналогичным. getMDXComponent
оценивает комплексный код, используя new Function
.
Одним из обходных путей является поместить ваш код, связанный с MDX-Bundler, в другую среду и назвать эту среду из работника CloudFlare. ИМО, это побеждает цель использования работников CloudFlare. Другой потенциальный обходной путь - использовать WASM изнутри работника. Есть esbuild-wasm
, но есть некоторые проблемы с этим пакетом, объясненным по этой ссылке. Тогда есть wasm-jseval
, но я не мог заставить его запустить код, который выводился из mdx-bundler
без ошибок.
Если кто -то хотел бы покопаться в этом, это было бы звездным, но, к сожалению, вряд ли я когда -либо поработаю над этим.
Esbuild полагается на __dirname
чтобы выяснить, где находится исполняемый файл, Next.js и Webpack иногда могут сломать это, и Esbuild нужно говорить вручную, где искать.
Добавление следующего кода до того, как ваш bundleMDX
будет указывать Esbuild непосредственно на правильный исполняемый файл для вашей платформы.
Путь импорта от 'path'if (process.platform ===' win32 ') { process.env.esbuild_binary_path = path.join (process.cwd (), 'node_modules', 'esbuild', 'esbuild.exe', )} еще { process.env.esbuild_binary_path = path.join (process.cwd (), 'node_modules', 'esbuild', 'bin', 'esbuild', )}
Более подробную информацию по этому вопросу можно найти в этой статье.
Когда я переписывал kentcdodds.com в ремикс, я решил, что хочу сохранить свои сообщения в блоге в качестве MDX, но я не хотел собирать их всех во время сборки или быть обязанными перераспределять каждый раз, когда я исправляю опечатку. Поэтому я сделал это, что позволяет моему серверу компилировать по требованию.
Там есть следующий-MDX-Remote, но это скорее MDX-компилятор, чем Bundler (не может объединить ваш MDX для зависимостей). Также он сосредоточен на следующем.js, в то время как это мета-обратная работа.
Хотите внести свой вклад? Ищите хороший лейбл первого выпуска.
Пожалуйста, подайте проблему для ошибок, отсутствующей документации или неожиданного поведения.
Смотрите ошибки
Пожалуйста, подайте проблему, чтобы предложить новые функции. Голосуйте по запросам функций, добавив? Это помогает сопровождающим расставить приоритеты, над чем работать.
Смотрите запросы функций
Спасибо этим людям (ключ эмодзи):
Кент С. Доддс ? | Бенвис ? ? | Адам Лейкок | Титус ? ? | Кристиан Мерфи ? | Педро Дуарте | Эрик Расмуссен |
Омар Сикс ? | Гаэль Хамеон | Габриэль Лояконе | Спенсер Мискик | Каспер | Апостолос Христодулу | Йордис Прието |
Xoumi | Ясин | Мухаммед 'Мо' Мулазада | Может Рау | Хосенес Рахаман | Макик Ситковски | Приян |
Мозаад | Stefanprobst | Влад Мороз |
Этот проект следует за спецификацией всех контролей. Взносы любого вида приветствуются!
Грань