Плагин Webpack меняет содержимое с помощью asm - PullRequest
0 голосов
/ 13 ноября 2018

Задача

Привет, я пытаюсь написать плагин и использую ast для анализа файла. Но я не могу внести изменения в код. Например, этот код не меняет div на метку. Как правильно изменить АСТ?

    apply(compiler) {
      compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
        factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => {
          parser.hooks.program.tap('MyPlugin', (ast, comments) => {

            if (parser.state &&
                parser.state.module &&
                parser.state.module.resource.indexOf('node_modules') === -1) {

            if (parser.state.module.resource.endsWith('tsx')) {
                var g = ast.body.filter(n=> n.type === 'ExportNamedDeclaration');

            for (let a of g) {
              var decl = a.declaration.declarations;

              if (decl && decl[0]) {
                decl[0].init.body.body[0].argument.arguments[0].raw = 'label';
                decl[0].init.body.body[0].argument.arguments[0].value = 'label';
              }
            }
          }
        }
      });
    });
  });
}`

Мне просто нужно изменить div на метку в блоке возврата или добавить data-attr в div. Я не хочу использовать регулярные выражения и заменять все содержимое файла, я хочу сделать это с помощью Ast. MyComponent.tsx может быть следующим:

import * as React from 'react';
import * as style from './MyComponent.css';

export const MyComponent = (props) => {
  return (
    <div className={style['test']}>bla bla</div>
  );
};

Может быть, кто-нибудь может привести небольшой пример изменения чего-либо с помощью абстрактного синтаксического дерева в плагине webpack.

1 Ответ

0 голосов
/ 19 ноября 2018

Как упоминалось в комментариях и указывалось в коде веб-пакета в в этом вопросе , веб-пакет игнорирует попытки изменить синтаксический анализатор AST одним касанием.

Ожидается, что плагины будут использовать ast в качестве карты только для чтения для построения новых зависимостей в графе . (Это менее хрупко в отношении упорядочения и параллельного выполнения, так как несколько плагинов могут добавлять к графу зависимостей, не аннулируя друг друга, изменяя эталонный AST.)

Основанный на i18n-lang и Define Plugins, пример использования ast для построения зависимости для вашего преобразования может выглядеть следующим образом:

"use strict";
const pluginName = 'MyPlugin';
const NullFactory = require('webpack/lib/NullFactory');
const ConstDependency = require("webpack/lib/dependencies/ConstDependency");

class MyPlugin {

    apply(compiler) {

        compiler.hooks.compilation.tap(
            "MyPlugin",
            (compilation, { normalModuleFactory }) => {
                compilation.dependencyFactories.set(ConstDependency, new NullFactory());
                compilation.dependencyTemplates.set(
                    ConstDependency,
                    new ConstDependency.Template()
                );
            });


        compiler.hooks.normalModuleFactory.tap('MyPlugin', (factory) => {
            factory.hooks.parser.for('javascript/auto').tap('MyPlugin', (parser, options) => {
                parser.hooks.program.tap('MyPlugin', (ast, comments) => {

                    if (parser.state &&
                        parser.state.module &&
                        parser.state.module.resource.indexOf('node_modules') === -1) {

                        if (parser.state.module.resource.endsWith('tsx')) {
                            var g = ast.body.map(n => {
                                try {
                                    let {expression:{left:{property:{name:my}}, right:{body:{body:[{argument:{arguments:[div]}}]}}}} = n
                                    return my == 'MyComponent' && div.value == 'div' ? div: false 
                                } catch(e) {
                                  return false;
                                }
                            }).filter(e=>e);
                            for (let div of g) {
                                let dep = new ConstDependency(JSON.stringify('label'), div.range);
                                    dep.loc = div.loc;
                                    parser.state.current.addDependency(dep);
                            }
                        }
                    }
                });
            });
        });
    }
}

module.exports= MyPlugin;

Где ast, предоставляемый синтаксическим анализатором, может немного отличаться для разных загрузчиков и изменений входных данных.

...