Как обновить исходный код модуля на каждый фрагмент?


Недавно я начал изучать, как создавать плагины webpack. Я пытаюсь создать плагин, который обновит мой исходный код.

Правила просты:

  1. Если имя точки входа имеет менее 2a s, Я должен переименовать все переменные haha в hehe во всех модулях в куске указанной точки входа .
  2. Если имя точки входа имеет более 2 as, Я должен переименовать все переменные haha в hoho всех модулей в куске упомянутой точки входа .

Вот мой код:

a. 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

веб-пакет.конфиг.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).

Что вы думаете? Каков правильный путь к этому?

2 9

2 ответа:

Ты прав. Вы не можете получить информацию о входе в модули. Я думаю, что вы можете решить, может быть, по-другому, не используя точку входа. В качестве модулей кэшируются, как только он загружен, мы можем использовать встроенный запрос ресурсов

A. 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

Пользовательский загрузчик - > трансформатор.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;
    }

Веб-пакет.конфиг.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"
        }
    };

Я открыл выпуск . Ответ от Тобиаса Копперса :

Это невозможно.

Модули независимы от исходной точки входа. Модуль график не содержит этой информации. В дополнение к этому модули может быть в обеих входных точках, но не строятся дважды в этом случае.