Why Vue SFC have no transformer / 为什么 Vue SFC 没有 transformer #12083
Unanswered
CrabSAMA
asked this question in
Help/Questions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
English version:
Background
In the development process, when facing problem such as Vue version upgrades, component library version upgrades, and code refactoring, we need to process the source code. Using regular expressions is feasible but very complex, so I prefer to use AST-based methods to do this.
Example 1: extract and replace i18n key
original:
result:
Example 2: update ant-design-vue v3 to v4
https://next.antdv.com/docs/vue/migration-v4-cn
original:
result:
The AST-based code modification scheme generally divides into parse and transform. Parse converts the source code into AST, and transform converts the modified AST back into source code. In the JS field, we have mature tools like babel and jscodeshift, which both have parse and transform functions. In the HTML field, parsers include htmlparser2, and posthtml has both parse and transform functions. Vue's own SFC parsing also uses babel and htmlparser2.
Problem
In the sfc compiler provided by Vue, it can help us convert SFC into AST, and we can also modify the AST. However, it does not provide a transformer to convert AST back into source code. Vue only provides a transformer to convert AST into render functions. I am not sure why Vue does not provide this transformer to convert back to source code.
In my opinion, it might be unnecessary or difficult to handle. When I compare it with React, I find that there are many such tools in the React ecosystem. The official ant-design also directly provides corresponding codemod tools to handle version upgrades. Is it because React uses JSX that can be parsed by babel, so it can directly use babel or jscodeshift to implement the transformer, making the implementation cost relatively low?
Similar to the https://github.com/reactjs/react-codemod library, React officially provides codemod tools that allow us to easily make some modifications to the code. Vue also seems to provide a similar library https://github.com/vuejs/vue-codemod, but it is unclear why it has not been maintained, and currently, the codemods inside are mostly used to handle the script part of the code.
My Attempt
In summary, in Vue SFC, the script part of the code is easy to handle. We only need to parse it out and use babel to process it. The difficult part is the template section. Initially, my idea was to treat the template part as HTML and use an HTML parser and transformer to handle it. However, the htmlparser2 used by Vue does not have a transformer, and posthtml's functionality is not perfect. The generated code also affects the style of the source code. During this process, I encountered issues such as losing self-closing tags and incorrect props modification. I personally feel that this is not a qualified solution.
In the end, I tried to manually concatenate the code strings through if-else cases using the AST parsed by Vue compiler/core, achieving simple code modification functionality.
Expectation
I hope that an expert from the Vue Core Team can explain why Vue does not provide this transformer. At the same time, I welcome fellow developers who have encountered similar issues to discuss better solutions. Thank you!
中文版:
背景
在开发过程中,面对 Vue 版本升级、组件库版本升级、代码重构等场景,都需要我们对源代码进行处理,使用正则是可行的,但是它十分复杂,因此我更倾向于使用基于 AST 的方法去做这件事。
基于 AST 的代码修改方案一般分为 parse 和 transform,parse 将源代码转成 AST,transform 将修改后的 AST 转回源代码。在 JS 领域,我们有成熟的工具 babel、jscodeshift 等,它们都有 parse 和 transform 的功能;在 HTML 领域的 parser 有 htmlparser2,posthtml 同时具有 parse 和 transform 功能。Vue 本身的 SFC 解析也有用到 babel 与 htmlparser2。
问题
Vue 提供的 sfc compiler 中,能够帮助我们将 SFC 转成 AST,我们也可以对 AST 进行修改,但是并没有提供 AST 转回源代码的 transformer,Vue 只提供了将 AST 转成 render 函数的 transformer。不知道是出于什么考虑,Vue 官方并没有做这个转回源代码的 transformer。
在我看来,可能是没有这个必要,或者是比较难去处理?我习惯地与 react 进行对比,发现 react 生态下这类工具十分多,ant-design 官方在升级版本的时候也直接提供了对应的 codemod 工具来进行处理。是不是因为 react 使用的 jsx 能被 babel 解析,因此可以直接使用 babel 或者 jscodeshift 就可以实现 transformer,实现成本比较低?
类似 https://github.com/reactjs/react-codemod 这个库,react 官方提供了 codemod 工具,能让我们方便地对代码进行一些修改。
Vue 似乎也提供了类似的库 https://github.com/vuejs/vue-codemod ,但是不清楚是因为什么原因没有继续维护下去,并且目前看里面的 codemod 基本都用于处理 script 部分的代码。
我的尝试
综上所述,在 Vue SFC 中,script 部分的代码是好处理的,我们只需要将其解析出来使用 babel 来做处理即可,比较难处理的是 template 部分。最初我的想法是,将 template 部分当做 html,使用 html 的 parser 和 transformer 来处理,但 Vue 官方使用的 htmlparser2 并没有 transformer,而 posthtml 的功能不完善,生成出来的代码也会影响源代码的样式,在这个过程中就遇到了单闭合标签丢失、props 修改错误的问题,我个人感觉这也不是一个合格的方案。
最终我尝试着将 Vue compiler/core 解析出来的 AST,自己通过 if else case 手动进行了代码的字符串拼接,实现了简单的代码修改功能。
期望
希望有 Vue Core Team 的大牛能解释一下为什么 Vue 官方没有做这个 transformer,同时也欢迎遇到问题的同行朋友们一起来讨论一下这种问题有什么更好的解决方案,感谢!
Beta Was this translation helpful? Give feedback.
All reactions