简体   繁体   English

如何从@babel/template 中移除环绕的 IIFE?

[英]How to remove the surround IIFE from @babel/template?

I'm trying to convert some Ember codes to React.我正在尝试将一些 Ember 代码转换为 React。 Here is what I want to transform.这就是我想要改造的。

From

export default Ember.Component.extend(({
    didInsertElement() { }
});

To

export default class MyComponent extends React.Component {
    componentDidMount() { }
}

I write a babel plugin, and try to replace the Ember.Component.extend call with an AST node which is produced by template method.我写了一个 babel 插件,并尝试用template方法生成的 AST 节点替换Ember.Component.extend调用。 Here is the code snippet.这是代码片段。

babel-plugin babel 插件

const { default: template } = require("@babel/template");

const code = `class TestComponent extends React.Component { 
   componentDidMount() { }
 }`;
let classDeclarationNode = template.ast(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            CallExpression(path) {
                if (!path.getSource().startsWith("Ember.Component.extend")) {
                    return;
                }
                path.replaceWith(classDeclarationNode);
            }
        }
    };
};

Output输出

export default (function () {
  class TestComponent extends React.Component {
    componentDidMount() {}
  }
})();

Instead of the expected code I wrote above, I get the ClassDeclaration statement surrounded with IIFE .而不是预期的代码,我写了上面的,我得到的ClassDeclaration与包围声明IIFE Is there any way to remove the IIFE ?有什么办法可以删除IIFE吗?

I have struggled with the problem one whole day, but have no way to resolve it.我一整天都在为这个问题苦苦挣扎,但没有办法解决它。


BTW, I also tried parseExpression method, but still can't get what exactly I want.顺便说一句,我也尝试了parseExpression方法,但仍然无法得到我想要的。

babel-plugin babel 插件

const { parseExpression } = require('@babel/parser');

const code = `class TestComponent extends React.Component { 
    componentDidMount() { }
}`;
let expression = parseExpression(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            CallExpression(path) {
                if (!path.getSource().startsWith("Ember.Component.extend")) {
                    return;
                }
                path.replaceWith(expression);
            }
        }
    };
};

Output输出

export default (class TestComponent extends React.Component {
  componentDidMount() {}
});

It's quite close to the correct code, except an extra pair of () .除了一对额外的()之外,它非常接近正确的代码。 Is there any way to generate the pure class declaration ?有没有办法生成纯class declaration

Thanks for the help of loganfsmyth on Slack, the problem was finally resolved.感谢loganfsmyth在Slack上的帮助,问题终于解决了。 I should replace the node of whole export default but not only the CallExpression .我应该替换整个export default的节点,而不仅仅是CallExpression Here is the code.这是代码。

babel-plugin babel 插件

const { default: template } = require("@babel/template");

const code = `export default class TestComponent extends React.Component { 
   componentDidMount() { }
 }`;
let rootNode = template.ast(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            ExportDefaultDeclaration(path) {
                let isMatchedNode = (path.node.declaration &&
                    t.matchesPattern(path.node.declaration.callee, "Ember.Component.extend"));
                if (!isMatchedNode) {
                    return;
                }
                path.replaceWith(rootNode);
            }
        }
    };
};

Output输出

export default class TestComponent extends React.Component {
  componentDidMount() {}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM