Postcss: Давайте добавим в вебпак возможность передавать AST из PostCSS по цепочке лоадеров?

Created on 7 Aug 2016  ·  11Comments  ·  Source: postcss/postcss

I apologize for my Russian...

Прошу прощения что на русском, просто такое через переводчик не перевести =)

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

Тогда бы например лоадеры, использующие PostCSS могли бы возвращать что-то типа

var code = ast.toCss() // я не знаю какой у вас апи просто
callback(code, map, ast) // и дополнительно можно передать служебную инфу

а следующий по цепочке лоадер бы получал аргументы:

function loader(code, map, ast){}

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

callback(ast)

Но тогда надо придумать какой то механизхм совместимости с уже существующими лоадерами, которые ожидают строку на входе. (и если там прилетит обьект то не факт что они вызовут у него например obj.toString() )

All 11 comments

А что будет, если посредине лоадер изменит код, но не обновит 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)
}

Я сейчас брату показываю Россию — не смогу :(.

Но ты начни, там нейтивов мало. Просто чаще используй примеры кода, чтобы показать.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Semigradsky picture Semigradsky  ·  3Comments

ZeeCoder picture ZeeCoder  ·  7Comments

sydneyitguy picture sydneyitguy  ·  5Comments

iamstarkov picture iamstarkov  ·  14Comments

buhlahkay picture buhlahkay  ·  3Comments