Упаковка проектов ThinkJS с помощью pkg

Node.js ThinkJS
Упаковка проектов ThinkJS с помощью pkg

В группе пользователей ThinkJS разработчики часто выдвигают необходимость шифрования и защиты исходного кода. Мы знаем, что JavaScript — это динамический язык, в отличие от других статических языков, которые можно компилировать в бинарные пакеты для предотвращения утечки исходного кода. Так оно и появилосьpkg,nexeТакие инструменты поддерживают упаковку JS-кода вместе с Node в исполняемый файл, что, во-первых, решает проблему зависимости от окружения, а во-вторых, решает волнующую всех проблему защиты исходного кода.

существуетpkgВ README модуля перечислены несколько основных его применений.Если у вас есть следующие требования, рекомендуется попробовать его.

  • Предоставление коммерческих дистрибутивов для приложений без раскрытия исходного кода
  • Предоставьте демонстрацию приложения, не раскрывая исходный код
  • Упаковка всех исполняемых файлов платформы одним щелчком мыши без необходимости в соответствующих зависимостях от среды платформы.
  • Предлагает самоизвлекающиеся или самоустанавливающиеся решения
  • Запуск приложения не требует установки Node.js и npm.
  • Для развертывания требуется только один файл, не нужно устанавливать множество зависимостей через npm.
  • После упаковки ресурсов приложение удобнее мигрировать
  • Протестировать приложение под указанной версией Node.js без установки соответствующей версии

как пользоваться

Об основном использовании модуля pkg вы можете узнать«Запускайте свои программы NodeJS для людей, у которых нет NodeJS»Эта статья. пройти черезnpm install -g pkgПосле того, как модуль установлен глобально, его можно использовать из командной строки.pkgзаказ.pkgВ дополнение к поддержке указания параметров в командной строке, он также поддерживаетpackage.jsonв конфигурации.

{
  ...
  "bin": "production.js",
  "scripts": {
    "pkg": "pkg . --out-path=dist/"
  },
  "pkg": {
    "scripts": [...]
    "assets": [...],
    "targets": [...]
  },
  ...
}

Выше приведена простая конфигурация.binИспользуется для указания окончательного упакованного файла записи,pkg.scriptsа такжеpkg.assetsИспользуется для указания того, что необходимо упаковать в исполняемый файл в дополнение к файлу входа, где первый используется для указания других.jsфайл, последний используется для указания не-.jsресурс из.pkg.targetsОн используется для указания платформы, которую необходимо упаковать.Структура имени платформы выглядит следующим образом:node${version}-${platform}-${arch}.versionИспользуется для указания версии конкретного узла,platformИспользуется для указания платформы компиляции, может бытьfreebsd, linux, alpine, macosилиwin,наконецarchИспользуется для указания архитектуры платформы компиляции, которую можноx64, x86, armv6илиarmv7. Напримерnode10-macos-x64На базе Node 10 представлена ​​упакованная исполняемая программа, исполняемая на платформе MacOS.scripts, assetsа такжеtargetsОба поддерживают несколько конфигураций массива.

После настройки входного файла, зависимых сценариев и ресурсов, а также платформы для компиляции выполнитеnpm run pkgдля завершения компиляции.

Как упаковать ThinkJS

pkgПринцип, вероятно, состоит в том, чтобы предоставить виртуальную файловую систему, которая будет__filename, __dirnameи другие переменные, а метод операции ввода-вывода в официальном API, который указывает на локальную файловую систему, изменен, чтобы указывать на виртуальную систему. Сжатый и упакованный исходный код программы считывается через виртуальную файловую систему, чтобы обеспечить среду для выполнения сценария. Следует отметить, что виртуальная файловая система доступна только для чтения, поэтому, если программа имеет__dirnameСледует избегать метода выполнения операций чтения и записи.

предварительная обработка кода

В проекте ThinkJS будет два следующих места для операций записи файлов:

  1. После запуска проекта будетruntime/config/${env}.jsonЗапишите окончательный файл конфигурации под
  2. По умолчанию в производственной средеlogs/Запись онлайн-журналов в каталог

Эти каталоги по умолчанию основаны на текущей папке проекта, поэтому их следует избегать, основываясь на предыдущей теории.pkgизREADMEскажи намprocess.cwd()Он по-прежнему будет указывать на реальную среду, поэтому мы можем изменить расположение указанного выше каталога наprocess.cwd()Для решения этой проблемы.

//pkg.js
const path = require('path');
const Application = require('thinkjs');

const instance = new Application({
  //在启动文件中可以自定义配置 runtime 目录
  RUNTIME_PATH: path.join(process.cwd(), 'runtime'), 
  ROOT_PATH: __dirname,
  proxy: true,
  env: 'pkg',
});

instance.run();

на основеproduction.jsмы создаем новыйpkg.jsФайл запуска, который определяет проект после запускаRUNTIME_PATHпуть, иenvназначить какpkg, что удобно передать в последующей конфигурацииthink.env === 'pkg'для переключения конфигурации.

//src/config/adapter.js
const {Console, DateFile} = require('think-logger3');
const isDev = think.env === 'development';
const isPkg = think.env === 'pkg';
exports.logger = {
  type: isDev ? 'console' : 'dateFile',
  console: {
    handle: Console
  },
  dateFile: {
    handle: DateFile,
    level: 'ALL',
    absolute: true,
    pattern: '-yyyy-MM-dd',
    alwaysIncludePattern: true,
    filename: path.join(isPkg ? process.cwd() : think.ROOT_PATH, 'logs/app.log')
  }
};

