Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discussion] Roadmap #198

Closed
ulivz opened this issue Apr 21, 2018 · 24 comments
Closed

[Discussion] Roadmap #198

ulivz opened this issue Apr 21, 2018 · 24 comments
Labels
type: question or discussion Question or discussion

Comments

@ulivz
Copy link
Member

ulivz commented Apr 21, 2018

Hey guys, about the next direction or planning of VuePress, specially set up a "channel" to discuss here.

Above all, we need to make clear that the original intention of VuePress is to write documents to Vue and its sub projects. As mentioned in the document, VuePress is composed of two parts:

  1. A static site generator
  2. A vue-styled default theme

If we leave everything to the default theme, then when you decide to develop a new theme, you would repeat many things. so for some of our new features, we should consider whether it is handled in 1 or 2.

In fact, I expect to complete the development of the core functionality as soon as possible, Only core is STABLE can we focus on migrating the documents and blog theme development (Maybe need to create a separate repo called vuepress-theme-blog). Of course, the premise is that we have prepared useful enough data and APIs for the beginning of the custom theme.

At present, the core function I think is probably only Algolia DocSearch Integration. If you think there are other deserved suitable core needs, feel free to tell us here.

Regards,
Thanks.

Radmap

  • 0.8.0
    • Algolia DocSearch Integration.
@ulivz ulivz added the type: question or discussion Question or discussion label Apr 21, 2018
@dgpgdev
Copy link

dgpgdev commented Apr 21, 2018

nice to centralize info :) .

I'll just finish to create a vue cli plugin for vuepress maybe add that inside project features. https://github.com/dgpgdev/vue-cli-plugin-vuepress

@dgpgdev
Copy link

dgpgdev commented Apr 22, 2018

Before work algolia docsearch maybe merge pullrequest validated. I don't think blog are useless... vuepress is perfect for documentation.

@yyx990803
Copy link
Member

One extra thing we need to finalize in core: API for custom themes to write additional files during build.

@mdaffin
Copy link
Contributor

mdaffin commented Apr 22, 2018

so for some of our new features, we should consider whether it is handled in 1 or 2.

Or we can implement things in a theme, then once they are proven or popular look to migrating them into the core. As long as the core is flexible enough for themes to do this extra useful common features can be backported into the core so that more themes can take advantage of them.

For these, we need a way for themes to write additional files like @yyx990803 suggests. I have attempted to introduce this in #196 but we should probably take about the implementations details a bit more. In short, it loads themeDir/index.js and .vuepress/index.js and expects them to export a function that takes {options} as an argument. This function runs in the context of the server as part of the prepare method so has access to write files to the outDir and otherwise manipulate the set options before the site is generated (allowing injection of extra headers or other things).

