Как загрузить файл .md при сборке при использовании приложения create-реагировать и Typescript?

Я пытаюсь загрузить файл уценки для загрузки при сборке. Я настроил приложение create-реагировать, которое использует Typescript и использует тему блога material_ui.

import ReactMarkdown from 'markdown-to-jsx';
import post1 from './blog-post.1.md';

export default function Main(props: MainProps) {
  const classes = useStyles();
  const { posts, title } = props;

  return (
    <Grid item xs = {12} md = {8}>
      <Typography variant = "h6" gutterBottom>
        {title}
      </Typography>
      <Divider />
      {posts.map((post) => (
        <Markdown className = {classes.markdown} key = {post.substring(0, 40)}>
          {post}
        </Markdown>
      ))}
    </Grid>
  );
}

Если запись назначена для уценки, она будет отображаться правильно: const post = '# Sample blog post #### April 1, 2020 by [Olivier](/)'

Итак, проблема в том, что файл .md не загружается в переменную.

При запуске npm start отображается html: /static/media/blog-post.1.09e7833f.md Почему это так и что это за номер: 09e7833f в пути к файлу?

В идеале я хотел бы загрузить файл во время сборки, чтобы его можно было быстрее обслуживать где-то вроде Netlify. Я не хочу использовать асинхронную выборку, как этот ответ предлагает.

Я предполагаю, что мне придется создать загрузчик веб-пакетов? Проблема в том, что приложение create-react-app имеет webpack.config.js в node_modules, что означает, что его настройка будет перезаписана во время новой сборки. Я не думаю, что использование raw-loader поможет, если я не могу его настроить.

Я также пробовал import post1 from 'raw-loader!./blog-post.1.md';, как было предложено здесь, но Typescript не знает, что с этим делать.

Любые предложения будут полезны.

🤔 А знаете ли вы, что...
React Testing Library - это инструмент для тестирования компонентов React.


7
6 636
2

Ответы:

Решено

Кажется, об этом уже спрашивали ранее (https://github.com/facebook/create-react-app/issues/3025), но, к сожалению, сейчас не представляется возможным напрямую импортировать уценку как строка в JavaScript/TypeScript.

При запросе create-react-app импортировать файл md кажется, что он получает URL-адрес (с шестнадцатеричной строкой) файла вместо необработанной строки, содержащейся внутри. Обходной путь выглядит следующим образом:

  1. Создайте файл .d.ts, чтобы указать TypeScript, как интерпретировать файл md:
declare module '*.md' {
  const value: string; // markdown is just a string
  export default value;
}
  1. Импортируйте файл md (the_text.md) следующим образом.
import theTextFile from './the_text.md';
  1. fetch содержимое файла для получения актуальной уценки (https://github.com/facebook/create-react-app/issues/2961#issuecomment-322916352)
const [postMarkdown, setPostMarkdown] = useState('');

// useEffect with an empty dependency array (`[]`) runs only once
useEffect(() => {
  fetch(theTextFile)
    .then((response) => response.text())
    .then((text) => {
      // Logs a string of Markdown content.
      // Now you could use e.g. <rexxars/react-markdown> to render it.
      // console.info(text);
      setPostMarkdown(text);
    });
}, []);
  1. Поместите текст уценки в тег Markdown, и он будет отображаться:
<Markdown className = {classes.markdown}>
  {post}
</Markdown>

Имейте в виду, что вы также можете переопределить элементы JSX, используемые для отображения окончательного результата. Для Material-UI это может выглядеть примерно так:

import { Typography } from '@material-ui/core';
import { MarkdownToJSX } from 'markdown-to-jsx';

const Foo = (): JSX.Element => {

  const MdOverrideTypography = ({
    children,
  }: // ...props
  React.DetailedHTMLProps<
    React.HTMLAttributes<HTMLParagraphElement>,
    HTMLParagraphElement
  >): JSX.Element => (
    <Typography paragraph>
      {children}
    </Typography>
  );

  const mdOverrides: MarkdownToJSX.Overrides = {
    // "p" paragraph elements are substituted with MUI "Typography"
    p: MdOverrideTypography,
  };

  // ...

  return (
    <Markdown options = {{ overrides: mdOverrides }}>
      {post}
    </Markdown>
  )
}

(https://www.npmjs.com/package/markdown-to-jsx#optionsoverrides---rendering-arbitrary-react-components)


Простым способом кажется использование пакета raw.macro (цитирую начало его README):

Монтаж

Чтобы использовать raw.macro в своем проекте, вы можете использовать один из следующие команды:

# or $ npm install --save-dev raw.macro

Убедитесь, что макросы babel-plugin уже установлены. Если вы используете Создайте приложение React, оно установлено по умолчанию.

Применение

raw.macro похож на вызов require в Node:

import raw from "raw.macro";

const markdown = raw("./README.md");

TypeScript видит переменную markdown как тип string.

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