markdownit-module icon indicating copy to clipboard operation
markdownit-module copied to clipboard

Exclude markdownIt from vendor

Open rbwilcoxon11 opened this issue 7 years ago • 6 comments

What problem does this feature solve?

Currently, I have a huge bundle size because prism.js is included in my vendor build. I want to avoid the Mb cost...

What does the proposed changes look like?

Essentially, the markdownit component needs to be available to the asyncData instance directly. I was thinking I could just use require in asnycdata—not sure if this will actually work—but if it were an option in the module that would be a lot easier. Some ways to do that are discussed in the nextjs blog post. https://arunoda.me/blog/ssr-and-server-only-modules

I tried the second option but couldn't get it working... maybe someone had success with another one of the options?

This feature request is available on Nuxt.js community (#c125)

rbwilcoxon11 avatar May 06 '18 16:05 rbwilcoxon11

I'd like to second this. I'm trying to find a way to use markdown-it to preprocess my pages on generate.

DitheringIdiot avatar Jan 16 '20 16:01 DitheringIdiot

I believe you can prevent markdown from injecting it's self into your pages:

// nuxt.config.js
  markdownit: {
    injected: false
  },

I use this on my blog and there is no markdownit or prismjs code in my vendor file.

nerdoza avatar Jan 16 '20 17:01 nerdoza

I just gave that a go and it does remove it from the vendor. But it also breaks my app because of when I'm parsing the markdown.

I get the markdown in asyncData then have this in my template:

<post-to-render :content="$md.render(post.body)" />

I just followed the Netlify CMS Nuxt Tutorial. But figured there must be a better way of doing it.

I'd really appreciate it if you could share how you preprocessed your markdown.

DitheringIdiot avatar Jan 16 '20 17:01 DitheringIdiot

It's been a over a year since I wrote this code so it took me a bit to remember where it was all hiding. It turns out that I do still have to include markdownit and prismjs in the page level code, but not in the top level vendor code. I used Contentful as the CMS, so it's probably fairly similar in implementation to Netlify CMS.

<!-- _slug.vue -->
<template>
  <section class="blog-post">
    <p class="back-link">
      <nuxt-link to="/blog/">Back to Latest Blog Posts</nuxt-link>
      <a :href="'/blog/amp/' + post.slug + '/'">To AMP Version⚡</a>
    </p>

    <article>
      <div v-if="post.bannerImg" class="banner">
        <img :src="post.bannerImg.src" :alt="post.bannerImg.alt" :height="post.bannerImg.height" :width="post.bannerImg.width">
      </div>

      <h1>{{ post.title }}</h1>

      <div class="meta">
        <time :datetime="post.publishedAt">Published on {{ post.publishedAt | formatDate }}</time>
      </div>

      <div class="content" v-html="mdRender(post.content)"></div>
    </article>
  </section>
</template>

<script src="~/mixins/slug/slug.js"></script>
<style lang="scss">
@import "~/mixins/slug/slug.scss";
</style>
// slug.scss
@import "~/node_modules/prismjs/themes/prism-tomorrow.css";

.blog-post {
  .content {
    pre {
      margin-bottom: 1.4rem;
    }

    p code {
      color: $color-white;
      background-color: $color-bg-secondary;
      padding: .25rem .5rem;
      border-radius: .4rem;
    }

    pre {
      background-color: $color-bg-secondary;
      padding: 2rem;

      code {
        white-space: pre-wrap;
      }
      @include for-phone-only {
        padding: .5rem;
        overflow-x: scroll;

        code {
          white-space: pre;
        }
      }
    }
  }
 }
// slug.js
import MarkdownIt from 'markdown-it'
import MDPrism from 'markdown-it-prism'
import stripMd from '~/mixins/stripMd'
import { formatDate } from '~/mixins/filters'
import contentfulClient from '~/plugins/contentful'

const md = new MarkdownIt()
md.use(MDPrism)

const processPost = (post) => {
  return {
    post: {
      title: post.fields.title,
      slug: post.fields.slug,
      publishedAt: post.sys.createdAt,
      updatedAt: post.sys.updatedAt,
      description: post.fields.description,
      content: post.fields.content,
      bannerImg: post.fields.banner ? {
        src: 'https:' + post.fields.banner.fields.file.url,
        alt: post.fields.banner.fields.description,
        height: post.fields.banner.fields.file.details.image.height,
        width: post.fields.banner.fields.file.details.image.width
      } : null
    }
  }
}

export default {
  head () {
    const rawContent = stripMd(this.post.content)

    return {
      title: this.post.title,
      meta: [
        { hid: 'description', name: 'description', content: this.post.description }
      ],
      link: [
        { rel: 'canonical', href: `/blog/${this.post.slug}/` },
        { rel: 'amphtml', href: `/blog/amp/${this.post.slug}/` }
      ],
      script: [ ],
      __dangerouslyDisableSanitizers: ['script']
    }
  },
  filters: { formatDate },
  asyncData ({ params, error, payload }) {
    if (payload) return processPost(payload)

    return contentfulClient
      .getEntries({
        content_type: 'blogPost',
        'fields.slug': params.slug,
      })
      .then(entries => {
        if (entries.items.length == 0) {
          throw new Error('article not found')
        }
        return processPost(entries.items[0])
      })
      .catch(e => { error({ statusCode: 404, message: e.message }) })
  },
  methods: {
    mdRender (content) {
      if (!content) return ''
      return md.render(content)
    }
  }
}

nerdoza avatar Jan 16 '20 18:01 nerdoza

I tried your solution but the markdown-it module stay in vendor app when i run webpack analyse

ghost avatar Feb 03 '20 11:02 ghost

Is there still no simple solution out there to render markdown on build? It seems silly to include this package when using static site generation.

madsh93 avatar Dec 12 '21 13:12 madsh93