I apologize for my Russian...
Прошу прощения что на русском, просто такое через переводчик не перевести =)
Давайте создадим тикет в репозитории вебпака, для того, чтобы лоадеры могли передавать, помимо соурс мепов, какую то другую служебную информацию, которая возможно приигодится следующим лоадерам в цепочке. Как вам такой подход, а?)
Тогда бы например лоадеры, использующие PostCSS могли бы возвращать что-то типа
var code = ast.toCss() // я не знаю какой у вас апи просто
callback(code, map, ast) // и дополнительно можно передать служебную инфу
а следующий по цепочке лоадер бы получал аргументы:
function loader(code, map, ast){}
либо же сделать проще, чтобы была возможность просто брать и передавать прям любой обьект а не только строку
callback(ast)
Но тогда надо придумать какой то механизхм совместимости с уже существующими лоадерами, которые ожидают строку на входе. (и если там прилетит обьект то не факт что они вызовут у него например obj.toString() )
А что будет, если посредине лоадер изменит код, но не обновит AST?
А что будет, если посредине лоадер изменит код, но не обновит AST?
Я слегка обновил пост, я думаю что код вообще передавать не нужно. Нужно передавать либо строку либо обьект имеющий метод toString(), и лоадеры должны знать что если им нужна просто строка, то у первого аргумента они должны вызвать toString() а если же они могут обработать какой то обьект, то делают что-то вроде
if (obj instanceof PostCssAST){
// обрабатываем как аст
}
else{
// парсим строку заного
}
Да, можно попробовать поговорить с командой вебпака. Создавай issue.
Не обязательно с ними разговаривать, я просто напишу сам и скину им реквест)
Главное обратную совместимость с текущими лоадерами, которые строку ожидают, сохранить
@ai слушай, вопрос, компиляция ast в соурсмэп, и в css код это дорогая операция?
То есть нужно стремиться избегать этого делать лишний раз?
вот гляди, придумал механизм обратной совместимости:
Если лоадер ожидает третий аргумент (определяется как func.length > 2)
Тогда мы просто передаем ему этот аргумент (ast в нашем случае), если же лоадер ожидает всего 2 аргумента, то тогда мы вызываем функцию обработчик, которая генерирует нам массив из мэпа и скомпилированной строки. Таким образом обычные лоадеры будут принимать то, что они и ожидают, строку и карту. А лоадеры ожидающие третий аргумент будут получать третий аргумент, и игнорирвать 2 предыдущих (которые будут undefined). Выглядит, признаться, убого, но я пока еще думаю.
function PostCSS(code, map) {
this.callback(ast, function () {
return [ast.toCss(), ast.createMap()]
})
}
function PostCSSBro(code, map, ast) {
}
function normalLoader(code, map) {
}
Надо как то развить эту идею, о том чтобы лоадер мог сообщить что он УМНЫЙ и если есть какое то AST то он готов его принять, и компилировать в строку, и тратить время, не надо.
@ai
во, я придумал, надо просто текущему лоадеру дать доступ к следующему лоадеру, элементарно =)
function PostCSS(code, map) {
if (this.nextLoader.length === 3) {
this.callback(ast)
}
else {
this.callback(ast.toCss(), ast.toMap())
}
}
Таким образом следующий лоадер например может даже какие то настройки себе задавать, которые БРАТСКИЕ лоадеры (свои ребята) поймут, гляди:
Наш лоадер:
module.exports = function(){
if(this.nextLoader.needAst){
this.callback(ast)
}
else{
this.callback(ast.toCss(), ast.toMap())
}
}
Следующий лоадер:
module.exports = loader
loader.needAst = true
function loader(ast){
}
или даже так, типа если мы, в качестве лоадера, экспортируем не функцию а обьект, то он устанавливается как "опции лоадера", а его свойство loader становится лоадером
module.exports = {
needsAst: true,
noCompile: true,
loader: function(ast){
}
}
А в предыдущем по цепочке лоадере мы читаем эти опции
module.exports = function loader(){
if(this.nextLoaderOptions.needsAst) {
this.callback(ast)
}
}
Да, но обсуди с ребятами из вебпака ;). Там очень много хитростей внутри — может это не будет работать, например, с кешами.
А, ну да. точно.
Да, но обсуди с ребятами из вебпака
Может ты обсудишь? А то у меня траблы с английским а сложные предложения приходится упрощать и получается бред. Или у тебя время нет на такое? (
Как раз бы вам пригодилась такая фишка с передачей ast, раз вебпак так популярен.
Не ну еще можно сделать вот так типа, но тут мы лишнюю компиляцию НА ВСЯКИЙ СЛУЧАЙ, ДЕЛАЕМ, что плохо ^^
var code = new String(ast.toCss())
code.ast = ast
this.callback(code)
function loader(code){
var ast = code.ast || new AST(code)
}
Я сейчас брату показываю Россию — не смогу :(.
Но ты начни, там нейтивов мало. Просто чаще используй примеры кода, чтобы показать.