Closed
Description
Background
Hey, guys, there is a previous work for plugin support: #240 (Lifecycle-based Plugin Support), but it seems only focus on providing Hook, and doesn't provide some useful APIs for plugin to use. so this issue is for that.
Proposal
My proposal is to leverage the plugin style from webpack. so for me, a ideal plugin would be like:
class XXXPlugin {
constructor(pluginOptions) {
this.options = pluginOptions
}
apply(app) {
// app is the current VuePress app instance.
// You can access all the app's properties and methods.
// so to finish this plugin API, we need to rewrite the core as a class.
////////////////////////////
// Basic extension
////////////////////////////
// #1 extend webpack via webpack-chain.
app.chainWebpack(config => { })
// #2 extend markdown
app.extendMarkdown(md => {
md.use(require('markdown-it-xxx'))
})
// #3 add extra temp file.
// so 'enhanceApp' and 'themeEnhanceApp' can be seperated as plugin.
app.enhanceAppFiles.add('[relative]', content) // generate file to '.temp/relative'
app.enhanceAppFiles.add('[absolute]') // copy to '.temp' if 'absolute' exists
// #4. Write extra file to outDir.
app.outFiles.add('[relative]', content) // generate file to 'outDir/relative'
app.outFiles.add('[absolute]') // copy to outDir if 'absolute' exists
// #5. Add extra data mixins, will be merged to core's dataMixin.
app.dataMixin.add({
computed: {
$themeTitle () { /* ... */ }
},
methods: { /* ... */ }
})
// #6. enhance dev server ('webpack-serve')
app.enhanceDevServer(server => {})
// #7. extend the $page's data
// so 'lastModified' support can be separated into a plugin.
app.extendPageData((filepath, path, content, frontmatter) => {
return {
lastModified: getLastModified(filepath)
}
})
////////////////////////////
// Life Cycle (Browser)
////////////////////////////
// #8 called before creating Vue app. (DEV & BUILD)
// So 'GA', 'SW' and 'scrollingActiveSidebarLink' could be separated into a plugin.
// Consider if we should open the Layout's hooks ???
app.hook.add('beforeCreateApp', ({ Vue, options, router, siteData }) => {})
////////////////////////////
// Life Cycle (Node.js)
////////////////////////////
// #9. called when all options was resolved. (DEV & BUILD)
// with this hook, all the internal generate-related logic at prepare
// can be separated into a plugin.
app.hook.add('ready', () => {})
// #10. called when webpack finished compiled. (DEV & BUILD)
app.hook.add('compiled', () => {})
// #11. called when webpack hot updated (only DEV)
app.hook.add('updated', () => {})
// #12. called when all files are generated (only BUILD)
app.hook.add('generated', () => {})
// ... we can also provide some useful utils.
}
}
With this plugin mechanism, maybe we can do a lot of things we want to do.
Feel free to tell me your thoughts. and we can make plugin more powerful !!!