MDX 파일과 종속성을 컴파일하고 번들로 묶습니다. 빠른.
사용하는 MDX 문자열 및 다양한 TS/JS 파일이 있으며 브라우저에서 평가할이 파일의 번들 버전을 가져 오려고합니다.
이것은 MDX 파일과 해당 종속성을 컴파일하고 번들로 제공하는 비동기 기능입니다. MDX V3 및 Esbuild를 사용하므로 매우 빠르며 TypeScript 파일 (MDX 파일의 종속성)을 지원합니다.
소스 파일은 원격 github 리포, CMS 또는 다른 곳에서 로컬 일 수 있으며 중요하지 않습니다. 모든 mdx-bundler
에 관심이있는 것은 필요한 모든 파일과 소스 코드를 전달하고 모든 것을 묶어야한다는 것입니다.
MDX를 사용하면 컨텐츠의 Terse Markdown 구문을 React 구성 요소의 힘과 결합 할 수 있습니다. 콘텐츠가 많은 사이트의 경우 똑바로 HTML로 콘텐츠를 작성하는 것이 성가신 장점이 될 수 있습니다. 종종 사람들은 WSYWIG 편집기를 사용하여 이것을 해결하지만 너무 종종 작가의 HTML의 의도를 매핑하는 데 부족합니다. 많은 사람들이 Markdown을 사용하여 컨텐츠 소스를 표현하고 HTML로 구문 분석하여 렌더링됩니다.
콘텐츠에 Markdown을 사용하는 데있어 문제는 컨텐츠에 상호 작용을 포함 시키려면 매우 제한적입니다. JavaScript 대상 (성가신 간접)의 요소를 삽입하거나 iframe
또는 무언가를 사용할 수 있습니다.
앞에서 언급했듯이 MDX를 사용하면 콘텐츠의 Terse Markdown 구문을 반응 구성 요소의 힘과 결합 할 수 있습니다. 따라서 React 구성 요소를 가져 와서 Markdown 자체 내에서 렌더링 할 수 있습니다. 두 세계 중 최고입니다.
next-mdx-remote
와 어떻게 다릅니 까?" mdx-bundler
실제로 MDX 파일의 종속성을 번들로 연결합니다. 예를 들어, 이것은 next-mdx-remote
에서는 작동하지 않지만 mdx-bundler
에서는 작동하지 않습니다.
--- 제목 : 예제 후 출판 : 2021-02-13description : 이것은 일부 설명입니다 ---# Wahooimport Demo From './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
에게 그 사실을 넘겨줍니다.
완전히. 이러한 도구 중 하나와 함께 작동합니다. 메타 프레임 워크가 서버 측 렌더링을 지원하는지 여부에 따라 다르게 구현할 수 있습니다. 구축 시간 접근 방식 (개츠비/CRA의 경우)을 사용하기로 결정할 수도 있지만, 언급했듯이 mdx-bundler
의 진정한 힘은 주문형 번들 형태로 제공됩니다. 따라서 Remix/Next와 같은 SSR 프레임 워크에 가장 적합합니다.
왜 안 돼?
Esbuild는 상호 작용하는 GO에 작성된 서비스를 제공합니다. 이 서비스의 하나의 인스턴스 만 한 번에 실행될 수 있으며 NPM 패키지와 동일한 버전이 있어야합니다. 어려운 종속성이라면 MDX-Bundler가 사용하는 Esbuild 버전 만 사용할 수 있습니다.
설치
용법
옵션
보고
유형
구성 요소 대체
프론트 터스와 콘서트
지명 된 수출에 액세스
이미지 번들링
파일 번들링.
다운 스트림 파일의 사용자 정의 구성 요소
알려진 문제
영감
다른 솔루션
문제
? 버그
기능 요청
기고자
특허
이 모듈은 NPM을 통해 분포되어 있으며 노드와 함께 번들로 제공되며 프로젝트의 dependencies
중 하나로 설치해야합니다.
npm install --save mdx-bundler esbuild
MDX-Bundler의 종속성 중 하나는 올바르게 설치할 수 있도록 작동 노드 곤란 설정이 필요합니다.
'mdx-bundler'const mdxsource =`--- 제목 : 제목 : 예제 후 게시 : 2021-02-13description : 2021-02-13description :# wahooimport 데모'./demo'here's a ** neat*에서 {bundlemdx} import * 데모 : <demo />` 출처 : mdxsource, 파일 : { './demo.tsx':`reture * report as as as a -reture as as a as a as a repport demo! </div>} 내보내기 기본 데모`, },}) const {code, frontmatter} = 결과
거기에서 code
클라이언트에게 보내고 다음과 같이합니다.
import * '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> </> )}
궁극적으로 이것은 (기본적으로) 렌더링됩니다.
<Header> <h1> 제목 </h1>입니다 <p> 이것은 설명 </p> </header> <main>입니다 <div> <h1> wahoo </h1> <p> <strong> neat </strong> 데모 : </p> <div> 깔끔한 데모! </div> </div> </main>
MDX의 string
소스.
file
이 설정된 경우 설정할 수 없습니다
MDX를 사용하여 디스크의 파일로가는 경로. CWD도 설정하고 싶을 것입니다.
source
설정된 경우 설정할 수 없습니다
files
구성은 번들링하는 모든 파일의 객체입니다. 키는 파일의 경로 (MDX 소스와 관련하여)이며 값은 파일 소스 코드의 문자열입니다. 파일 시스템이나 원격 데이터베이스에서이를 가져올 수 있습니다. MDX가 다른 파일을 참조하지 않거나 node_modules
에서 물건을 가져 오는 경우 전적으로 생략 할 수 있습니다.
이를 통해 내장 MDX 구성 ( @mdx-js/esbuild
로 전달됨)을 수정할 수 있습니다. 이는 자신의 warickplugins/rehypeplugins를 지정하는 데 도움이 될 수 있습니다.
함수는 기본 MDXOPTIONS 및 프론트 매트가 전달됩니다.
bundlemdx ({ 출처 : mdxsource, mdxoptions (옵션, 프론트 매스터) {// 이것은 사용자 정의 설명/rehype 플러그인을 추가하는 권장 방법입니다. // 구문은 이상하게 보일 수 있지만 미래에 // 플러그인을 추가/제거 할 경우를 보호합니다. = [... (Options.RemarkPlugins ?? []), MyRemarkPlugin] 옵션. rehypeplugins = [... },})
옵션 esbuildOptions
로 Esbuild 옵션을 사용자 정의 할 수 있습니다. 이것은 기본 Esbuild 옵션과 프론트 마터를 전달하는 함수를 사용하며 옵션 개체가 반환 될 것으로 기대합니다.
bundlemdx ({ 출처 : mdxsource, esbuildoptions (옵션, 프론트 매스터) {옵션 .minify = falseoptions.target = [ 'es2020', 'chrome58', 'firefox57', 'safari11', 'edod16', '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
예는 다음과 같습니다.
// 노드에서 실행되는 서버 측 또는 빌드 타임 코드 : 'mdx-bundler'const mdxsource에서 {bundlemdx} 가져 오기 {bundlemdx}`#'왼쪽 '<div>의 Titleimport LeftPad입니다 (leftpad (”Neat Demo ! ", 12, '!')} </div>`.trim () const result = bundlemdx ({{ 출처 : mdxsource, // 참고 : 이것은 MDX간에 DEP를 공유하려는 경우에만 * 필요합니다. // 파일 번들 및 호스트 앱. 그렇지 않으면 모든 DEP가 번들로 연결됩니다. // 어느 쪽이든 작동합니다. 이것은 전송을 피하는 최적화 일뿐입니다. // 사용자에게 동일한 라이브러리의 여러 사본. 글로벌 : { '왼쪽 패드': 'myleftpad'},})
// 브라우저 또는 노드에서 실행할 수있는 서버-렌더링 및/또는 클라이언트 측 코드 : 'mdx-bundler/client'function에서'left-pad'import {getmdxcomponent}에서 'react'import leftpad에서'react'import leftpad에서 react로 가져 오기 * mdxpage ({code} : {code : string}) { const component = react.usememo (() => getMdxComponent (result.code, {myleftPad : leftPad}), [result.code, leftPad], )) return (<main> <component /> < /main> )}
cwd
( 현재 작업 디렉토리 )를 디렉토리로 설정하면 Esbuild가 가져 오기를 해결할 수 있습니다. 이 디렉토리는 MDX 컨텐츠에서 읽은 디렉토리 또는 오프 디스크 MDX를 실행 해야하는 디렉토리 일 수 있습니다.
내용/페이지/demo.tsx
import * 'react'Function Demo () {에서 반응하여 <div> 깔끔한 데모를 반환하십시오! </div>} 내보내기 기본 데모
src/build.ts
'mdx-bundler'const mdxsource =`--- 제목 : 제목 : 예제 후 게시 : 2021-02-13description : 2021-02-13description :## wahooimport 데모'./demo'here's a ** neat*에서 {bundlemdx} import * 데모 : <demo />` 출처 : mdxsource, cwd : '/user/you/site/_content/pages',}) const {code, frontmatter} = result
이를 통해 회색 단체 옵션을 구성 할 수 있습니다.
귀하의 기능은 수정할 수있는 현재 회색 매체 구성이 전달됩니다. 수정 된 구성 객체를 회색 물질에 반환하십시오.
bundlemdx ({ graymatteroptions : 옵션 => {옵션 .excerpt = truereturn 옵션 },})
이를 통해 번들의 출력 디렉토리와 공개 URL을 디렉토리로 설정할 수 있습니다. 한 옵션이 설정되면 다른 옵션도 마찬가지입니다.
JavaScript 번들은이 디렉토리에 기록되지 않았으며 여전히 bundleMDX
에서 문자열로 반환됩니다.
이 기능은 mdxOptions
및 esbuildOptions
에 대한 조정과 함께 사용되는 것이 가장 좋습니다. 아래의 예에서 .png
파일은 디스크에 기록 된 다음 /file/
에서 제공됩니다.
이를 통해 MDX에 자산을 저장 한 다음 다른 것과 마찬가지로 Esbuild 프로세스를 처리 할 수 있습니다.
각 번들에는 자체 bundleDirectory
있어 여러 번들이 서로 자산을 덮어 쓰지 않도록 권장됩니다.
const {code} = bundlemdx를 기다립니다 ({ 파일 : '/path/to/site/content/file.mdx', CWD : '/path/to/site/content', Bundledirectory : '/path/to/site/public/file', Bundlath : '/file/', MDXOPTIONS : 옵션 => {옵션 .remarkPlugins = [warchmdxImages] 반환 옵션 }, esbuildoptions : 옵션 => {옵션.loader = {... Options.Loader, '.png': 'file',} 반환 옵션 },})
bundleMDX
다음 속성을 가진 객체에 대한 약속을 반환합니다.
code
- string
로서 MDX의 번들.
frontmatter
회색의 전면 object
.
matter
- 회색 단체에 의해 반환 된 전체 물체
mdx-bundler
자체 패키지 내의 완전한 타이핑을 공급합니다.
bundleMDX
에는 단일 유형 매개 변수가 있으며 이는 프론트 마터의 유형입니다. 기본적으로 {[key: string]: any}
로 기본적으로 객체 여야합니다. 그런 다음 반환 된 frontmatter
입력하는 데 사용되며 프론트 마터는 esbuildOptions
및 mdxOptions
로 전달되었습니다.
const {frontmatter} = bundlemdx <{title : string}> ({source}) frontmatter.title // 유형 문자열이 있습니다
MDX Bundler는 getMDXComponent
가 반환 한 구성 요소의 components
소품을 통해 구성 요소를 대체 할 수있는 MDX의 능력을 전달합니다.
다음은 이미지 주변에서 P 태그를 제거하는 예입니다.
가져 오기 * 'MDX-BUNDLER/CLIENT'CONST 단락에서'react'import {getMdxComponent}에서 REACT : React.fc = propss => { if (props.children! == 'string'&& props.children.type === 'img') {return <> {propss.children} </> } return <p {... props} />} 함수 mdxpage ({code} : {code : string}) { const component = react.usememo (() => getmdxcomponent (code), [code]) return (<main> <component components = {{p : paragraph}} /> < /main> )}
MDX 컨텐츠에서 FrontMatter Meta 또는 Const를 참조 할 수 있습니다.
--- 제목 : 예제 포스트 --- 내보내기 const exmainImage = 'https://example.com/image.jpg'# {frontmatter.title} <img src = {exampleImage} alt = "image alt text"/>
getMDXComponent
대신 getMDXExport
사용하여 MDX 파일을 구성 요소 대신 모듈로 처리 할 수 있습니다. getMDXComponent
와 동일한 주장이 필요합니다.
--- 제목 : 예제 게시 --- 내보내기 const toc = [{깊이 : 1, 값 : '제목'}]# 제목
import * 'react'import {getmdxexport}에서'mdx-bundler/client'function mdxpage ({code} : {code : string}) { const mdxexport = getmdxexport (코드) console.log (mdxexport.toc) // [{깊이 : 1, 값 : '제목'}] const component = react.usememo (() => mdxexport.default, [code]) return <component />}
CWD 및 비고 플러그인 비고 MDX- 이미지를 사용하면 MDX에서 이미지를 번들로 묶을 수 있습니다!
Esbuild에는 여기에 사용할 수있는 두 개의 로더가 있습니다. 가장 쉬운 것은 dataurl
이며, 반환 된 코드에서 이미지를 인라인 데이터 URL로 출력합니다.
'warch-mdx-images'const {code} = import {warticmdximages}} = bundlemdx ({{ 출처 : mdxsource, CWD : '/user/you/site/_content/pages', mdxOptions : 옵션 => {옵션 .remarkPlugins = [... (옵션 .remarkPlugins? }, esbuildoptions : 옵션 => {옵션.loader = {... Options.Loader, '.png': 'dataUrl',} 반환 옵션 },})
file
로더는 작동하는 데 약간 더 구성이 필요합니다. file
로더를 사용하면 이미지가 출력 디렉토리에 복사되므로 Esbuild는 파일을 작성하도록 설정해야하며 이미지 소스에서 사용할 폴더의 URL을 넣을 위치를 알아야합니다.
bundleMDX
에 대한 각 호출은 다른 사람과 격리됩니다.bundleMDX
경고없이 이미지를 덮어 쓰는 모든 것에 대해 디렉토리를 동일하게 설정하면. 결과적으로 각 번들에는 자체 출력 디렉토리가 필요합니다.
// 파일의 경우`_content/pages/about.mdx`const {code} = bundlemdx ({ 출처 : mdxsource, CWD : '/user/you/site/_content/pages', mdxOptions : 옵션 => {옵션 .remarkPlugins = [... (옵션 .remarkPlugins? }, esbuildoptions : 옵션 => {//``outdir '를 공용 위치로 설정하십시오. aptions.outdir ='/users/you/site/public/img/about'options.loader = {... Options.Loader , // esbuild에 pngs 용`file 'loader'.png ':'file ',} // 공개 경로를 /img/aboutoptions.publicpath ='/img/about '// true에 set write set write to'file ',} // esbuild가 files.options.write = truereturn 옵션을 출력합니다. },})
MDX 파일이 디스크에 있으면 mdx-bundler
파일을 읽게하여 시간과 코드를 절약 할 수 있습니다. source
문자열을 공급하는 대신 디스크에서 MDX의 경로로 file
설정할 수 있습니다. 상대적 수입이 작동하도록 cwd
폴더로 설정하십시오.
'mdx-bundler'const {code, frontmatter}에서 {bundlemdx} import {bundlemdx}} = bundlemdx ({{ 파일 : '/users/you/site/content/file.mdx', CWD : '/user/you/site/content/',})
다운 스트림 MDX 파일에서 사용자 정의 구성 요소에 액세스 할 수 있도록 @mdx-js/react
의 MDXProvider
사용하여 사용자 지정 구성 요소를 중첩 된 가져 오기에 전달할 수 있습니다.
npm install --save @mdx-js/react
const globals = { '@mdx-js/react': {varname : 'mdxjsReact', namexports : [ 'usemdxcomponents'], defaultexport : false, },}; const {code} = bundlemdx ({ 원천, 글로벌, mdxOptions (옵션 : record <string, any>) {return {... 옵션, 제공자 importSource : '@mdx-js/react',}; }});
거기에서 code
클라이언트에게 보내고 다음과 같이합니다.
import {mdxprovider, usemdxcomponents}에서 '@mdx-js/react'; const mdx_global_config = { mdxjsReact : {usemdxcomponents, },}; 내보내기 const mdxcomponent : react.fc <{ 코드 : 문자열; FrontMatter : record <string, any>;}> = ({code}) => { const component = usememo (() => getmdxcomponent (code, mdx_global_config), [Code], ); return (<mdxprovider 구성 요소 = {{텍스트 : ({children}) => <p> {children} </p>}}> <구성 요소/</mdxProvider> );};
우리는 이것이 CloudFlare Workers에서 일하기를 원합니다 . 불행히도 CloudFlares는 mdx-bundler
해당 환경에서 작동하지 못하게하는 두 가지 제한 사항이 있습니다.
노동자들은 바이너리를 운영 할 수 없습니다. bundleMDX
esbuild
(이진)를 사용하여 MDX 코드를 번들로 묶습니다.
근로자는 eval
또는 이와 유사하게 달릴 수 없습니다. getMDXComponent
new Function
사용하여 번들 코드를 평가합니다.
이에 대한 한 가지 해결 방법은 MDX-Bundler 관련 코드를 다른 환경에 넣고 CloudFlare 작업자 내에서 해당 환경을 호출하는 것입니다. IMO, 이것은 CloudFlare Workers를 사용하는 목적을 물리칩니다. 또 다른 잠재적 인 해결 방법은 근로자 내에서 WASM을 사용하는 것입니다. esbuild-wasm
이 있지만 해당 링크에 설명 된이 패키지에는 몇 가지 문제가 있습니다. 그런 다음 wasm-jseval
이 있지만 mdx-bundler
에서 오류없이 출력 한 코드를 실행할 수 없었습니다.
누군가가 이것에 대해 파고 들기를 원한다면, 그것은 훌륭한 일 것이지만 불행히도 나는 그 일을 할 것 같지 않습니다.
Esbuild는 __dirname
에 의존하여 실행 파일이 어디에 있는지 알아냅니다. 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을 Remix로 다시 작성하면서 블로그 게시물을 MDX로 유지하기로 결정했지만 오타를 수정할 때마다 빌드 시간에 모두 컴파일하거나 재배치해야 할 필요가 없었습니다. 그래서 나는 이것을 만들어 내 서버가 주문형으로 컴파일 할 수있게했다.
다음 MDX- 리모트가 있지만 Bundler보다 MDX 컴파일러가 더 많습니다 (종속성을 위해 MDX를 묶을 수 없습니다). 또한 Next.js에 중점을 두는 반면, 이것은 메타 프레임 워크의 비수성입니다.
기여를 원하십니까? 좋은 첫 번째 이슈 레이블을 찾으십시오.
버그, 누락 된 문서 또는 예기치 않은 동작에 대한 문제를 제출하십시오.
버그를 참조하십시오
새로운 기능을 제안하려면 문제를 제기하십시오. A?를 추가하여 기능 요청에 투표하십시오. 이를 통해 유지 관리자는 작업해야 할 사항을 우선시하는 데 도움이됩니다.
기능 요청을 참조하십시오
이 사람들에게 감사합니다 (이모티콘 키) :
켄트 C. Dodds ? | 벤위스 ? ? | Adam Laycock | 티투스 ? ? | 기독교 머피 ? | 페드로 듀 아르테 | 에릭 라스무센 |
오마르 시스 ? | Gaël Haméon | 가브리엘 로이 아코 노 | 스펜서 미스 코비아 크 | 캐스퍼 | Apostolos Christodoulou | Yordis Prieto |
xoumi | 야신 | 모하메드 'Mo'Mulazada | Rau 할 수 있습니다 | Hosenur Rahaman | Maciek Sitkowski | 프리병 |
모자 드 | StefanProbst | 블라드 모 로즈 |
이 프로젝트는 All-Contritors 사양을 따릅니다. 모든 종류의 공헌을 환영합니다!
MIT