Как вы определяете node_modules как externs в Closure Compiler?
У меня есть проект Node.js, который я хочу скомпилировать с помощью Closure Compiler. Я не хочу, чтобы он запускался в браузере/использовал браузер. В основном я хочу использовать функцию проверки типов. Я изначально получил компилятор для правильной работы, используя следующее:
java -jar compiler.jar -W VERBOSE
--language_in ECMASCRIPT5_STRICT
--externs closure-externs.js
--js="lib/**.js"
Где closure-externs.js
вручную определенные переменные и функции, которые я использовал из Node.js, довольно грубо:
// closure-externs.js
/** @constructor */function Buffer(something){}
function require(path){}
var process = {};
[...]
Оказывается, это работало только благодаря удаче. Нет никакого отслеживания зависимостей между файлами, поэтому вы можете иметь случаи, когда вы возвращаете тип {Foo}
, и компилятор будет жаловаться, что он не существует (в зависимости от машины, в зависимости от порядка компиляции). Затем я узнал, что делаю все это неправильно и должен использовать --process_common_js_modules
, чтобы компилятор выполнял отслеживание зависимостей, где я require("foo")
. В настоящее время я вызываю такой компилятор:
java -jar compiler.jar -W VERBOSE
--language_in ECMASCRIPT5_STRICT
--externs externs/fs.js
--js="lib/**.js"
--process_common_js_modules
--common_js_entry_module app.js
Но это не работает:
ERROR - required entry point "module$crypto" never provided
ERROR - required entry point "module$dgram" never provided
ERROR - required entry point "module$extend" never provided
ERROR - required entry point "module$fs" never provided
ERROR - required entry point "module$net" never provided
ERROR - required entry point "module$q" never provided
Некоторые из этих модулей являются родными для Node.js(например, fs
), тогда как другие содержатся в node_modules
как q
. Я не хочу запускать эти внешние модули через компилятор, поэтому я знаю, что мне нужно настроить externs
файл для них. Я знаю, что https://github.com/dcodeIO/node.js-closure-compiler-externs для обычных Node.js externs, и я знаю, как их вызывать в компиляторе, но по какой-то причине когда я делаю что-то вроде --externs externs/fs.js
, ошибка для module$fs
сохраняется. Что я делаю неправильно?
Я знаю там другие флаги, такие как --module
и --common_js_module_path_prefix
, но я не уверен, что мне нужно использовать их, чтобы заставить это работать или нет. Мой Google-фу не смог найти ответы на правильное заклинание здесь.: (
Ответы
Ответ 1
Проблема заключается в том, что вы хотите, чтобы компилятор каким-то образом узнал, что определенные вызовы require
являются внутренними, а именно, что требуемый модуль должен обрабатываться компилятором как источник, а другие внешние, поэтому его следует оставить в покое. В настоящее время нет хорошего способа справиться с этой ситуацией.
Обходные
Использовать пост-обработку для добавления внешних требований о требованиях
В этом случае вы полностью опускаете любые операторы require
для внешних модулей. Компилятор будет обрабатывать только код с внутренними требованиями операторов и модулей. После компиляции вы добавили внешние требования:
Заголовок JS должен быть превентивным
var crypto = require('crypto');
Источник для компиляции
console.log(crypto);
Поскольку crypto
объявлен в extern, компилятор правильно распознает тип и имя символа.
Псевдоним требует вызовов
Когда указан параметр --process_common_js_modules
, компилятор распознает операторы require
и расширяет их аналогично тому, как макросы работают на других языках. Путем сглаживания операторов require
, которые должны оставаться внешними, компилятор не узнает их и, следовательно, не расширяет их.
Источник для компиляции
var externalRequire = require;
/** @suppress {duplicate} this is already defined in externs */
var crypto = externalRequire('crypto');
console.log(crypto)