В конфигурации адаптера мы основываем оригиналthink.ROOT_PATHПуть изменен, чтобы основываться наprocess.cwd(). В дополнение к службам журнала, если есть служба, такая как кеш и сеанс, если она также основана на хранилище файлов, им также необходимо изменить соответствующую конфигурацию хранилища файлов. Конечно, это некоторые из сервисов, поставляемых с THINKJS, если вы используете какие-то другие сервисы в своем проекте или вам нужно изменить файл в своей бизнес-логике.

Конфигурация упаковки

После того, как операция записи проекта будет предотвращена, мы можем нормально настроить pkg, а затем упаковать его. Простая конфигурация модуля pkg выглядит так:

//package.json
{
  "bin": "pkg.js",
  "pkg": {
    "assets": [
      "src/**/*",
      "view/**/*",
      "www/**/*"
    ],
    "targets": [
      "node10-linux-x64",
      "node10-macos-x64",
      "node10-win-x64"
    ]
  }
}

Здесь мы указываемpkg.jsДля упакованного входного файла укажите необходимость компиляцииlinux, macos, winИсполняемые скрипты для трех платформ, при указанииsrc/, view/, www/Три каталога упакованы как ресурс. Это связано с тем, что ThinkJS — это проект с динамическими требованиями, и конкретная бизнес-логика загружается в виде чтения файлов путем обхода файлового каталога во время выполнения.pkgДля упаковки модуля эти зависимости не могут быть известны во время компиляции, поэтому их необходимо упаковать как «ресурсы» зависимостей запуска.

После настройки выполните его прямо в каталоге проекта.pkg ., если все в порядке, вы должны увидеть три исполняемых файла в текущем каталоге и напрямую выполнить двоичный файл соответствующей платформы для запуска службы.

➜  www.thinkjs.org git:(master) npm run pkg-build

> thinkjs-official@1.2.0 pkg-build /Users/lizheming/workspace/thinkjs/www.thinkjs.org
> pkg ./ --out-path=dist

> pkg@4.4.0
➜  www.thinkjs.org git:(master) ✗ ls -alh dist
total 577096
drwxr-xr-x   5 lizheming  staff   160B 12 28 17:35 .
drwxr-xr-x@ 30 lizheming  staff   960B 12 28 17:34 ..
-rwxr-xr-x   1 lizheming  staff    87M 12 28 17:34 thinkjs-official-linux
-rwxr-xr-x   1 lizheming  staff    87M 12 28 17:35 thinkjs-official-macos
-rw-r--r--   1 lizheming  staff    82M 12 28 17:35 thinkjs-official-win.exe
➜  www.thinkjs.org git:(master) ✗

постскриптум

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

  1. Динамическая конфигурация настраивается в переменной среды, и программа перезаписывает конфигурацию по умолчанию, считывая переменную среды.
  2. Используйте ThinkJSbeforeStartServer()Хук считывает файл конфигурации в реальном каталоге для охвата конфигурации перед запуском.
    //pkg.js
    const path = require('path');
    think.beforeStartServer(() => {
      const configFile = path.join(process.cwd(), 'config.js');
      const config = require(configFile);
      think.config(config);
    });
    

Кроме того, по мере увеличения сложности проекта в дело может быть введено большое количество сторонних модулей. Предыдущая статья решает только проблему динамического импорта самого проекта ThinkJS.Если импортируемые сторонние модули также динамически импортируются, их также необходимоpkg.assetsОн указан в окне конфигурации. Существует также для модулей C++,pkgВ настоящее время нет возможности добиться автоматического введения, а также необходимоpkg.assetsУкажите зависимые ресурсы в .

//package.json
{
  "pkg": {
    "assets": [
      //以 node-sqlite3 模块为例
      "node_modules/sqlite3/lib/binding/node-v64-darwin-x64/node_sqlite3.node"
    ]
  }
}

вnode-v64-darwin-x64Имена могут не совпадать в зависимости от платформы. нельзя импортировать.nodeПричина для модуля в том, что модуль C++ установлен черезnode-gypВыполнение динамической компиляции, зависящей от платформы. То есть характеристика иpkgТот факт, что модули могут упаковывать бинарные пакеты для всех платформ на одной платформе, в конце концов является конфликтомpkgТакже нет возможности компилировать модули для платформы Windows на платформе Mac. Так что в этом случае помимо необходимости вручную импортировать скомпилированный.nodeВ дополнение к модулю, вам также нужно обратить внимание на введение.nodeмодули иpkg.targetsСоответствие указанной платформе компиляции.

Получать.nodeПомимо установки модулей на соответствующую платформу, вы также можете загрузить скомпилированные модули, предоставленные другими учащимися. Исходный код Taobao предоставляет скомпилированные результаты многих двоичных модулей дляnode-sqlite3Например, все его скомпилированные модули можно найти вЕжегодный рейтинг Taobao.org/mirrors/SQL…Скачать здесь и выбрать соответствующую версию и платформу самостоятельно.

Конфигурация упаковки, упомянутая в этой статье, ужеОфициальный сайт ThinkJSРеализовано в проекте, студенты, которые хотят попробовать, могут напрямую клонировать проект официального сайта и выполнять его после установки зависимостей.npm run pkg-buildдоступны наdist/каталог для получения двоичных исполняемых файлов.