-
Notifications
You must be signed in to change notification settings - Fork 52
Kickoff: redesign #28
Comments
We should careful to add new API to avoid making Vue overcomplicated |
A consolidate like library for style. |
/ping @eddyerburgh |
I'm not sure how it would work with vue-loader. But for jest-vue passing the compiled script, template HTML and styles would be ideal. We'd also need to pass SourceMaps. style = {
code: string,
map: SourceMap
}
style = {
style: string,
scoped: Boolean
}
vueComponentCompiler.compile(string, script, style[]) The compiler would return the code and a sourcemap: {
code: string,
map: SourceMap
} |
SFC can have custom blocks too. |
Proposed API. interface Compiler {
// Complete compiler. Takes in SFC.
compile(source: String, filename: String, options: CompilerOptions): Output
// SFC to descriptor parsing.
_parse(source: String, filename: String, options: ParserOptions): Output
// Consolidated style processor.
_style(source: String, filename: String, options: StyleProcessorOptions): CompiledStyle
// Template to render function compiler (wrapper around vue-template-compiler).
_template(source: String, filename: String, options: TemplateCompilerOptions): CompiledCode
}
type Output = {
script: CompiledCode
styles: Array<CompiledStyle>
} & {
[customBlock: string]: Array<CompiledCode>
}
type CompiledCode = {
code: string
map: SourceMap
}
type CompiledStyle = CompiledCode & {
module: { [key: string]: string }
}
type CompilerOptions = {}
type ParserOptions = {}
type TemplateCompilerOptions = {
lang: string
scopeId: string | null
}
type StyleProcessorOptions = {
lang: string
module: boolean | string
scoped: boolean
scopeId: string | null
}
type SourceMap = {} |
Related: vuejs/vetur#276 vuejs/vetur#380 In Vetur we are looking into ways to parse Vue SFC and generate a descriptor that can be used for enhancing IntelliSense in Currently Vetur has limited support for libraries such as element-ui. And it depends on manually entered descriptor:
Would be intersting to keep Vue Language Server in mind while designing the compiler. That's the approach TS designed its compiler and language server to get great editing experience.
Now here we are :D |
We can currently add custom blocks to a SFC, but we would like to add a custom attributes to the <template></template>
<script></script>
<style></style> <!-- common styles shared acrosss platforms -->
<style platform="android"></style> <!-- styles only used on android -->
<style platform="ios"></style> <!-- styles only used on ios--> Ideally this would be reusable for all blocks, so we could add the |
Any attribute is supported on const compiler = require('vue-template-compiler')
const fs = require('fs')
const result = compiler.parseComponent(fs.readFileSync('./Test.vue').toString())
console.log(JSON.stringify(result, null, 2)) Descriptor for ...
{
"type": "style",
"content": "",
"start": 341,
"attrs": {
"platform": "ios",
"module": true
},
"module": true,
"end": 341
} P.S.: We should consider platform if consolidated style processing goes in vue-component-compiler. |
Open questions:
|
We probably need to first decide what features should be supported. A general pattern is that the more features are supported, the more assumptions are quired. Several thoughts:
This is the easiest and most universal feature. We can extract descriptor parsing from Vue source.
Transpilation is easy for some language like CoffeeScript: one script in one script out. Yet most styling languages like sass and stylus needs whole file dependency. Say, component.styl depends on base.styl. We need resolve that dependency. Luckily, most transpilers provide API for transpile one file. Vue-component-compiler might need to mock a filename/file path for transpilers to resolve dependency. (Real file system access is probably necessary.) That said, integrating a series of transpilers isn't easy.
Finding config shouldn't be hard. (Notwithstanding details matter)
This is mainly for vue-loader. If we transpile source by vue-component-compiler, we need to inform webpack which files are used. Similar situation is expected for future tools like
Most compilers are bad at error handling. e.g Stylus cannot report the error line when a syntax happens. Pug compiler cannot recover from malformed input. This prevents component-compiler from being used in interactive environment like editor. @octref It seems that the hard story begins from preprocessor support. |
Regarding pre-processors: It should be noted that in Basically, this means instead of providing one single API, we should first design several low-level APIs and then compose them into higher level usage: // All usage hypothetical. We will likely need to pass additional options along the way
import { parse, compileTemplate, compileStyles, assemble } from 'vue-component-compiler'
// 1. parse
// equivalent: vue-loader/lib/parser.js
const descriptor = parse(source)
// 2. pre-processors
// (to be implemented by other tools)
// in vue-loader, this would be equivalent to `getRequireString`
const processedStyles = preProcessStyles(descriptor.styles)
const processedScript = preProcessScript(descriptor.script)
const processedTemplate = preProcessTemplate(descriptor.template)
// 3. vue-specific post processing
// equivalent: vue-loader/lib/style-compiler
const finalStyles = compileStyles(processedStyles)
// equivalent: vue-loader/lib/template-compiler
const renderFns = compileTemplate(processedTemplate)
// 4. assemble final component
// equivalent: parts of vue-loader/lib/loader.js and vue-loader/component-normalizer.js
const finalComponentCode = assemble(processedScript, renderFns, finalStyles) Remember the primary goal is to extract tooling agnostic logic and reduce redundancy instead of providing a standalone compiler. |
Indeed, providing utility function looks better. It imposes least assumption and thus make library use at free. |
Looks clean.
|
How about providing a standalone compiler with options to customize pre-process and assemble steps? |
The primary goal here is to extract tooling agnostic logic and reduce redundancy instead of providing a standalone compiler. |
Closing in favor of #34 . |
So far, we have seen the logic of compiling an SFC duplicated in multiple projects:
vue-loader
vueify
rollup-plugin-vue
jest-vue
...and others. The goal here is to extract shared logic regarding SFC compilation into a dedicated package to avoid redundancy and ensure all of these tools are on the same page regarding SFC features and behavior.
Some initial thoughts. APIs should include:
Not entirely clear how much we should and could extract from
vue-loader
, as a lot of it is tightly coupled to webpack, but let's discuss./cc @znck @eddyerburgh @phanan @vuejs/collaborators
The text was updated successfully, but these errors were encountered: