Javascript 有没有一种方法可以连接到Webpack';是AST让它识别新的模块格式吗?

Javascript 有没有一种方法可以连接到Webpack';是AST让它识别新的模块格式吗?,javascript,node.js,webpack,Javascript,Node.js,Webpack,短版: 我们如何处理最终输出包的AST,以及加载程序中文件的AST?在这两种情况下,我都希望操作现有的AST,而不是我正在做的事情,即解析源代码并生成一个新的AST。我做的很慢,而且我知道Webpack肯定已经做了AST,所以我想避免重复工作 长版本: 例如,假设我有一堆文件,其格式与AMD模块类似(但不完全相同): module({ Foo: '/path/to/Foo', Bar: '/path/to/Bar', Baz: '/path/to/Baz', }, function(

短版:

我们如何处理最终输出包的AST,以及加载程序中文件的AST?在这两种情况下,我都希望操作现有的AST,而不是我正在做的事情,即解析源代码并生成一个新的AST。我做的很慢,而且我知道Webpack肯定已经做了AST,所以我想避免重复工作

长版本:

例如,假设我有一堆文件,其格式与AMD模块类似(但不完全相同):

module({
  Foo: '/path/to/Foo',
  Bar: '/path/to/Bar',
  Baz: '/path/to/Baz',
}, function(imports) {
  console.log(imports) // {Foo:..., Bar:... Baz:...}
})
不同之处在于,它被称为
模块
,而不是
定义
,依赖项参数是导入名称到模块路径的映射,而不是模块路径数组,模块正文函数接收一个包含所有请求导入的
导入
对象,而不是每个请求导入一个参数

以上类似于AMD格式的以下内容,具有相同的输出:

define([
  '/path/to/Foo',
  '/path/to/Bar',
  '/path/to/Baz',
], function(Foo, Bar, Baz) {
  console.log({Foo, Bar, Baz}) // {Foo:..., Bar:... Baz:...}
})
为了最终构建一个包含以此
module()
格式编写的文件的捆绑包,建议采用何种方式连接到Webpack以使Webpack能够理解文件(能够知道文件具有哪些依赖关系)

我已经尝试过一种方法:我制作了一个自定义加载程序,它以字符串形式接收文件源代码,对其进行解析并创建AST,转换AST,然后以Webpack能够理解的AMD
define()
格式输出代码


然而,我觉得这样做很慢,因为如果有很多文件,而且文件很大,那么解析和生成每个文件的AST似乎是多余的,因为我打赌Webpack从一开始就已经这样做了。有没有办法从Webpack获取AST并在Webpack想要扫描其依赖项之前对其进行转换,以便我可以将AST转换为AMD格式(或任何公认的格式),以便Webpack最终可以处理该文件?还有其他方法吗?

我想您会发现在依赖项解析过程中使用了加载程序

基本上,解析器需要源代码才能完成其工作。因此,在当前解析阶段遇到的任何import/require语句(依赖项)都需要:a。被解决和:b。必须先加载,然后才能对其进行分析。如果您挂接到增强解析包的“解析步骤”,您可以console.log退出解析程序转换的状态转换,这些状态转换通常以触发“创建模块”插件而告终

钩住“解决步骤”:

钩住“创建模块”:


希望这能有所帮助。

我正在寻找类似的东西,想要操纵ast,但没有示例或有用的文档

用谷歌搜索它只浪费了我2个小时的时间,但由于完成了一半且不可理解的文档,我确实想到了这个(尽管不起作用):

这会给我一个if语句的节点,对于其他类型的节点,您可以查看

我尝试返回另一个节点,但是创建一个节点需要大量的工作,而且似乎没有一个简单的方法来完成

为什么还要费心在网页包中这么做呢?webpack贡献者制作了一个很好的产品,但没有人知道它是如何工作的,因为它的许多功能都没有文档

作为一个babel插件,你可能会做得更好,它写得很好,可以理解

我和巴贝尔在20分钟内完成了这项工作:

module.exports = function ({ types: t }) {
    return {
        visitor: {
            IfStatement(path, file) {
        path.node.test = {
          "type": "BooleanLiteral",
          "start": path.node.test.start,
          "end": path.node.test.start+4,
          "loc": {
            "start": {
              "line": 7,
              "column": path.node.test.loc.start.column
            },
            "end": {
              "line": 7,
              "column": path.node.test.loc.start.column+4
            }
          },
          "value": true
        }
        // debugger;
                // path.unshiftContainer('body', t.expressionStatement(t.stringLiteral('use helloworld')));
      }
        }
  };
};
在webpack.config.js中:

const path = require("path");
const webpack = require("webpack");

module.exports = {
  entry: "./src",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].chunk.js"
  },
  module:{
    rules: [
      {
        test: /\.html$/,
        use: [{ loader: './plugin/templateLoader' }]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['env'],
            plugins: [require("./plugin/myBabelPlugin")]
          }
        },
      }
    ]
  }
}
var acorn = require("acorn-dynamic-import").default;

function MyPlugin(options) {
  // Configure your plugin with options...
}

MyPlugin.prototype.apply = function(compiler) {
  compiler.plugin("compilation", function(compilation, data) {
    data.normalModuleFactory.plugin(
      "parser"
      , function(parser, options) {
        parser.plugin(
          [
            "statement if"
          ]
          ,(node)=>
            Object.assign(
              node
              ,{
                test:{
                  type:"Literal",
                  start: node.test.start,
                  end: node.test.start+4,
                  loc: {
                    start: {
                      line: 7,
                      column: 3
                    },
                    end: {
                      line: 7,
                      column: node.test.loc.start.column+4
                    }
                  },
                  range: [
                    node.test.range,
                    node.test.range+4
                  ],
                  value: true,
                  raw: "true"
                }
              }
            )
        ); 
      });
  });
};

module.exports = MyPlugin;
module.exports = function ({ types: t }) {
    return {
        visitor: {
            IfStatement(path, file) {
        path.node.test = {
          "type": "BooleanLiteral",
          "start": path.node.test.start,
          "end": path.node.test.start+4,
          "loc": {
            "start": {
              "line": 7,
              "column": path.node.test.loc.start.column
            },
            "end": {
              "line": 7,
              "column": path.node.test.loc.start.column+4
            }
          },
          "value": true
        }
        // debugger;
                // path.unshiftContainer('body', t.expressionStatement(t.stringLiteral('use helloworld')));
      }
        }
  };
};
const path = require("path");
const webpack = require("webpack");

module.exports = {
  entry: "./src",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].chunk.js"
  },
  module:{
    rules: [
      {
        test: /\.html$/,
        use: [{ loader: './plugin/templateLoader' }]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['env'],
            plugins: [require("./plugin/myBabelPlugin")]
          }
        },
      }
    ]
  }
}