Поделюсь небольшими экспериментами с дублированием функциональности require в Node.js. Практика скорее порочная, но немного проливает свет на проблемы этой популярной платформы. Изначальная мотивация в подобных изысканиях возникла после следующих наблюдений.
Существует некое концептуальное различие в способах подключения внешних библиотек и файлов проекта. А стандартный механизм для этого используется один и тот же. Второй момент, который меня смущает — это несколько замороченная логика работы самого require.
В итоге захотелось по крайней мере свои файлы подключать самодельным, но более прозрачным способом. Параллельно добавив несколько дополнительных фич. Так появились нижеописанные функции.
get_modules =( string, modules ={} )->
groups =string .split ' '
for group in groups
items =group .split ':'
id =items[ 0 ]
named =items .length > 1
name =if named then items[ 1 ] else id .replace( /\-/g, '_' )
obj =require id
obj =obj[ name ] if named and obj[ name ]
modules[ name ] =obj
modules
вспомогательная функция подключения стандартных модулей. Работает следующим образом. После, например modules =get_modules 'fs path coffeescript vm'
в объекте modules
мы получим стандартные модули fs, path и другие, обращаться, к которым соответсвенно можно будет modules .[имя модуля] .[имя функции]
.
Теперь
read =( file )->
path =modules .path .join __dirname, file
modules .fs .readFileSync path, 'utf8'
— возвращает содержимое исходного файла.
compile =( coffee, file )->
options = inlineMap: false, sourceMap: true, bare: true, filename: file
res =modules .coffeescript .compile coffee, options
res .js
— транслирует CoffeeScript в JavaScript.
evaluate =( js, filename ='', lineOffset =0, columnOffset =0 )->
modules .vm .runInThisContext js, { filename, lineOffset, columnOffset }
— исполняет JavaScript код.
И всё вместе, в случае, если мы хотим обернуть наш код в некую wrapper-функцию:
get_wrapper =( id, args )->
file =id + '.coffee' #путь к файлу
str =@read( file ) .replace( /\n/g, "\n\t" ) #добавляем отступы
coffee ="( #{ args } )->\n\t#{ str }" #собственно "оборачиваем" в функцию
js =@compile coffee, file
@evaluate js, file#, 1, 0
где args
— строка с именами переменных через запятую, которые станут доступны как "глобальные" в данном модуле.
https://gist.github.com/jenya239/78b7c819ee8e93490d7d384a204c44bf