One thing it does not expose is a way to hint to the build about extra routes that should be generated (such as routes added in enchanceApp.js like in #143)

@ulivz
Copy link
Member Author

ulivz commented Apr 23, 2018

@mdaffin @dacsang97 Thanks for your two guys' contribution for the plugin support (#196 & #216). Let me summarize for that here.

1. Figure out the reponsibility of plugin.

Obviously, VuePress core's prepare process is only to do some pre-build work for the default theme. When user need to extend some data or do some specific generate work before building, plugins come in handy. So we should consider what can be changed by the developer of the plugin.

So the options should not be exposed directly, especially such values that are not allowed to be modified, such as sourceDir, outDir, plugin system shouldn't let plugins to have permissions to modify them. So it would be better to create a shallow-cloned options to expose:

interface exposedOptions {
	sourceDir: string;  // readable
	outDir: string; // readable
	publicPath: string; // readable
	markdown: Object; // readable
	themePath: string; // readable, theme component entry
	useDefaultTheme: boolean; // readable
	notFoundPath: string;     // readable,404 component entry
	
	siteConfig: Object;    
	pageFiles: string[]; // A list containing relative paths of source makrdown files
	siteData: Object;     
}

interface Page {
	path: string;
	title: string;
	headers: Array<{ level: number, title: string, slug: string }>;
	frontmatter: { [key: string]: string };
}

interface siteData {
	title: string,
	description: string,
	base: string,
	pages: Page
}

2. Determine the timing of the plugin's execution.

At the moment, I found out that both of yours put the excution timing at the end of prepare. I agree that at least we can ensure that the core is stable enough. and @yyx990803 what do you think about this?


3. Deciding on the plugin's API.

Obviously, I think everyone supports pure function API, However, at this stage we have two options:

  1. First-order function

The extra pluginOptions was mixed into the exposed options object.

module.exports = ({siteConfig, siteData, pageFiles, pluginOptions}) => {}
  1. High-order function

Also from @dacsang97:

module.exports = (pluginOptions) => ({siteConfig, siteData, pageFiles}) => {}

Let's vote:


It is worth mentioned that the plugin should support the async function and return Promise.


4. Deciding on the usage of plugins

User can add extra plugins via plugins field at docs/.vuepress/config.js, there are 4 optional types of usage:

  1. Function in Array
module.exports = {
    plugins: [
        require('./rssPlugin.js')   
    ]
}
  1. String in Array
module.exports = {
    plugins: [
        'pluginName', // will to load 'vuepress-plugin-${pluginName}'
        'vuepress-plugin-rss', // also support full name
    ]
}
  1. Array in Array (Babel Style)

This configuration style comes from babel:

module.exports = {
    plugins: [
        [
          'rss',
          {
              option1: '1',
              option2: '2'
              // ...
          }
        ]
    ]
}
  1. Object in Array

This configuration style comes from @dacsang97:

module.exports = {
    plugins: {
        resolve: 'rss', // resolve => 'name' ?
        options: {
            option1: '1',
            option2: '2'
        }
    }
}

I think that the first two style are sure to support. so we need to make choices in the latter two:


Thank you for all of your guys' participation!

@dacsang97
Copy link

dacsang97 commented Apr 23, 2018

I had implemented to run Function and AsyncFunction
https://github.com/dacsang97/vuepress/blob/673cc2e44d6f1694d21ef855aaadc2b73de7e5eb/lib/prepare.js#L79L82
Do you think we should support Generator Function ?

@ulivz
Copy link
Member Author

ulivz commented Apr 23, 2018

@dacsang97 I have seen your change, cool, butGenerator Function is unnecessary. maybe you can add support for return Promise.

@mdaffin
Copy link
Contributor

mdaffin commented Apr 23, 2018

  1. Figure out the responsibility of plugin.

I agree on the options side, my pull request was just an experiment to figure out what would be required. Your object looks reasonable but I think it might be worth adding a routes: [] section to allow plugins to hint to the ssr additional routes that it should attempt to render that don't have corresponding markdown files (ie more dynamic components added by the theme). This might want to live inside siteData though.

It is also worth adding a base URL to siteData as a number of plugins require this value (RSS feeds, sitemaps etc) and being able to inject this at build time is also worthwhile (for example for changing it during netlifys preview deploys).

  1. Deciding on the plugin's API.

I vote for 1. First-order function as it looks cleaner to plugin developers and it is only ever going to be a run once function.

  1. Deciding on the usage of plugins

I prefer the Object in Array like the way Nuxt does it:

module.exports = {
  plugins: [
    { src: '~/plugins/vue-notifications', ssr: false }
  ]
}

Keeping things similar to Nuxt is a good way to go as I suspect there will be a crossover of the user base here.

@mdaffin
Copy link
Contributor

mdaffin commented Apr 23, 2018

Also, what about theme/site plugins? ie ones that are baked into a theme or site like in my original implementation. I think we can get rid of the site ones as that is covered by the plugins array in the config, but there should be a way for themes to add to the list of plugins, maybe a config.js inside the theme? Or just treat the theme as a plugin (as my implementation does)?

@dgpgdev
Copy link

dgpgdev commented Apr 23, 2018

i agree with @ulivz, if anyone can write a plugin we need to secure input data.
i agree too with @mdaffin to expose plugin as nuxt way.

@dgpgdev
Copy link

dgpgdev commented Apr 23, 2018

i love how vue cli use plugin maybe can we use same for vuepress to install and manage plugin .

@dgpgdev
Copy link

dgpgdev commented Apr 23, 2018

i agree, but often we need same configuration (rssfeed, sitemap...) (vue cli presets) for many project. yarn add vuepress-plugin-<plugin> is correct too. I try to think of what is simpler to use.

@mdaffin
Copy link
Contributor

mdaffin commented Apr 23, 2018

@dgpgdev all dependencies of a project should be inside the package.json for that project and there should be no side effects from globally installed packages (or you end up wot the 'It works for me' problem).

If you want to use the same plugins/base structure for many projects you should use vue cli to create a template for vuepress with all your plugins and desired config in the template. Vuepress does not need to know or understand vue cli at all and yarn/npm are the tools you should be using for managing project level dependencies.

@ycmjason
Copy link
Contributor

as vue-cli is moving away from templates, it makes sense to create a vue-cli plugin that create a vuepress project with a bunch of vuepress plugin options to be selected during vue create.

@dgpgdev
Copy link

dgpgdev commented Apr 23, 2018

@ycmjason i made a vuepress plugin for vue/cli ;) , maybe include inside plugin an input prompt to add plugin after created template.

