Сейчас мы вообще не реализуем весь код сами, а в основном разрабатываем его на основе сторонних пакетов, что отражено в каталогах src и node_modules.
Пропорции src и node_modules (сторонних пакетов) варьируются от проекта к проекту.
Способ выполнения заглядывает в сторонние пакеты, также отличается:
- В среде Node поиск Node_Modules поддерживается во время работы. Поэтому просто разверните раздел SRC, а затем установите соответствующие зависимости.
- node_modules не поддерживаются в среде браузера, их необходимо упаковать в форму, поддерживаемую браузером.
В кросс-терминальной среде, что из перечисленного выше?
Нет, реализация разных кросс-энд движков будет разная, кросс-энд движки будут реализовывать require, который может находить модули (встроенные и сторонние) во время выполнения, но это не способ поиска узлов, а его собственный набор.
Это похоже на поиск модуля в среде узла, но структура каталогов отличается, поэтому вам нужно реализовать установку xxx самостоятельно.
Анализ мыслей
npm имеет собственный сервер реестра для поддержки загрузки пакетов выпуска, которые загружаются с сервера реестра. Если мы реализуем его сами, нет необходимости реализовывать этот набор, просто используйте git clone для загрузки исходного кода с gitlab.
Анализ зависимостей
Чтобы выполнить загрузку, вы должны сначала определить, что загружать, и способ определения зависимостей отличается от способа для инструментов упаковки:
- Инструмент упаковки определяет зависимости с помощью AST-анализа содержимого файлов и пакетов.
- Инструмент установки зависимостей определяет зависимости через объявленные пользователем файлы зависимостей (package.json/bundle.json) и устанавливает их
Здесь мы вызываем файл описания пакета bundle.json, в котором объявляются зависимые пакеты:
{
"name": "xxx",
"dependencies": {
"yyyy": "aaaa/bbbb#release/1111"
}
}
Проанализировав файл bundle.json в корневом каталоге проекта в качестве записи, загрузите каждую зависимость, проанализируйте файл bundle.json, а затем продолжите загрузку каждой зависимости, рекурсивно выполняя этот процесс. Это процесс анализа зависимостей.
Таким образом, загрузка, анализ зависимостей завершается, и загрузка пакета окончена. Это осуществимая идея.
Но есть проблемы с таким образом мышления, например: как насчет конфликтов версий? Как насчет циклических зависимостей?
Разрешен конфликт
Конфликты версий более зависят от пакета с пакетом, но полагаются на разные версии, на этот раз мы должны выбрать версию для установки, мы можем просто установить правила для использования высокой версии этого.
Мы решили конфликты версий и циклические зависимости, есть ли другие проблемы?
Когда есть конфликт версий, будет загружен пакет с самой высокой версией, но в настоящее время в предыдущей версии пакета была загружена в это время, поэтому будет ненужные загрузки. Может ли эта часть избыточной скачивания быть удалена?
Анализ зависимостей и разделение загрузки
Причина загрузки большего количества пакетов более низких версий заключается в том, что мы скачали их в процессе анализа зависимостей.Можем ли мы загрузить только bundle.json для анализа во время анализа зависимостей, а затем загрузить зависимости пакетами после анализа и определения графа зависимостей?
Скачивание только файла bundle.json с гитлаба нужно качать по протоколу ssh, это немного сложно, можно реализовать более простой идеей:
git clone --depth=1 --branch=bb xxx
После добавления --depth git clone будет загружать только один коммит, и скорость будет очень высокой.Хотя это не так хорошо, как загрузка только bundle.json, его все же можно использовать (я пытался загрузить все коммиты, когда это заняло 20 с, а загрузка одного коммита заняла всего 1 с.).
Таким образом, мы загружаем только один коммит во временный каталог во время анализа зависимостей, анализируем зависимости, разрешаем конфликты и определяем граф зависимостей, а затем загружаем в пакетах.В это время используйте git clone для загрузки всех коммитов. Наконец, удалите временный каталог.
Таким образом, разделив анализ зависимостей и загрузку, мы удаляем ненужные загрузки низкоуровневых пакетов. Скорость загрузки немного увеличится.
Глобальный кеш
При наличии нескольких локальных проектов каждый проект загружает свои зависимые пакеты независимо друг от друга, поэтому для некоторых общих пакетов будут повторяться загрузки.Решение заключается в глобальном кэшировании.
Проанализировав зависимости и загрузив каждый зависимый пакет, сначала проверьте, существует ли этот пакет глобально.Если он существует, скопируйте его напрямую и получите последний код. Если нет, сначала загрузите в глобальный, а затем скопируйте в локальный каталог.
Добавив уровень глобального кэширования, мы добились повторного использования пакетов зависимостей между проектами.
Код
Для ясности мысли ниже будет написан псевдокод
Анализ зависимостей
Анализ зависимостей рекурсивно обрабатывает Bundle.json, анализируют зависимости и загружают их в временный каталог и записывают анализируемые зависимости. Это разрешит версию конфликтов и круговых зависимостей.
const allDeps = {};
function installDeps(projectDir) {
const bundleJsonPath = path.resolve(projectDir, 'bundle.json');
const bundleInfo = JSON.parse(fs.readFileSync(bundleJsonPath));
const bundleDeps = bundleInfo.dependencies;
for (let depName in bundleDeps) {
if(allDeps[depName]) {
if (allDeps[depName] 和 bundleDeps[depName] 分支和版本一样) {
continue;// 跳过安装
}
if (allDeps[depName] 和 bundleDeps[depName] 分支和版本不一样){
if (bundleDeps[depName] 版本 < allDeps[depName] 版本 ) {
continue;
} else {
// 记录下版本冲突
allDeps[depName].conflit = true;
}
}
}
childProcess.exec(`git clone --depth=1 ${临时目录/depName}`);
allDeps[depName] = {
name: depName
url: xxx
branch: xxx
version: xxx
}
installDeps(`${临时目录/depName}`);
}
}
скачать
Загрузка будет основана на зависимостях пакетной загрузки allDeps, проанализированных выше, сначала загруженных в глобальный каталог кеша, а затем скопированных в локальный.
function batchInstall(allDeps) {
allDeps.forEach(dep => {
const 全局目录 = path.resolve(os.homedir(), '.xxx');
if (全局目录/dep.name 存在) {
// 复制到本地
childProcess.exec(`cp 全局目录/dep.name 本地目录/dep.name`);
} else {
// 下载到全局
childProcess.exec(`git clone --depth=1 ${全局目录/dep.name}`);
// 复制到本地
childProcess.exec(`cp 全局目录/dep.name 本地目录/dep.name`);
}
});
}
Таким образом, мы завершили анализ и загрузку зависимостей и реализовали глобальный кеш.
Суммировать
Сначала мы разобрались, как разные среды (браузер, узел, кросс-энд движок) по-разному работают со сторонними пакетами. но мы используем собственный набор механизмов реализации.
Тогда четкие инструменты упаковки определяются иждивенцевым способом анализа AST, но зависит инструмент загрузки основан на файлах описания пакета Bundl.json (package.json) для анализа. Затем мы реализовали рекурсивный анализ зависимостей, решая версию конфликтов, круговые зависимости.
Чтобы уменьшить ненужные загрузки, мы разделяем анализ зависимостей и загрузка. На этапе анализа зависимостей загружается только один коммит, и все последующие партии загружаются. Способ загрузки не реализует набор реестра, но непосредственно из GitLab в GIT клон.
Во избежание дублирования загруженных более зависимых от общественных проектов, мы достигли глобального кеша, сначала загружайте в глобальный каталог, а затем скопируйте локально.
npm install, реализовать детали процесса установки пряжи будет больше, но похоже на общий процесс. Надеюсь, эта статья поможет вам разобраться в четких идеях: как работать с разными средами — это сторонний пакет, анализ зависимостей и загружаемый процесс установки xxx — вот что.