Всем привет!
Очень интересную ситуацию наблюдаю при сборке примеров для документации на разных платформах (Windows, Linux/OS X) с использованием пакетов enb-bem-examples
и enb-magic-factory
. На Windows сборка проходит без ошибок на остальных возникает следующая ошибка:
~/src/drom-bem-makeup master ● enb make examples -n
16:14:26.665 - build started
16:14:27.446 - [failed] [blocks.examples/common-desktop/common-desktop.bemjson.js] file-provider
16:14:27.448 - [failed] [blocks.examples/common-mobile/common-mobile.bemjson.js] file-provider
16:14:27.448 - [rebuild] [blocks.examples/b-button/ee3ZC6dyTetTRFqbHHZqKvywwXM/ee3ZC6dyTetTRFqbHHZqKvywwXM.bemjson.js] file-provider
16:14:27.448 - [rebuild] [blocks.examples/b-button/wrlcu38vmkNaP3tb9gvwZXBiszI/wrlcu38vmkNaP3tb9gvwZXBiszI.bemjson.js] file-provider
16:14:27.448 - [rebuild] [blocks.examples/b-button/PNXYUr__M6VSB4YxqCmkdMhk2l0/PNXYUr__M6VSB4YxqCmkdMhk2l0.bemjson.js] file-provider
16:14:27.449 - [rebuild] [blocks.examples/b-button/Ekw9TzRLS_fyQiOkC-Zi804eDzo/Ekw9TzRLS_fyQiOkC-Zi804eDzo.bemjson.js] file-provider
16:14:27.449 - [rebuild] [blocks.examples/b-button/9y8JjzeQPxlsleieuSrVga8xv4U/9y8JjzeQPxlsleieuSrVga8xv4U.bemjson.js] file-provider
16:14:27.449 - [rebuild] [blocks.examples/b-button/WgU-OFa8iJsKWLBtnoxXtfgoLCc/WgU-OFa8iJsKWLBtnoxXtfgoLCc.bemjson.js] file-provider
16:14:27.449 - [rebuild] [blocks.examples/b-link/D1rJB4_MGVvbnFlNUN1xUlQvtpQ/D1rJB4_MGVvbnFlNUN1xUlQvtpQ.bemjson.js] file-provider
16:14:27.449 - [rebuild] [blocks.examples/b-link/6O-IryxuQJM1YwYJYT_hHvf20NQ/6O-IryxuQJM1YwYJYT_hHvf20NQ.bemjson.js] file-provider
16:14:27.449 - [rebuild] [blocks.examples/b-button/kreyF1JOyT4hpa2NBRIP_KwvWkY/kreyF1JOyT4hpa2NBRIP_KwvWkY.bemjson.js] file-provider
16:14:27.449 - [rebuild] [blocks.examples/b-link/7PpftPzRoUzxzKCcgS8Xn51w1o/7PpftPzRoUzxzKCcgS8Xn51w1o.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/b-link/28tLGFFUSZMApDlzg9Hi-09cNzg/28tLGFFUSZMApDlzg9Hi-09cNzg.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/b-link/XCMcnEyp-kgOzxTPExe9Xyu6xUI/XCMcnEyp-kgOzxTPExe9Xyu6xUI.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/b-link/uIFN2UGU4DNbCgT2JACquwcCSUo/uIFN2UGU4DNbCgT2JACquwcCSUo.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/b-link/UgeVMmhNha9pAtahV7VjriQCt9I/UgeVMmhNha9pAtahV7VjriQCt9I.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/b-link/xhSZr6XvNYk0AwDEfeLBCjtMs1g/xhSZr6XvNYk0AwDEfeLBCjtMs1g.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/b-button/g7f-wx_WjkFq_MRA_Fzs9eRLCnQ/g7f-wx_WjkFq_MRA_Fzs9eRLCnQ.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/m-button-ico/cUvu2JGXCO5KN8cmKNt11ZL40nI/cUvu2JGXCO5KN8cmKNt11ZL40nI.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/b-link/xIo7WqepN6yOXUzXkxpVCwoPtLw/xIo7WqepN6yOXUzXkxpVCwoPtLw.bemjson.js] file-provider
16:14:27.450 - [rebuild] [blocks.examples/b-link/QD3PyE2oaSabCQ_mcdAbZliSAME/QD3PyE2oaSabCQ_mcdAbZliSAME.bemjson.js] file-provider
16:14:27.586 - [rebuild] [blocks.examples/common-desktop/common-desktop.levels] levels
16:14:27.586 - [rebuild] [blocks.examples/common-mobile/common-mobile.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-button/ee3ZC6dyTetTRFqbHHZqKvywwXM/ee3ZC6dyTetTRFqbHHZqKvywwXM.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-button/wrlcu38vmkNaP3tb9gvwZXBiszI/wrlcu38vmkNaP3tb9gvwZXBiszI.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-button/PNXYUr__M6VSB4YxqCmkdMhk2l0/PNXYUr__M6VSB4YxqCmkdMhk2l0.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-button/Ekw9TzRLS_fyQiOkC-Zi804eDzo/Ekw9TzRLS_fyQiOkC-Zi804eDzo.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-button/9y8JjzeQPxlsleieuSrVga8xv4U/9y8JjzeQPxlsleieuSrVga8xv4U.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-button/WgU-OFa8iJsKWLBtnoxXtfgoLCc/WgU-OFa8iJsKWLBtnoxXtfgoLCc.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-link/D1rJB4_MGVvbnFlNUN1xUlQvtpQ/D1rJB4_MGVvbnFlNUN1xUlQvtpQ.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-link/6O-IryxuQJM1YwYJYT_hHvf20NQ/6O-IryxuQJM1YwYJYT_hHvf20NQ.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-button/kreyF1JOyT4hpa2NBRIP_KwvWkY/kreyF1JOyT4hpa2NBRIP_KwvWkY.levels] levels
16:14:27.587 - [rebuild] [blocks.examples/b-link/7PpftPzRoUzxzKCcgS8Xn51w1o/7PpftPzRoUzxzKCcgS8Xn51w1o.levels] levels
16:14:27.588 - [rebuild] [blocks.examples/b-link/28tLGFFUSZMApDlzg9Hi-09cNzg/28tLGFFUSZMApDlzg9Hi-09cNzg.levels] levels
16:14:27.588 - [rebuild] [blocks.examples/b-link/XCMcnEyp-kgOzxTPExe9Xyu6xUI/XCMcnEyp-kgOzxTPExe9Xyu6xUI.levels] levels
16:14:27.588 - [rebuild] [blocks.examples/b-link/uIFN2UGU4DNbCgT2JACquwcCSUo/uIFN2UGU4DNbCgT2JACquwcCSUo.levels] levels
16:14:27.588 - [rebuild] [blocks.examples/b-link/UgeVMmhNha9pAtahV7VjriQCt9I/UgeVMmhNha9pAtahV7VjriQCt9I.levels] levels
16:14:27.588 - [rebuild] [blocks.examples/b-link/xhSZr6XvNYk0AwDEfeLBCjtMs1g/xhSZr6XvNYk0AwDEfeLBCjtMs1g.levels] levels
16:14:27.588 - [rebuild] [blocks.examples/b-button/g7f-wx_WjkFq_MRA_Fzs9eRLCnQ/g7f-wx_WjkFq_MRA_Fzs9eRLCnQ.levels] levels
16:14:27.588 - [rebuild] [blocks.examples/m-button-ico/cUvu2JGXCO5KN8cmKNt11ZL40nI/cUvu2JGXCO5KN8cmKNt11ZL40nI.levels] levels
16:14:27.589 - [rebuild] [blocks.examples/b-link/xIo7WqepN6yOXUzXkxpVCwoPtLw/xIo7WqepN6yOXUzXkxpVCwoPtLw.levels] levels
16:14:27.589 - [rebuild] [blocks.examples/b-link/QD3PyE2oaSabCQ_mcdAbZliSAME/QD3PyE2oaSabCQ_mcdAbZliSAME.levels] levels
16:14:27.590 - build failed
16:14:27.597 - build failed
Error: File not found: /Users/rudoy/src/drom-bem-makeup/blocks.examples/common-desktop/common-desktop.bemjson.js
at /usr/local/lib/node_modules/enb-bem-examples/node_modules/enb/techs/file-provider.js:47:49
at FSReqWrap.cb [as oncomplete] (fs.js:212:19)
Кусок кода отвечающий за сборку примеров и их бандлов:
var factory = config.module('enb-magic-factory'),
helper = factory.getHelper('examples');
helper.prebuild(function(magicConfig){
magicConfig.registerNode('blocks.examples/common-desktop');
magicConfig.registerNode('blocks.examples/common-mobile');
});
helper.configure(function(config, nodes, targets){
var nodes = nodes;
config.nodes(nodes, function(nodeConfig){
if(nodeConfig.getPath() === appConfig.examplesDir + '/common-desktop' || nodeConfig.getPath() === appConfig.examplesDir + '/common-mobile'){
var depsDesktop = [],
depsMobile = [];
nodeConfig.addTechs([
[ require('enb-bem-techs/techs/levels'), {levels: getExamplesLevels(config)} ],
[ enbBemTechs.files ],
[ techs.js ]
]);
nodes.forEach(function (node) {
if (!/\/.*common.*/.test(node)) {
var pathNorm = path.normalize(node),
splitedPath = pathNorm.split(path.sep);
if(/m\-.\w*/.test(node)){
depsMobile.push(splitedPath[splitedPath.length - 1] + '.deps.js');
nodeConfig.addTechs([
//copy deps files to common-mobile dir
[ enbBemTechs.provideDeps, { node: pathNorm, target: splitedPath[splitedPath.length - 1] + '.deps.js' } ],
]);
}else{
depsDesktop.push(splitedPath[splitedPath.length - 1] + '.deps.js');
nodeConfig.addTechs([
//copy deps files to common-desktop dir
[ enbBemTechs.provideDeps, { node: pathNorm, target: splitedPath[splitedPath.length - 1] + '.deps.js' } ],
]);
}
}
});
//merge bundle
if(nodeConfig.getPath() === appConfig.examplesDir + '/common-mobile'){
nodeConfig.addTechs([
[ enbBemTechs.mergeDeps, { sources: depsMobile }]
])
}
if(nodeConfig.getPath() === appConfig.examplesDir + '/common-desktop'){
nodeConfig.addTechs([
[ enbBemTechs.mergeDeps, { sources: depsDesktop }]
])
}
nodeConfig.addTechs([
//bemhtml
[ techs.bemhtml, { sourceSuffixes: [ 'bemhtml', 'bemhtml.js' ] } ],
//css
[ techs.cssStylus, {target: '?.noprefix.css'}],
[ techs.cssAutoprefixer, {
sourceTarget: "?.noprefix.css",
destTarget: '?.css',
browserSupport: ["> 2%", "last 2 versions", "Firefox ESR", "Opera 12.1", "Android >= 4", "iOS >= 5"]
}]
]);
nodeConfig.addTargets(['?.js', '?.css', '?.bemhtml.js']);
}else {
nodeConfig.addTechs([
[require('enb-bem-techs/techs/levels'), {levels: getExamplesLevels(config)}],
[enbBemTechs.bemjsonToBemdecl],
[enbBemTechs.depsOld],
[enbBemTechs.files],
//CSS
[techs.cssStylus, {target: '?.noprefix.css'}],
[techs.cssAutoprefixer, {
sourceTarget: "?.noprefix.css",
destTarget: '?.css',
browserSupport: ["> 2%", "last 2 versions", "Firefox ESR", "Opera 12.1", "Android >= 4", "iOS >= 5"]
}],
//BEMHTML
[techs.bemtree, {sourceSuffixes: ['bemhtml', 'bemhtml.js']}],
//BEMHTML
[techs.bemhtml, {sourceSuffixes: ['bemhtml', 'bemhtml.js']}],
//HTML
[techs.htmlBeautify],
[techs.htmlFromJSON],
//client JS
[techs.browserJs],
[techs.fileMerge, {target: '?.pre.js', sources: ['?.bemhtml.js', '?.browser.js']}],
[techs.prependYm, {source: '?.pre.js'}]
]);
nodeConfig.addTargets(['?.js', '?.css', '?.html', '?.browser.js', '?.beauty.html', '?.bemtree.js']);
}
});
});
Ошибка возникает на этапе сборки бандлов(common-desktop и common-mobile) . При сборке которых нет необходимости провайдить .bemjson.js
.
Не много дебага с помощьюnode.getTechs()
.
if(nodeConfig.getPath() === appConfig.examplesDir + '/common-desktop' || nodeConfig.getPath() === appConfig.examplesDir + '/common-mobile'){
console.log(nodeConfig.getTechs());
......
}
На Windows результат будет пустой
на OS X/Linux [ { _options: { target: '?.bemjson.js' } } ]
Хотелось бы разобраться, почему сборка ведет себя по разному на разных платформах?
@blond
@Hurtsok, беглым взглядом кажется, что проблема в конфигурации нод.
Пакет
enb-bem-examples
берёт BEMJSON-файлы из примеров, которые хранятся в блоках:block.examples/example-name.bemjson.js
и предоставляет их в сеты примеров:desktop.examples/button/example-name/example-name.bemjson.js
.Тут следует обратить внимание, что маской к такой ноде будет
*.examples/*/*
. Судя по логу ошибка возникает в том месте где BEMJSON пытается взяться по такой маске*.examples/*
(на один уровень выше).Можешь подробнее расказать что это за примеры? Как они расположены на файловой системе изначально?
Что касается разного поведения на Windows и OS X/Linux, то скорее всего это какая-то ошибка в Windows.
@blond, у нас есть библиотека блоков, мы собираем не большую документацию по ним, чтобы всей команде было с ними проще работать. Все примеры блоков, вместе с их описанием хранятся в
.md
файле который лежит*.examples/*/*/?.md
. Насколько я понимаю файл парсится и ищутся вставки видаСам
enb-bem-examples
провайдит только.bemjson.js
, но нам необходимы еще css,js,bemhtml, html. Мы пробовали написать конфиг для ноды вида*.examples/*/*
, чтобы до собрать оставшиеся файлы, но такой вариант не подошел по 2 причинам: 1) Каждый раз при вызовеenb make
у нас собирались и страницы, и примеры, что нам не нужно 2) Сборка всегда проходила с ошибкой, что мы не провайдимbemjson.js
. А если начинаем провайдит, то возникает конфиликт т.к его провайдитenb-bem-examples
каждый раз при запуске таскаexamples
Тот код, что я привел в посте решил все наши проблемы, но возникла проблема со сборкой на разных платформах... Проблему эту можно решить, если создать файл
.bemjson.js
вblock.examples/*
, но насколько я понимаю, он не обязателен если мы собираем мердж бандл с помощью.deps.js
.Кажется, я понял в чём проблема.
Конфиг всё же надо написать для нод вида
*.examples/*/*
.А проблема вот в чём: сам ENB не умеет работать с magic пакетами. Точнее, с некоторыми работает, но по случайному совпадению. И с
enb-bem-examples
когда-то давно мог, поэтому в документации осталось про запуск черезenb make
.Для таких пакетов нужно использовать пакет enb-magic-platform.
С точки зрения API он почти ничем не отличается:
Если нужно собрать что-то по пути — надо использовать
make
команду:Сет примеров:
Примеры блока:
Конкретный пример блока:
Если нужно запустить таск:
Если нужно запустить сервер:
@blond Мы добились эффекта чтобы
enb make
собирала только страницы, а командаenb make examples
собирала только примеры. Если убрать сборку бандлов с примерами и собирать только таргеты примеров, то проблема уходит. Конфиг дляenb-bem-examples
есть, просто сейчас не могу его выложить, нет под рукой :) , чуть позже сюда скину.Пример в ветке, это донастройка
enb-make-examples
через фабрику, т.к примеры сами под капотом ее используют@blond И очень странно поведение с
enb make
. Если описать ноду в таком виде:То эта команда будет собирать и примеры и страницы. Если написать так:
Так будут собираться только страницы Я заглянул под капот
`enb-bem-examples
и декларация нод происходит в таком виде['block.examples/button/buttonHash', block.examples/popup/popupHash', ....]
@blond Вот более полный пример сборки примеров и их бандлов, с конфигом для
enb-bem-examples
@blond Поставили
enb-magic-platform
эффект тот же. Windows - ок, остальные fail. Уже начали думать в пользу костылей, создавать на лету '.bemjson.js' для бандлов. Мне кажется проблема кроется вenb-bem-examples
@Hurtsok Спасибо за подробности!
Я всё же, пока считаю, что проблема в конифге :)
Вот тут регистрируются ноды:
Порядок исполнения будет такой:
prebuild
.prebuild
.configure
: https://github.com/enb-bem/enb-bem-examples/blob/master/lib/plugins/inline-bemjson.js#L111-L133.configure
.Из-за пункта (2) в родной
configure
(3) придут эти ноды, и соответственно, там не будет симлинки. И этот код выполнится: https://github.com/enb-bem/enb-bem-examples/blob/master/lib/plugins/inline-bemjson.js#L130-L131.Тут важно понимать, что
prebuild
иconfigure
дополняют, а не переопределяют. Я бы предложил в текущем случаеenb-bem-examples
использовать только для сборки инлайновых примеров, скажем вmd-examples
таске. Плюс сделать мета-таскexamples
, который будет просто вызывать сборку 2х бандлов +md-examples
.Работа в Windows может отличаться из-за специфики симлинок. Я чесно говоря не знаю как симлинки работают в Windows.
@blond Спасибо за ответ! Очень помог :) Все же вы правы по поводу ошибки в конфиге.
Вот тут то и крылась проблема.
А по поводу
Мы собственно и решили до определить изначально :)
Проблему решили, мы просто на этапе
prebuild
создаем в директории с бандлом пустой bemjson, а когда завершается сборка c помощьюEventEmitter
по событиюbuild
прибираем за собой.