Начало работы с плагином babel — AST (Abstract Syntax Tree)

Babel

содержание

  • Введение в Вавилон
  • Как работает Бабель
  • Разбор АСТ
  • Трансформация АСТ
  • Написать плагин Babel

Введение в Вавилон

Babel — это компилятор JavaScript, который может компилировать языки, которые не распознаются младшими браузерами, такими как es2015, и реагировать.

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

Как работает Бабель

Три основных этапа обработки в Babel:

Разбирать, преобразовывать, генерировать.

Babel三个步骤

Процесс декомпозиции описывается на языке следующим образом:

Разобрать

Используйте синтаксический анализатор babylon для анализа входной строки исходного кода и создания начального AST (File.prototype.parse)

Используйте независимый пакет babel-traverse для обхода AST, анализа пути всего дерева и считывания соответствующей метаинформации через смонтированный метаданныеVisitor.Этот шаг называется процессом установки AST.

конвертировать

Процесс преобразования: пройдитесь по дереву AST и примените каждый преобразователь (плагин) для создания преобразованного дерева AST.

Ядром babel является babel-core, который предоставляет интерфейс babel.transform.

let result = babel.transform(code, {
    plugins: [
        arrayPlugin
    ]
})

генерировать

Используйте Babel-генератор для вывода дерева AST в виде перекодированной строки кода.

Разбор АСТ

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

узел

AST преобразует стрелочную функцию, упомянутую в начале, в дерево узлов в соответствии с узлом.

Стрелочные функции ES2015

codes.map(code=>{
	return code.toUpperCase()
})

map+стрелочная функция+возврат буквы в верхнем регистре Кажется, что это очень простая функция, а соответствующее абстрактное синтаксическое дерево (AST) обычно более сложное, особенно для некоторых сложных программ. Вместо того, чтобы пытаться самостоятельно анализировать абстрактное синтаксическое дерево (AST), мы можем сделать это с помощьюastexplorer.netВы можете увидеть AST, полученный разными парсерами после разбора js-кода онлайн, сайт помогает нам завершить преобразование, он позволяет нам ввести код JavaScript слева, а справа появится доступное для просмотра абстрактное синтаксическое дерево (AST). Мы можем использовать этот инструмент. Помогите понять и поэкспериментировать с некоторым кодом.

JavaScript AST visualizerAST можно визуализировать онлайн.

Обход дерева AST преобразованной структуры

{
    type:"ExpressionStatement",
    expression:{
        type:"CallExpression"
        callee:{
            type:"MemberExpression",
            computed:false
            object:{
                type:"Identifier",
                name:"codes"
            }
            property:{
                type:"Identifier",
                name:"map"
            }
            range:[]
        }
        arguments:{
            {
                type:"ArrowFunctionExpression",
                id:null,
                params:{
                    type:"Identifier",
                    name:"code",
                    range:[]
                }
                body:{
                    type:"BlockStatement"
                    body:{
                        type:"ReturnStatement",
                        argument:{
                            type:"CallExpression",
                            callee:{
                                type:"MemberExpression"
                                computed:false
                                object:{
                                    type:"Identifier"
                                    name:"code"
                                    range:[]
                                }
                                property:{
                                    type:"Identifier"
                                    name:"toUpperCase"
                                }
                                range:[]
                            }
                            range:[]
                        }
                    }
                    range:[]
                }
                generator:false
                expression:false
                async:false
                range:[]
            }
        }
    }
}

Мы начинаем с ExpressionStatement и переходим к древовидной структуре и видим, что ее внутренние свойства имеют callee, тип, аргументы, поэтому мы по очереди посещаем каждое свойство и его дочерние узлы.

Итак, существует следующая последовательность

进入  ExpressionStatement
进入  CallExpression
进入  MemberExpression
进入  Identifier
离开  Identifier
进入  Identifier
离开  Identifier
离开  MemberExpression
进入  ArrowFunctionExpression
进入  Identifier
离开  Identifier
进入  BlockStatement
进入  ReturnStatement
进入  CallExpression
进入  MemberExpression
进入  Identifier
离开  Identifier
进入  Identifier
离开  Identifier
离开  MemberExpression
离开  CallExpression
离开  ReturnStatement
离开  BlockStatement
离开  ArrowFunctionExpression
离开  CallExpression
离开  ExpressionStatement
离开  Program

Все этапы преобразования Babel — это обходы, подобные этому. (что-то вроде луковой модели коа??)

Трансформация АСТ

После анализа древовидной структуры мы вручную преобразуем стрелочную функцию.

При сравнении двух изображений разница обнаруживается в arguments.type двух функций.

Разобрать код
//babel核心库,用来实现核心的转换引擎
let babel = require('babel-core');
//可以实现类型判断,生成AST节点
let types = require('babel-types');
let code = `codes.map(code=>{return code.toUpperCase()})`;//转换语句
//visitor可以对特定节点进行处理
let visitor = {
    ArrowFunctionExpression(path) {//定义需要转换的节点,这里拦截箭头函数
        let params = path.node.params
        let blockStatement = path.node.body
        //使用babel-types的functionExpression方法生成新节点
        let func = types.functionExpression(null, params, blockStatement, false, false)
        //替换节点
        path.replaceWith(func) //
    }
}
//将code转成ast
let result = babel.transform(code, {
    plugins: [
        { visitor }
    ]
})
console.log(result.code)

Примечание: ArrowFunctionExpression() { ... } является сокращением от ArrowFunctionExpression: { enter() { ... } } .

Путь — это объект, представляющий соединение между двумя узлами.

шаг синтаксического анализа
  • Определите узлы, которые необходимо преобразовать
    ArrowFunctionExpression(path) {
        ......
    }
  • Создать узел для замены
types.functionExpression(null, params, blockStatement, false, false)

ссылка на документацию по типам babel

  • Найдите необходимые параметры на узле узла
  • заменить (заменить)

Написать плагин Babel

Начните с функции, которая принимает объект Babel в качестве параметра.

export default function(babel) {
  // plugin contents
}

Затем он возвращает объект, свойство посетителя которого является основным посетителем узла для этого плагина.

export default function({ types: t }) {
  return {
    visitor: {
      // visitor contents
    }
  };
};

Когда мы ежедневно внедряем зависимости, мы будем вводить весь пакет, что делает упакованный код слишком избыточным, добавляется много ненужных модулей, таких как index.js с тремя строками кода, а размер упакованного файла достигает 483 КиБ.

index.js

import { flatten, join } from "lodash";
let arr = [1, [2, 3], [4, [5]]];
let result = _.flatten(arr);

Итак, наша цель на этот раз состоит в том, чтобы

import { flatten, join } from "lodash";

Преобразовано так, что вводятся только два модуля lodash, что уменьшает размер упаковки.

import flatten from "lodash/flatten";
import join from "lodash/join";

Этапы реализации следующие:

  1. Создайте новую папку babel-plugin-extract в node_module под проектом

Примечание. Папка плагина babel определяется как имя плагина babel-plugin.

Мы можем добавить пользовательские плагины в плагин .babelrc или добавить пользовательские плагины в параметры загрузчика webpack.config.js.

  1. Создайте новый index.js в файле babel-plugin-extract.
module.exports = function ({types:t}) {
    return {
        // 对import转码
        visitor:{
            ImportDeclaration(path, _ref = { opts: {} }) {
                const specifiers = path.node.specifiers;
                const source = path.node.source;
                // 只有libraryName满足才会转码
                if (_ref.opts.library == source.value && (!t.isImportDefaultSpecifier(specifiers[0]))) { //_ref.opts是传进来的参数
                    var declarations = specifiers.map((specifier) => {      //遍历  uniq extend flatten cloneDeep
                        return t.ImportDeclaration(                         //创建importImportDeclaration节点
                            [t.importDefaultSpecifier(specifier.local)],
                            t.StringLiteral(`${source.value}/${specifier.local.name}`)
                        )
                    })
                    path.replaceWithMultiple(declarations)
                }
            }
        }
    };
}
  1. Измените элемент конфигурации babel-loader в webpack.prod.config.js и добавьте собственное имя плагина в plugins.
rules: [{
    test: /\.js$/,
    loader: 'babel-loader',
    options: {
        presets: ["env",'stage-0'],
        plugins: [
            ["extract", { "library":"lodash"}],
            ["transform-runtime", {}]
        ]
    }
}]

Примечание. Плагины плагинов используются по порядку, а пресеты — в обратном порядке. Таким образом, приведенный выше метод выполнения: Extract>transform-runtime>stage-0>env.

  1. Запустите webpack.config.js с введенным пользовательским плагином.

Размер файла пакета теперь составляет 21,4 КБ, что значительно уменьшено, и пользовательский плагин работает успешно! ~

директория с файлами плагинов

YUAN-PLUGINS
|
| - node_modules
|   |
|   | - babel-plugins-extract
|           |
|           index.js
|   
| - src
|   | - index.js
|
| - webpack.config.js

Если вы думаете, что это весело, пожалуйста, обратите внимание ~ Добро пожаловать, чтобы собрать и написать комментарий ~~~

Объявление о вакансии

ByteDance набирает сотрудников!

Описание вакансии: Front-end development (senior) ToB направление - видео облако (База: Шанхай, Пекин)

1. Отвечает за производство мультимедийных услуг, таких как аудио и видео по запросу / прямая трансляция / общение в реальном времени и создание облачных платформ для бизнеса;

2. Отвечает за мультимедийную систему качества, эксплуатацию и техническое обслуживание, построение и развитие системы;

3. Хорошо разбирается в абстрактном дизайне, инженерном мышлении, фокусируется на взаимодействии и создает максимальный пользовательский опыт.

Профессиональные требования

1. Компьютеры, связь и электронная информатика и другие смежные специальности являются предпочтительными;

2. Владение различными фронтенд-технологиями, включая HTML/CSS/JavaScript/Node.js и т. д.;

3. Глубокое понимание языка JavaScript с использованием основных сред разработки, таких как React или Vue.js;

4. Приветствуется знание Node.js, понимание Express/KOA и других фреймворков, а также опыт разработки крупномасштабных серверных программ;

5. Иметь определенное представление о пользовательском опыте, интерактивной работе и анализе потребностей пользователей, а также иметь опыт разработки продуктов или интерфейсов;

6. Предпочтение отдается участникам со своими собственными техническими продуктами, работами с открытым исходным кодом или активным сообществом с открытым исходным кодом.

Основные моменты работы

Команда видеооблачных сервисов опирается на накопленные аудио- и видеотехнологии и базовые ресурсы Douyin, Xigua Video и других продуктов, чтобы предоставлять клиентам универсальные аудио- и видеомультимедийные услуги, включая аудио- и видеопо запросу, прямую трансляцию, реальную связь времени, обработка изображений и т. д. Внутренне, как центр видеотехнологий, он обслуживает внутренний бизнес; снаружи он создает готовые аудио- и видео-мультимедийные сервисные решения для обслуживания пользователей корпоративного уровня.

У команды есть стандартизированный процесс итерации проекта и идеальная конфигурация ролей проекта; сильная техническая атмосфера, охватывает сообщество открытого исходного кода и регулярно делится, так что каждый может быстро расти вместе с бизнесом и использовать технологии, чтобы изменить мир!

способ доставки

Резюме можно отправлять напрямую по адресу:yuanyuan.wallace@bytedance.com

Вы также можете отсканировать внутренний QR-код для доставки онлайн, с нетерпением жду вашего присоединения! ~