Created
December 30, 2018 19:31
-
-
Save sliekens/350198fe025787d451f3fd16ca5f87f1 to your computer and use it in GitHub Desktop.
rollup-plugin-vue-unofficial
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Plugin, PluginContext } from 'rollup'; | |
import { createFilter } from 'rollup-pluginutils'; | |
import { | |
parse, | |
compileTemplate, | |
TemplateCompileResult | |
} from '@vue/component-compiler-utils'; | |
import { VueTemplateCompiler } from '@vue/component-compiler-utils/dist/types'; | |
import { | |
ObjectExpression, | |
BlockStatement, | |
ArrayExpression, | |
Program | |
} from 'estree'; | |
const templateCompiler = require('vue-template-compiler') as VueTemplateCompiler; | |
import * as estraverse from 'estraverse'; | |
import * as escodegen from 'escodegen'; | |
export interface Options { | |
optimize?: boolean; | |
include?: string | string[]; | |
exclude?: string | string[]; | |
} | |
export const defaultOptions: Options = { | |
include: '**/*.vue', | |
optimize: false | |
}; | |
function nullRender(): BlockStatement { | |
return { | |
type: 'BlockStatement', | |
body: [] | |
}; | |
} | |
function nullStaticRender(): ArrayExpression { | |
return { | |
type: 'ArrayExpression', | |
elements: [] | |
}; | |
} | |
export default function(options: Options = {}): Plugin { | |
options = { ...defaultOptions, ...options }; | |
const filter = createFilter(options.include, options.exclude); | |
function decompileTemplate( | |
context: PluginContext, | |
result: TemplateCompileResult | |
) { | |
let renderfn: BlockStatement | null = null; | |
let staticRenderFns: ArrayExpression | null = null; | |
let ast = context.parse(result.code, {}); | |
estraverse.traverse(ast, { | |
enter(node, parentNode) { | |
if (node.type === 'FunctionExpression') { | |
return estraverse.VisitorOption.Skip; | |
} | |
if (node.type === 'VariableDeclarator') { | |
if ( | |
node.id.type === 'Identifier' && | |
node.id.name === 'render' | |
) { | |
if (node.init == null) { | |
throw new Error(`Missing value for 'render'.`); | |
} else if (node.init.type !== 'FunctionExpression') { | |
throw new Error( | |
`The value of 'render' is not a function.` | |
); | |
} else { | |
renderfn = node.init.body; | |
} | |
} | |
if ( | |
node.id.type === 'Identifier' && | |
node.id.name === 'staticRenderFns' | |
) { | |
if (node.init == null) { | |
throw new Error( | |
`Missing value for 'staticRenderFns'.` | |
); | |
} else if (node.init.type !== 'ArrayExpression') { | |
throw new Error( | |
`The value of 'staticRenderFns' is not an array.` | |
); | |
} else { | |
staticRenderFns = node.init; | |
} | |
return estraverse.VisitorOption.Break; | |
} | |
} | |
} | |
}); | |
return { | |
render: renderfn!, | |
staticRender: staticRenderFns! | |
}; | |
} | |
return { | |
name: 'rollup-plugin-vue-unofficial', | |
transform(code, id) { | |
if (!filter(id)) { | |
return; | |
} | |
let sfcDescriptor = parse({ | |
compiler: templateCompiler, | |
source: code, | |
filename: id, | |
needMap: true | |
}); | |
let render: BlockStatement = nullRender(); | |
let staticRender: ArrayExpression = nullStaticRender(); | |
if (sfcDescriptor.template !== null) { | |
let compiledTemplate = compileTemplate({ | |
source: sfcDescriptor.template.content, | |
filename: id, | |
compiler: templateCompiler, | |
isProduction: options.optimize | |
}); | |
let parsed = decompileTemplate(this, compiledTemplate); | |
render = parsed.render; | |
staticRender = parsed.staticRender; | |
} | |
let ast: Program; | |
if (sfcDescriptor.script !== null) { | |
ast = this.parse(sfcDescriptor.script.content, {}); | |
} else { | |
ast = this.parse(`export default {}`, {}); | |
} | |
// TODO: consider skipping if obj already has render() | |
estraverse.replace(ast, { | |
enter(node, parentNode) { | |
if ( | |
node.type === 'ObjectExpression' && | |
parentNode!.type === 'ExportDefaultDeclaration' | |
) { | |
return <ObjectExpression>{ | |
type: 'ObjectExpression', | |
properties: [ | |
...node.properties, | |
{ | |
type: 'Property', | |
method: true, | |
shorthand: false, | |
computed: false, | |
key: { | |
type: 'Identifier', | |
name: 'render' | |
}, | |
kind: 'init', | |
value: { | |
type: 'FunctionExpression', | |
params: [], | |
body: render | |
} | |
}, | |
{ | |
type: 'Property', | |
method: false, | |
shorthand: false, | |
computed: false, | |
key: { | |
type: 'Identifier', | |
name: 'staticRenderFns' | |
}, | |
kind: 'init', | |
value: staticRender | |
} | |
] | |
}; | |
} | |
} | |
}); | |
return { code: escodegen.generate(ast) }; | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment