Включение контента Markdown в Vue или Nuxt SPA

Разработчики любят хвастаться решением, которое они придумали для решения сложной проблемы (черт возьми, я делаю это прямо сейчас). По этой причине вы, вероятно, в какой-то момент своей карьеры создадите блог разработчика, чтобы продемонстрировать свои любимые приемы.

И как разработчик, вы, без сомнения, иррационально создадите свой блог с нуля, а не будете использовать готовое решение, потому что это именно то, что мы делаем!

Markdown — это действительно удобный формат для написания сообщений в блогах разработчиков, поскольку он позволяет легко включать блоки кода и другие виды форматирования без многословия при написании HTML.

Если вы собираетесь создать блог разработчика на основе уценки, одностраничное приложение Vue (или Nuxt) будет отличным выбором, как мы вскоре увидим.

Примечание: эта статья изначально была опубликована здесь, в блоге разработчиков Vue.js 01.01.2019.

Включая файлы уценки

Включение файлов уценки в Vue SPA на самом деле немного сложно. Самая большая проблема заключается в том, что каждый файл уценки должен быть «страницей» вашего SPA. Это означает, что Vue Router должен знать о них, но, поскольку они постоянно меняют контент, вы не хотите жестко кодировать их URL-адреса в коде приложения.

В оставшейся части статьи я буду описывать архитектуру приложения, которая имеет дело с этим.

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

Я рекомендую использовать «frontmatter» для ваших файлов уценки, при этом метаинформация добавляется как данные YAML в верхней части файла следующим образом:

---
title:  "..."
description: "..."
date: ...
---



Using markdown.

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

Подавайте файлы уценки

Убедитесь, что ваши файлы уценки находятся в каталоге, который обслуживается статически.

сервер.js

app.use(express.static(__dirname + '/articles'));


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

Создать файл манифеста

Теперь вы должны сгенерировать файл манифеста, содержащий URL-адрес каждой статьи и путь на сервере.

Во-первых, вам нужно определиться с заданной структурой URL для каждого поста, например /:year/:month/:day/:title. Убедитесь, что это получено из сообщения, добавив необходимые данные в вашу переднюю часть.

Теперь создайте исполняемый скрипт, который будет выполняться во время процесса сборки. Скрипт будет перебирать все ваши файлы уценки и генерировать список URL-адресов и путей к файлам в массиве JSON, который затем может использоваться Vue Router.

Вот некоторый псевдокод, чтобы вы могли увидеть, как он должен работать. Обратите внимание, что фронтматер может быть извлечен с помощью передний план Модуль НПМ.

generateManifest.js

const fs = require("fs");
const fm = require("front-matter");

fs.readdir("articles", files => {
  files.foreach(file => {
    fs.readFile(`articles/${file}`, data => {
      const { url } = fm(data);
      // Now you need to add the URL and file path to a file "/manifest.json"
    });
  });
});

В итоге у вас должен получиться такой файл JSON:

[
  { "url": "/2018/12/25/my-blog-post", "file": "/articles/my-blog-post.md" },
  { ... },
]

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

Динамические маршруты

Обязательно настройте Vue Router для включения динамического пути, соответствующего структуре URL-адреса вашей статьи. Этот маршрут загрузит компонент страницы, который на следующем шаге отобразит вашу уценку:

router.js

new VueRouter({
  routes: [
    { path: '/:year/:month/:day/:title', component: Article }
  ]
})

Как бы то ни было, этот динамический путь может соответствовать почти чему угодно. Как убедиться, что предоставленный URL действительно соответствует статье? Давайте возьмем манифест и, прежде чем мы попытаемся загрузить статью, убедитесь, что указанный URL-адрес есть в манифесте.

В созданном хуке вашего экземпляра Vue используйте AJAX и извлеките этот файл манифеста. Данные манифеста должны быть доступны любому компоненту, которому они нужны, поэтому вы можете добавить их в свою глобальную шину или хранилище Vuex, если вы их используете, или просто прикрепить их к прототипу Vue:

app.js

function createInstance() {
  new Vue(...);
}

axios.$http.get("/manifest.json")
  .then(file => {
    Vue.prototype.articles = JSON.parse(file);
    createInstance();
  });

Теперь, в вашем Article компонент, при вводе динамического маршрута подтвердите, находится ли он в URL-адресах, указанных в манифесте:

Предмет.просмотр

export default {
  beforeRouteEnter(to) {
    next(vm => {
      return vm.articles.find(article => article.url === to);
    });
  }  
}

Было бы неплохо вернуться к странице 404, если beforeRouteEnter возвращает ложь.

<контент-объявление/>

Загрузка уценки

Итак, теперь SPA распознает правильные URL-адреса, соответствующие вашему содержимому уценки. Теперь пришло время загрузить фактическое содержимое страницы.

Один из простых способов сделать это — использовать AJAX для загрузки контента и его разбора с помощью библиотеки типа «markdown-it». На выходе будет HTML, который можно добавить к элементу в вашем шаблоне с помощью v-html директива.

Предмет.просмотр

<template>
  <div v-html="content">
</template>
import md from "markdown-it";
export default {
  data: () => ({
    content: null
  }),
  beforeRouteEnter(to) {...},
  created() {
    const file = this.articles.find(article => article.url === this.$route.to).file;
    this.$http.get(file)
      .then({ data } => this.content = md(data));
  }
}

Рендеринг на стороне сервера

Большим недостатком этой архитектуры является то, что пользователю приходится ждать не одного, а двух вызовов AJAX, прежде чем просматривать статью. Фу.

Если вы собираетесь использовать этот подход, вы действительно должны использовать рендеринг или предварительный рендеринг на стороне сервера.

Самый простой способ, на мой взгляд, это использовать Nuxt. Вот как я сделал это с этим сайтом.

Кроме того, с помощью Nuxt asyncData метод упрощает загрузку в манифест, а с помощью verify метод каждого компонента страницы, вы можете сообщить приложению, существует ли статья или нет.

Кроме того, вы можете легко выполнить сценарий создания манифеста как часть процесса сборки Nuxt.

Бонус: вставка компонентов Vue в контент

Недостатком использования уценки для контента является то, что вы не можете включать динамический контент, т.е. в вашем уцененном контенте нет ничего похожего на «слоты».

Однако есть способ добиться этого!

Используя удивительный frontmatter-уценка-загрузчиквы можете заставить Webpack превратить ваши файлы уценки в функции рендеринга Vue во время процесса сборки.

Затем вы можете загрузить эти функции рендеринга, используя AJAX вместо файла уценки:

created() {
  const file = this.articles.find(article => article.url === this.$route.to).file;
  this.$http.get(file)
    .then({ data } => {
      this.templateRender = new Function(data.vue.render)();
      this.$options.staticRenderFns = new Function(this.content.vue.staticRenderFns)();
    });
}

Это означает, что вы можете включить компоненты Vue в уценку, и они будут работать! Например, в блоге разработчиков Vue.js я вставляю рекламу в статью, добавляя такой компонент:

# My article

Line 1

<advertisement-component/>

Line 2

Станьте старшим разработчиком Vue в 2020 году.

Изучите и освойте знания профессионалов о создании, тестировании и развертывании полнофункциональных приложений Vue в нашем последнем курсе.

Учить больше


Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *