предисловие
TaroЭто многотерминальная унифицированная среда разработки, созданная Bump Labs и соответствующая спецификации синтаксиса React.
Используя Taro, мы можем написать только один набор кода, а затем использовать инструмент компиляции Taro для отдельной компиляции исходного кода в коды, которые можно запускать на разных сторонах (апплет WeChat, H5, сторона приложения и т. д.). выполнитьНапиши один раз, запускай много. Более подробную информацию о Таро можно найти в официальной вводной статье.Таро - мультитерминальная среда разработки, или сразу перейдите в репозиторий GitHubNervJS/taroОзнакомьтесь с документацией Taro и сопутствующими материалами.
У проекта Taro мощные функции, а проект сложный и огромный, включающий множество аспектов (многотерминальное преобразование кода, компоненты, маршрутизация, управление состоянием, жизненный цикл, реализация и совместимость возможностей терминала и т.д.), для большинства людей, хочу Трудно глубоко понять механизм и принцип его реализации.
Taro 技术揭秘
Серия статей постепенно раскроет тайну могущественных функций Таро, позволит вам погрузиться вглубь Таро и понять, как шаг за шагом реализуется Таро.Напиши один раз, запускай многоВ то же время я также надеюсь воспользоваться этой возможностью, чтобы привлечь других и способствовать появлению большего количества проектов с открытым исходным кодом в кругу переднего плана, которые могут решить болевые точки каждого.
Во-первых, мы начнем с инструмента командной строки, отвечающего за инициализацию строительных лесов Taro и построение проекта, который является точкой входа в Taro:@tarojs/cliНачинать.
пакет таро-кли
команда таро
Пакет таро-кли находится по адресуTaroВ каталоге пакетов проекта перейдитеnpm install -g @tarojs/cli
При глобальной установке будет сгенерирована команда таро. В основном отвечает за инициализацию проекта, компиляцию, построение и т. д. Введите таро прямо в командной строке, и вы увидите следующее приглашение:
➜ taro
👽 Taro v0.0.63
Usage: taro <command> [options]
Options:
-V, --version output the version number
-h, --help output usage information
Commands:
init [projectName] Init a project with default templete
build Build a project with options
update Update packages of taro
help [cmd] display help for [cmd]
Здесь вы можете подробно увидеть использование и функции команды таро.
Управление пакетами и публикация
Во-первых, нам нужно понять взаимосвязь между пакетом taro-cli и проектом таро.
После клонирования проекта Taro мы видим, что структура каталогов проекта выглядит следующим образом, и в целом все относительно просто и понятно.
.
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build
├── docs
├── lerna-debug.log
├── lerna.json // Lerna 配置文件
├── package.json
├── packages
│ ├── eslint-config-taro
│ ├── eslint-plugin-taro
│ ├── postcss-plugin-constparse
│ ├── postcss-pxtransform
│ ├── taro
│ ├── taro-async-await
│ ├── taro-cli
│ ├── taro-components
│ ├── taro-components-rn
│ ├── taro-h5
│ ├── taro-plugin-babel
│ ├── taro-plugin-csso
│ ├── taro-plugin-sass
│ ├── taro-plugin-uglifyjs
│ ├── taro-redux
│ ├── taro-redux-h5
│ ├── taro-rn
│ ├── taro-rn-runner
│ ├── taro-router
│ ├── taro-transformer-wx
│ ├── taro-weapp
│ └── taro-webpack-runner
└── yarn.lock
TaroПроект в основном состоит из серии пакетов npm, которые расположены в каталоге пакетов проекта. его управление пакетами иBabelКак и проект, весь проект управляется как монорепозиторий, а также используется инструмент управления пакетами.Lerna.
Lerna – это инструмент управления, используемый для оптимизации рабочего процесса кодовых баз с несколькими пакетами, размещенных на git/npm. Он позволяет вам управлять несколькими подпроектами в рамках основного проекта, тем самым устраняя необходимость зависимости нескольких пакетов друг от друга и необходимости быть освобождены при публикации Проблемы с ручным обслуживанием нескольких пакетов.
Более подробную информацию о Lerna можно найти в официальной документации.Lerna: инструмент для управления проектами JavaScript с несколькими пакетами..
Среди более чем дюжины пакетов в каталоге пакетов наиболее часто используемые инструменты командной строки для инициализации и построения проектаtaro-cliявляется одним из них. Запуск из корневого каталога проекта Tarolerna publish
После команды,lerna.json
Все настроенные в нем пакеты будут опубликованы в npm.
Структура каталогов
Структура каталогов пакета taro-cli выглядит следующим образом:
./
├── bin // 命令行
│ ├── taro // taro 命令
│ ├── taro-build // taro build 命令
│ ├── taro-update // taro update 命令
│ └── taro-init // taro init 命令
├── package.json
├── node_modules
├── src
│ ├── build.js // taro build 命令调用,根据 type 类型调用不同的脚本
│ ├── config
│ │ ├── babel.js // Babel 配置
│ │ ├── babylon.js // JavaScript 解析器 babylon 配置
│ │ ├── browser_list.js // autoprefixer browsers 配置
│ │ ├── index.js // 目录名及入口文件名相关配置
│ │ └── uglify.js
│ ├── creator.js
│ ├── h5.js // 构建h5 平台代码
│ ├── project.js // taro init 命令调用,初始化项目
│ ├── rn.js // 构建React Native 平台代码
│ ├── util // 一系列工具函数
│ │ ├── index.js
│ │ ├── npm.js
│ │ └── resolve_npm_files.js
│ └── weapp.js // 构建小程序代码转换
├── templates // 脚手架模版
│ └── default
│ ├── appjs
│ ├── config
│ │ ├── dev
│ │ ├── index
│ │ └── prod
│ ├── editorconfig
│ ├── eslintrc
│ ├── gitignore
│ ├── index.js // 初始化文件及目录,copy模版等
│ ├── indexhtml
│ ├── npmrc
│ ├── pagejs
│ ├── pkg
│ └── scss
└── yarn-error.log
Добавлена функция ключевых файлов с аннотациями, вы можете сначала взглянуть на них, чтобы составить предварительное впечатление.
Как видно из приведенного выше дерева каталогов, в проекте taro-cli не так много файлов, основные каталоги:/bin
,/src
,/template
, выше я подробно отметил функции основных директорий и файлов, а что касается конкретного процесса, то его мы разберем далее.
используемая основная библиотека
- tj/commander.js Node.jsКомплексное решение с интерфейсом командной строки, вдохновленное Ruby.commander. Он может автоматически анализировать команды и параметры, комбинировать несколько параметров, обрабатывать короткие параметры и т. д. Он мощный и простой в использовании.
- jprichardson/node-fs-extraДобавлены некоторые новые методы на основе фс нодджей, которые проще в использовании, а также могут копировать шаблоны.
- chalk/chalkМожет использоваться для управления стилем выходной строки терминала.
- SBoudrias/Inquirer.jsИнтерактивный инструмент командной строки NodeJ, набор общих пользовательских интерфейсов командной строки для взаимодействия с пользователями.
- sindresorhus/oraКогда указано состояние загрузки, как может хватить загрузки, а потом добавить перед ним маленький кружок и перевернуть.Если консоль удачная, то как успеха может хватить?Можно еще добавить маленький крючок в перед ним, что и делает ora.
- SBoudrias/mem-fs-editorПредоставляет ряд API для облегчения работы с файлами шаблонов.
- shelljs/shelljsShellJS — это расширение Node.js для реализации выполнения команд оболочки Unix.
- Node.js child_processМодули используются для создания новых дочерних процессов. Результат выполнения дочернего процесса сохраняется в системном кеше (максимум 200 КБ).После завершения выполнения дочернего процесса основной процесс использует функцию обратного вызова для чтения результата выполнения дочернего процесса.
taro init
Основной процесс команды taro init выглядит следующим образом:
ввод команды таро
Когда мы устанавливаем пакет taro-cli глобально, в нашей командной строке появляется еще одна команда taro.
$ npm install -g @tarojs/cli
Так как же добавляется команда таро?package.json
внутри поля корзины;
"bin": {
"taro": "bin/taro"
},
Приведенный выше код указывает, что исполняемый файл, соответствующий команде taro, — bin/taro. npm будет искать этот файл в[prefix]/bin
Создайте символическую ссылку в каталоге. В приведенном выше примере таро создаст символическую ссылку[prefix]/bin/taro
. так как[prefix]/bin
Каталог будет добавлен в системную переменную PATH во время выполнения, поэтому при запуске npm вы можете вызывать эти скрипты напрямую через команды без пути.
оprefix
, в состоянии пройтиnpm config get prefix
Получать.
$ npm config get prefix
/usr/local
Символические связи между ними можно увидеть более четко с помощью следующих команд:
$ ls -al `which taro`
lrwxr-xr-x 1 chengshuai admin 40 6 15 10:51 /usr/local/bin/taro -> ../lib/node_modules/@tarojs/cli/bin/taro
подкоманда таро
Выше мы уже знаем, как команда taro работает с пакетом taro-cli после его установки./bin/taro
файлы связаны, так как же taro init и taro build связаны с соответствующими файлами?
Ассоциация команд и анализ параметров
Здесь я должен упомянуть полезный пакет:tj/commander.js Node.jsКомплексное решение с интерфейсом командной строки, вдохновленное Ruby.commander. Он может автоматически анализировать команды и параметры, комбинировать несколько параметров, обрабатывать короткие параметры и т. д. Он мощный и простой в использовании. Для конкретного метода использования, пожалуйста, обратитесь к README проекта.
Что еще более важно, Commander поддерживает обработку подкоманд в стиле git и может автоматически направлять к файлу выполнения команды, названному в определенном формате в соответствии с подкомандой.[command]-[subcommand]
,Например:
taro init => taro-init
taro build => taro-build
/bin/taro
Содержимого файла не так много, а основной код — это только те строки.command()
Заказ:
#! /usr/bin/env node
const program = require('commander')
const {getPkgVersion} = require('../src/util')
program
.version(getPkgVersion())
.usage('<command> [options]')
.command('init [projectName]', 'Init a project with default templete')
.command('build', 'Build a project with options')
.command('update', 'Update packages of taro')
.parse(process.argv)
командный метод
использование:.command('init <path>', 'description')
Использование команды немного сложнее, в принципе, она может принимать три параметра, первый - это определение команды, второй - описание команды, а третий - объект вспомогательного оформления команды.
- Вы можете использовать или [] для изменения параметров команды в первом параметре.
- Второй параметр является необязательным.
- Когда второй параметр отсутствует, command.js вернет объект Command, если есть второй параметр, он вернет объект-прототип.
- Когда action(fn) вызывается со вторым параметром, а action(fn) не вызывается явно, он будет использоватьсяподкомандный режим.
- Так называемый режим подкоманды,
./pm
,./pm-install
,./pm-search
Ждать. Эти подкоманды находятся в отдельных файлах от основной команды.
- Третий параметр обычно не используется, он может установить, следует ли отображать использование подкомандного режима.
Обратите внимание на первую строку
#!/usr/bin/env node
, есть ключевое слово под названиемShebang, если вы не понимаете, вы можете пойти в Сосо.
Парсинг параметров и взаимодействие с пользователями
Как упоминалось ранее, пакет command может автоматически анализировать команды и параметры, а после настройки команд он также может автоматически генерировать команды справки (help) и команды версии (view версии). и черезprogram.args
Вы можете получить параметры командной строки, а затем вызывать разные скрипты в соответствии с параметрами.
но когда мы бежимtaro init
Как после команды достигается взаимодействие с командной строкой, как показано ниже?
$ taro init taroDemo
Taro即将创建一个新项目!
Need help? Go and open issue: https://github.com/NervJS/taro/issues/new
Taro v0.0.50
? 请输入项目介绍!
? 请选择模板 默认模板
используется здесьSBoudrias/Inquirer.jsдля обработки взаимодействия с командной строкой.
Использование на самом деле очень простое:
const inquirer = require('inquirer') // npm i inquirer -D
if (typeof conf.description !== 'string') {
prompts.push({
type: 'input',
name: 'description',
message: '请输入项目介绍!'
})
}
prompt()
Принять данные объекта вопроса, сохранить ввод пользователя в объекте ответа во время взаимодействия между пользователем и терминалом, а затем вернутьPromise
,пройти черезthen()
Получите этот объект ответа. так легко!
Таким образом, такая информация, как имя, номер версии, описание и другая информация о новом проекте, может быть непосредственно вставлена в шаблон проекта через терминальное взаимодействие для улучшения процесса взаимодействия.
Конечно, интерактивная задача этим не ограничивается, и вы можете добавить больше интерактивных задач в зависимости от ситуации в вашем собственном проекте. Сила inquirer.js заключается в том, что он поддерживает множество типов взаимодействий, помимо простыхinput
,иconfirm
,list
,password
,checkbox
и т. д. Для получения подробной информации обратитесь к технической документации проекта.README.
Кроме того, вы все еще находитесь в процессе выполнения асинхронной операции, вы также можете использоватьsindresorhus/oraДобавим эффект загрузки. использоватьchalk/chalkДобавляйте различные стили в вывод терминала.
Операции с файлами шаблонов
Наконец, работа с файлом шаблона в основном делится на две части:
- Вставьте ввод в шаблон
- Создайте соответствующую структуру каталогов по команде, скопируйте файл
- Обновить содержимое существующего файла
Эти операции в основном/template/index.js
в файле.
Также используется здесьshelljs/shelljsВыполнение сценариев оболочки, таких как инициализация gitgit init
, установить зависимости после инициализации проектаnpm install
Ждать.
скопировать файл шаблона
Копирование файлов шаблонов в основном используетсяjprichardson/node-fs-extraизcopyTpl()
метод, этот метод используетejs
Синтаксис шаблона, вы можете вставить входное содержимое в соответствующую позицию шаблона:
this.fs.copyTpl(
project,
path.join(projectPath, 'project.config.json',
{description,projectName}
);
Обновить содержимое существующего файла
Обновление содержимого существующего файла — сложная работа, самый надежный способ — разобрать файл какAST
, а затем отредактируйте. некоторые популярныеAST parser
включают:
-
Cheerio
: разборHTML
. -
Babylon
: разборJavaScript
. - за
JSON
файл, используйте роднойJSON
объектный метод.
использоватьRegex
Разбор кодового файла - это зло, не делай этого, не принимайте шансов.
taro build
taro build
Команда — это душа и ядро всего проекта Таро, в основном отвечающая заМноготерминальная компиляция кода(h5, апплет, React Native и т. д.).
ассоциация команд таро, анализ параметров и т. д. иtaro init
На самом деле это точно так же, так как же реализована самая важная часть преобразования кода?
Эта часть содержания слишком велика, и ее нужно вытащить в виде отдельной лекции. Но здесь кратко упоминается.
Рабочий процесс компиляции и абстрактное синтаксическое дерево (AST)
Основная часть Taro — это компиляция кода в код другой стороны (H5, апплет, React Native и т. д.). В общем, компиляция кода на одном структурированном языке в код на другом аналогичном структурированном языке включает следующие шаги:
Первый — парсинг, код解析(Parse)
стать抽象语法树(Abstract Syntex Tree)
, а затем выполните AST遍历(traverse)
и替换(replace)
(Это не чуждо фронтенду, это можно сравнить с работой DOM-дерева), и наконец生成(generate)
, который генерирует скомпилированный код из нового AST.
Вавилонские модули
Babel — универсальныйJavaScript 编译器
, точнее компилятор исходного кода, также обычно называемый转换编译器(transpiler)
. Это означает, что вы предоставляете Babel некоторый код JavaScript, Babel изменяет этот код и возвращает вам вновь сгенерированный код.
Кроме того, он имеет множество модулей для различных форм静态分析
.
Статический анализ — это процесс анализа кода без выполнения кода (анализ кода во время его выполнения — это динамический анализ). Назначение статического анализа разнообразно, его можно использовать для проверки синтаксиса, компиляции, подсветки кода, преобразования кода, оптимизации, сжатия и так далее.
Babel на самом деле представляет собой набор модулей и имеет огромную экологию. Раздел компиляции кода проекта Taro основан на следующих модулях Babel:
- babylonВавилон — это парсер Бабеля. Первоначально разветвлен от проекта Acorn. Acorn очень быстрый, простой в использовании и имеет архитектуру на основе плагинов, предназначенную для нестандартных функций (и тех, которые станут стандартными в будущем).
- babel-traverseМодуль Babel Traverse поддерживает состояние всего дерева и отвечает за замену, удаление и добавление узлов.
- babel-typesМодуль Babel Types — это библиотека инструментов в стиле Lodash для узлов AST, содержащая методы построения, проверки и преобразования узлов AST. Библиотека инструментов содержит продуманные методы инструментов, которые полезны для написания логики для обработки AST.
- babel-generatorМодуль Babel Generator — это генератор кода Babel, который считывает AST и преобразует его в код и исходные карты.
- babel-templatebabel-template — еще один небольшой, но очень полезный модуль. Он позволяет писать строковый код с заполнителями вместо ручного кодирования, особенно при создании крупномасштабных AST. В информатике эта способность называется квазикавычками.
Разобрать конфигурацию страницы
В процессе компиляции бизнес-кода в код апплета одним из шагов является анализ атрибута конфигурации записи страницы js и запись его в*.json
файл для использования апплетом. Так как же достигается этот шаг?Здесь извлекается ключевой код этой части функции:
// 1. babel-traverse方法, 遍历和更新节点
traverse(ast, {
ClassProperty(astPath) { // 遍历类的属性声明
const node = astPath.node
if (node.key.name === 'config') { // 类的属性名为 config
configObj = traverseObjectNode(node)
astPath.remove() // 将该方法移除掉
}
}
})
// 2. 遍历,解析为 JSON 对象
function traverseObjectNode(node, obj) {
if (node.type === 'ClassProperty' || node.type === 'ObjectProperty') {
const properties = node.value.properties
obj = {}
properties.forEach((p, index) => {
obj[p.key.name] = traverseObjectNode(p.value)
})
return obj
}
if (node.type === 'ObjectExpression') {
const properties = node.properties
obj = {}
properties.forEach((p, index) => {
// const t = require('babel-types') AST 节点的 Lodash 式工具库
const key = t.isIdentifier(p.key) ? p.key.name : p.key.value
obj[key] = traverseObjectNode(p.value)
})
return obj
}
if (node.type === 'ArrayExpression') {
return node.elements.map(item => traverseObjectNode(item))
}
if (node.type === 'NullLiteral') {
return null
}
return node.value
}
// 3. 写入对应目录的 *.json 文件
fs.writeFileSync(outputPageJSONPath, JSON.stringify(configObj, null, 2))
Из комментариев к приведенному выше коду ясно видно, что с помощью трех вышеуказанных шагов конфигурация конфигурации в проекте может быть преобразована в файл конфигурации json, соответствующий апплету.
Однако даже эту небольшую функциональную точку реализовать не так просто, к тому же нужно учитывать большое количество реальных бизнес-сценариев и экстремальных ситуаций:
- Должны ли конфигурации для записи приложения app.js и записи страницы index.js обрабатываться отдельно?
- Как преобразовать конфигурацию tabBar и обеспечить согласованное функционирование и взаимодействие?
- Как подсказать, если информация о конфигурации пользователя неверна?
Больше контента, связанного с компиляцией кода, или поместите его в следующую статью.
Суммировать
Уже,taro-cli
Основная структура каталогов, вызов команд, метод инициализации проекта и т. д. в основном завершены.Заинтересованные студенты могут самостоятельно следить за исходным кодом проекта, это не должно быть слишком сложно.
taro-cli
В настоящее время шаблон размещен в проекте, и леса должны обновляться синхронно при каждом обновлении шаблона. иvue-cliОн заключается в том, чтобы поместить шаблон проекта в git, а затем загрузить различные шаблоны в соответствии с взаимодействием с пользователем при запуске и отобразить их через механизм шаблонов для создания проекта. Таким образом, шаблон и каркас можно разделить, чтобы их можно было поддерживать отдельно.Даже если шаблон изменится, необходимо загрузить только последний шаблон, и можно создать последний проект, не требуя от пользователя обновления каркаса. . Это было включено в объем последующей оптимизации.
В следующей статье мы вместе войдем в мир составления кода Таро.