Skip to content

Expose the api for directly generating render function code from element ASTs in createCompiler function #5703

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

Closed
CXHtml opened this issue May 19, 2017 · 7 comments

Comments

@CXHtml
Copy link

CXHtml commented May 19, 2017

What problem does this feature solve?

It may sounds awkward when using the modified AST to generate render function instead of using template files as input. But, in the following cases, it might be useful:

What if:

  • people want to do some optimized operations on AST like what the optimizer.js does before jump into the codegen method in the baseCompile function.
  • a pre-disposed component can be loaded via webpack loader which implements the exposed generate function to get the new render function. In this case, I can initially load some customized vue components with new added dom elements, attributes, events and etc.
  • I can visually edit the rendered components by modifying the ASTs instead of the original template which is considered to be much easier.
  • After the previous step, I can even generate the new template file like the reverse way of template -> AST -> render function.

I'm not sure whether there is an alternative way of doing the things above, but it might be helpful when it comes to something like visualized vue components development IDE.

What does the proposed API look like?

Maybe in the createCompilerCreator function, we can add a function as property in compile method like:

compile.fromAST = function fromAST(
    ast
  ) {
    return generate(ast, baseOptions)
  };

in line 49, src/compiler/create-compiler.js

@CXHtml
Copy link
Author

CXHtml commented May 23, 2017

I don't think JSX is what I need, 'cause it is just the syntactic sugar of what the createElement does. Just suppose I want to load and then render the component as usual, but at the same time in other scenario, I want to load the exactly the same component which has new attrs or props added and its original binded event is disabled (or removed). Most importantly, I want to keep the template of the component as pure as possible instead of modifying (by adding extra logic) to achieve this goal. I think the best way is to modify the AST directly and then compile to render function. Hope you guys can catch my point.

z-ZYS-s added a commit to vusion/vue that referenced this issue Jun 12, 2017
@yyx990803
Copy link
Member

Does #5857 address your needs? I'm still interested in a more concrete/detailed usage example - by concrete I mean what problem does it solve for your project?

@rainfore can you also provide some examples of what kind of plugins you think that can be written?

@z-ZYS-s
Copy link

z-ZYS-s commented Jun 16, 2017

@yyx990803 CXHtml and I are a team. We're planning to create an IDE for Vue, which support editing a single component, UI Library and even a webapp project. Here is a simple demo (not the final result) https://github.com/vusion/vusion

The following steps about handling template are necessary:
When editing a vue file:
1.1. compile template to AST
1.2. remove the original events in component and add some other attributes or events in AST (In the workspace, we don't want to trigger the original events. And to modify AST is easier than to modify a template or a render function)
1.3. generate render function from the modified AST
1.4. trigger the hot reload to update the living component
When saving a vue file:
2.1. get the working AST
2.2. restore the events into AST and maybe the user can add or remove some events or attributes
2.3. regenerate a template from the AST
2.4. write into the file

The issue and the PR i pushed are about 1.2. We really need a api to generate render function directly from some AST not from a template. Maybe there is some solution better than I thought. We are hoping to get more advice from you.

BTW, according to 2.3, we also need some function like toString in PostCSS.

@CXHtml
Copy link
Author

CXHtml commented Jun 20, 2017

@yyx990803 after our discussion, we find that using the plugin pattern to expose the AST doesn't address our needs either. The reason is simple, each time we generate render function by means of compile method with the plugin options, the AST is always generated from parse method. But, what I need is just modify the AST object once we obtain from the compile method and then pass to the generate method to get the render func.

In addition, after we digging into compiler/codegen source code, we cannot directly use the AST in the API (compile.fromAST) I've proposed. Because the AST object has been modified (like some xxProcessed attributes are added or array.shift() method are used) after the generate method called. It means that next time when I call generate method, the render function may not be generated as expected. So I wonder is it possible to make the generate method as pure function ? No matter how many times I call the generate, the AST is as same as what is like after the parse method ?

Hmm. Also, can you expose the parse/optimize/generate method to the plugin options that @rainfore mention before?

@z-ZYS-s
Copy link

z-ZYS-s commented Jun 20, 2017

As @CXHtml mentioned, my PR doesn't address our needs completely. So I close my pull request at present.

@yyx990803
Copy link
Member

I'm still not quite sure why plugins wouldn't be enough for your use case. Maybe you can try to explain in Chinese...

@yyx990803
Copy link
Member

This request has been stale for a while. In the meanwhile, vue-loader actually allows you to inject custom compiler modules via the compilerModules option: https://github.com/vuejs/vue-loader/blob/master/lib/template-compiler/index.js#L17

The module API is defined here and should theoretically enable most standard use cases. Alternative codegens are imo too much control to be given to userland.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants