Компиляция s css на стороне клиента для экономии в сети - PullRequest
5 голосов
/ 26 апреля 2020

Я видел этот пример для анимированного звездного фона, используя css, и заметил, что скомпилированный css значительно меньше в этом случае, так как sass генерирует тысячу звезд за все oop.

// n is number of stars required
@function multiple-box-shadow ($n) 
  $value: '#{random(2000)}px #{random(2000)}px #FFF'
  @for $i from 2 through $n
    $value: '#{$value} , #{random(2000)}px #{random(2000)}px #FFF'

  @return unquote($value)

Это заставило меня задуматься, есть ли способ сгенерировать css на стороне клиента? Не перевесит ли экономия на пропускной способности сети (минимальную) стоимость генерации css?

Я не смог найти пример для такого варианта использования, делает ли сетевое трафик c это неуместным?

Я не обязательно специально спрашиваю об этом случае. Больше того, как учитывается пропускная способность и время вычислений (если вообще). То же самое можно сказать о наличии js каркасов, которые имеют способы генерации HTML с использованием более краткого синтаксиса (например, ngFor в Angular) на стороне клиента.

Ответы [ 3 ]

6 голосов
/ 07 мая 2020

Компилятор Sass написан на C ++, поэтому было бы более или менее невозможно запустить его внутри браузера.

Вместо этого вы можете использовать Less , который довольно хорошо работает внутри браузер.

index. html

<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/3.9.0/less.min.js" ></script>

множественная коробка-тень. js

(этот плагин необходим, поскольку Less не может генерировать случайные числа сам по себе)

registerPlugin({
  install: function(less, pluginManager, functions) {
      functions.add('multiple-box-shadow', function(n) {
          return Array(n.value).fill().map(function() {
              var x = Math.floor(Math.random()*2000);
              var y = Math.floor(Math.random()*2000);
              return x+'px '+y+'px #FFF';
          }).join(',');
      });
  }
});

styles.less

@plugin "multiple-box-shadow";

@shadows-small:  multiple-box-shadow(700);
@shadows-medium: multiple-box-shadow(200);
@shadows-big:    multiple-box-shadow(100);

#stars {
    width: 1px;
    height: 1px;
    background: transparent;
    box-shadow: @shadows-big;
    animation: animStar 50s linear infinite;
}

Для вашего конкретного примера c:

  • стилей. css: 41'277 B (5'936 B сжатых)
  • стили .less: 1'856 B (сжатый 586 B)

В консоли меньше выводит время генерации, на моем компьютере оно составляет от 100 мс до 200 мс.

Я думаю, что Преимущество компиляции на стороне клиента очень мало. Очень редко иметь скомпилированный CSS, который больше, чем его источник, в основном потому, что CSS компиляторы минимизируют их вывод.

4 голосов
/ 08 мая 2020

Не перевесит ли экономия на пропускной способности сети (незначительные) затраты на генерацию css?

Возможный аргумент против этого может заключаться в том, что да, вы можете сэкономить при загрузке полосы пропускания загрузка меньшего файла S CSS по сравнению с CSS, но также необходимо предоставить клиенту код компилятора, который (предположение) перевешивает разницу в размере файла по сравнению с css.

В отсутствие лучшего примера я беру числа Янна и LESS в предположении, что воображаемый компилятор S CSS будет демонстрировать аналогичное поведение:

Для вашего конкретного примера c:
- styles . css: 41'277 B (сжатый 5'936 B)
- без стилей: 1'856 B (сжатый 586 B)

  • меньше. Мин. js: 167'812 B

Если браузеры не будут поставляться с предустановленным S CSS -компилятором, следовательно, в первую очередь возникает вопрос о необходимости CSS типа файла.

1 голос
/ 09 мая 2020

Как отметил @onewaveadrian, нет смысла пытаться сохранить несколько байтов, генерируя CSS в браузере, но вместо этого скачайте компилятор S CSS или LESS, чтобы сделать это.

Тем не менее, вы могли бы генерировать эти CSS тени, используя только ваниль JS в браузере, без учета какой-либо дополнительной зависимости, которая сэкономит много байтов и, вероятно, будет работать быстрее, чем полноценный а также компилятор.

Чтобы сделать его еще быстрее, функция multipleBoxShadow использует простую while l oop, конкатенацию строк и побитовое ИЛИ оператор (|) до номера этажа намного быстрее, чем Math.floor().

const MAX_Y_OFFSET = 2000;
const MAX_X = window.innerWidth;
const MAX_Y = window.innerHeight + MAX_Y_OFFSET;

function multipleBoxShadow(n) {
  let boxShadow = '';
  
  // Let's use a simple while loop and the bitwise OR operator (`|`) to round up values here
  // to run this as fast as possible:
  while (n--) {
    boxShadow += `,${ Math.random() * MAX_X | 0 }px ${ Math.random() * MAX_Y | 0 }px #FFF`;
  }
  
  return boxShadow.slice(1);
}

const { documentElement } = document;

documentElement.style.setProperty('--shadows-small', multipleBoxShadow(700));
documentElement.style.setProperty('--shadows-medium', multipleBoxShadow(200));
documentElement.style.setProperty('--shadows-big', multipleBoxShadow(100));
body {
  min-height: 100vh;
  background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%);
  overflow: hidden;
}

#stars {
  width: 1px;
  height: 1px;
  background: transparent;
  animation: animStar 50s linear infinite;
  box-shadow: var(--shadows-small);
}

#stars:after {
  content: " ";
  position: absolute;
  top: 2000px;
  width: 1px;
  height: 1px;
  background: transparent;
  box-shadow: var(--shadows-small);
}

#stars2 {
  width: 2px;
  height: 2px;
  background: transparent;
  animation: animStar 100s linear infinite;
  box-shadow: var(--shadows-medium);
}

#stars2:after {
  content: " ";
  position: absolute;
  top: 2000px;
  width: 2px;
  height: 2px;
  background: transparent;
  box-shadow: var(--shadows-medium);
}

#stars3 {
  width: 3px;
  height: 3px;
  background: transparent;
  animation: animStar 150s linear infinite;
  box-shadow: var(--shadows-big);
}

#stars3:after {
  content: " ";
  position: absolute;
  top: 2000px;
  width: 3px;
  height: 3px;
  background: transparent;
  box-shadow: var(--shadows-big);
}

@keyframes animStar {
  from {
    transform: translateY(0px);
  }
  to {
    transform: translateY(-2000px);
  }
}
<div id='stars'></div>
<div id='stars2'></div>
<div id='stars3'></div>

Как видите, я использую CSS пользовательских свойств , чтобы передать сгенерированное значение box-shadow в CSS, чтобы я мог использовать его и в псевдоэлементах. Если вы предпочитаете не использовать CSS переменные, вы можете использовать 6 <div> s вместо 3 и использовать атрибут style следующим образом:

document.getElementById('stars').style.boxShadow = multipleBoxShadow(700);
document.getElementById('stars2').style.boxShadow = multipleBoxShadow(700);
document.getElementById('stars3').style.boxShadow = multipleBoxShadow(200);
document.getElementById('stars4').style.boxShadow = multipleBoxShadow(200);
document.getElementById('stars5').style.boxShadow = multipleBoxShadow(100);
document.getElementById('stars6').style.boxShadow = multipleBoxShadow(100);

Также, если производительность самой анимации не достаточно хорош, вы, вероятно, могли бы легко адаптировать этот код для рисования начальных точек (фактически, кругов или квадратов) на <canvas> и анимировать их, используя Window.requestAnimationFrame().

...