@mdaffin you're rigth ;)

@mdaffin
Copy link
Contributor

mdaffin commented Apr 23, 2018

Another point to consider: allowing plugins a hook into the client side code to allow them to register new dynamic components or otherwise change the client-side behaviour in a similar way to the enhanceApp.js currently does.

@dacsang97
Copy link

Based on the results of the voting, I had updated plugin API to first-order function, use Babel style for configuring extra options. Now plugin support return Promise (5cdb744). Then I clone options to exposedOptions in order to avoid user modify system config (8aec214).

@samburgers
Copy link

+1 for Additional content sources... such as Contentful, WordPress Headless etc at build time!

@eyleron
Copy link

eyleron commented Apr 30, 2018

Headless CMS, data via REST / GraphQL

A lot of the static site generators hook to data-driven content sources, such as headless headless CMS like DatoCMS, StoryBlok, Netlify, Snipcart, ButterCMS, etc.
Some have RESTful API's, some provide GraphQL.

For my less technical staff, I was considering a headless CMS for topic editing as opposed to a Markdown or AsciiDoc file editor.

@lunelson
Copy link

One cloud CMS which would integrate quite easily is Dato, which —in addition to REST and soon GraphQL APIs— provides a workflow where all content can be 'dumped' to markdown files and then processed by a further the build process

https://www.datocms.com/

@EnMod
Copy link

EnMod commented Apr 30, 2018

I am currently trying to finagle a workflow for DatoCMS import at build time that involves another SSG running a build, then grabbing JSON from that build to add to VuePress. To have Dato or other headless CMSs import-able (?) and configurable directly within VuePress would be amazing.

@lunelson
Copy link

@EnMod check out this dato documentation WRT metalsmith, it walks through how to dump your data in to markdown files, and it should give you an idea how to configure the script to output in the directory / naming scheme required by VuePress.

https://www.datocms.com/docs/metalsmith/

Alternately you can dump Dato data to YML or JSON, and just require() them in to your app, as this is also supported by webpack

@EnMod
Copy link

EnMod commented Apr 30, 2018

@lunelson Thanks for that, very nifty! I'm managing a slider gallery as one of my models, so I might either:

  • dump all gallery items to markdown files and include them in the gallery's page (will have to check docs again to see if I can read the file system and include all in a folder)
  • Go the JSON route and loop with a v-for

Either way, metalsmith's integration a good solution. Having DatoCMS's data right there in VuePress, ready at build time, would save quite a bit of trouble though haha.

@ulivz
Copy link
Member Author

ulivz commented May 11, 2018

#421

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question or discussion Question or discussion
Projects
None yet
Development

No branches or pull requests

10 participants