9

最近,我开始学习如何构建 webpack 插件。我正在尝试构建一个可以更新我的源代码的插件。

规则很简单:

  1. 如果入口点名称少于 2a秒,我必须将所有变量重命名hahahehe所述入口点块中的所有模块中的所有变量。
  2. 如果入口点名称超过 2a秒,我必须将所述入口点haha块中所有模块的所有变量重命名为。hoho

这是我的代码:

一个.js

const haha = 'hello';
// will be "const hehe = 'hello';" in the bundle of "aa" entry point
// will be "const hoho = 'hello';" in the bundle of "aaaa" entry point
console.log(haha);
// will be "console.log(hehe);" in the bundle of "aa" entry point
// will be "console.log(hoho);" in the bundle of "aaaa" entry point
export default haha;
// will be "export default hehe;" in the bundle of "aa" entry point
// will be "export default hoho;" in the bundle of "aaaa" entry point

几个.js

import haha from 'a'; // will be "import hehe from 'a';" in the bundle
console.log(haha); // will be "console.log(hehe);" in the bundle

很多.js

import haha from 'a'; // will be "import hoho from 'a';" in the bundle
console.log(haha); // will be "console.log(hoho);" in the bundle

webpack.config.js

module.exports = {
 mode: 'development',
 entry: {
    aa: 'few.js',
    aaaa: 'lots.js'
 },
 output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist')
 }
};

我不知道这样做的正确方法是什么。

一开始我以为我的插件要注册到解析器的特定钩子上,检查当前入口点的名字,替换掉AST节点的名字。问题是该模块a.js只被解析一次。

我尝试的第二种方法是通过简单的正则表达式注册到并重命名变量的render钩子。mainTemplate我不喜欢这种方法,因为通过正则表达式替换代码非常困难(IMO)。

你怎么看?正确的方法是什么?

4

2 回答 2

1

你是对的。您无法在模块中获取条目信息。我认为您可以通过其他方式解决不使用入口点的问题。由于模块一旦加载就会被缓存,我们可以使用内联资源查询

一个.js

    const haha = 'hello';
    console.log(haha);
    export default haha;

几个.js

    import haha from './a?change=e'; // will be "import hehe from 'a';" in the bundle
    console.log(haha); // will be "console.log(hehe);" in the bundle

很多.js

    import haha from './a?change=o'; // will be "import hehe from 'a';" in the bundle
    console.log(haha); // will be "console.log(hoho);" in the bundle

自定义加载器-> transformer.js

    module.exports = function(source) {
      let queryval = "";
      if (this.resourceQuery && this.resourceQuery.indexOf('change')) {
        queryval = this.resourceQuery.substr(this.resourceQuery.indexOf("change"+ 1));
        // console.log("queryval: ", queryval);
        if (queryval) {
          const replacedCode = source.replace(/[a]/g, queryval); // this replace every thing but need own logic even default -> def_ult _ is query val :P
          console.log("replacedCode: ", replacedCode);
          return replacedCode;
        }
      }
      return source;
    }

webpack.config.js

    const path = require('path');

    module.exports = {
        mode: 'development',
        entry: {
            aa: './src/few.js',
            aaaa: './src/lots.js'
        },
        module: {
          rules: [
            {
              test: /\.js$/,
                oneOf: [
                  {
                    resourceQuery: /change/,
                    use: [
                      {
                        loader: path.resolve('./src/transformer.js'),
                        options: {
                          replaceWith: true
                        }
                      }
                    ],
                  },
                  {
                    loader: path.resolve('./src/transformer.js'),
                  }
                ],
            }
          ]
        },
        output: {
            filename: '[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        optimization: {
          runtimeChunk: "single"
        }
    };
于 2018-09-26T06:23:41.077 回答
0

我打开了一个问题Tobias Koppers的回应:

那是不可能的。

这些模块独立于原始入口点。模块图不包含此信息。除此之外,模块可以在两个入口点中,但在这种情况下不会构建两次。

于 2018-09-26T05:14:54.097 回答