Interviews (new Projects)

BugFixing flow

React

React элементы -- неизменяемые. Как только элемент был создан, изменить его атрибуты или потомки невозможно. Элемент похож на одиночный кадр в фильме: он представляет собой UI в определенный момент времени.

Однонаправленный поток данных (от родителей к дочерним компонентам). Props -- св-ва, позволяющие взаимодействовать компонентам между собой.

////////////////////////

DOM - это объектное представление HTML документа и интерфейс для управления этим объектом. Это интерфейс доступа к действительных (то есть уже отображаемым) элементам документа HTML.

Хотя DOM похож на другие формы исходного документа HTML, он отличается по ряду причин:

  • Это всегда верный (валидный) HTML код

  • Это модель, которая может быть изменена с помощью Javascript

  • В него не входят псевдоэлементы (такие как ::after)

  • В него входят скрытые элементы (такие как display: none)

ВOM - Объектная модель браузера (Browser Object Model) -- дополнительные объекты, предоставляемые браузером, чтобы работать со всем, кроме документа. С помощью объектной модели браузера (BOM) Вы можете управлять поведением браузера из JavaScript.

Объект window является корневым объектом JavaScript. Все объекты JavaScript, а также переменные и функции определяемые пользователем хранятся в объекте window. -navigation -- информация о браузере и операционной системе -location -- получить текущий URL и перенаправить браузер по новому адресу -history -- журнал навигации за все время работы с конкретны окном.

Функции alert/confirm/prompt тоже являются частью BOM: они не относятся непосредственно к странице, но представляют собой методы объекта окна браузера для коммуникации с пользователем.

////////////////////////

Virtual DOM

Virtual DOM - это любое представление реального DOM. Virtual DOM - это отказ от ненужных изменений в DOM, которые являются дорогостоящими по производительности, потому что изменения в DOM обычно вызывают повторную визуализацию страницы.

Virtual DOM не является стандартом и в конечном итоге мы по-прежнему взаимодействуем с DOM, но делаем это как можно реже и более эффективно. Это техника и набор библиотек / алгоритмов, которые позволяют нам улучшить производительность на клиентской стороне, избегая прямой работы с DOM путем работы с легким JavaScript-объектом, имитирующем DOM-дерево.

Вместо того, чтобы взаимодействовать с DOM напрямую, мы работаем с его легковесной копией. Мы можем вносить изменения в копию, исходя из наших потребностей, а после этого применять изменения к реальному DOM. При этом происходит сравнение DOM-дерева с его виртуальной копией, определяется разница и запускается перерисовка того, что было изменено. Такой подход работает быстрее, потому как не включает в себя все тяжеловесные части реального DOM. Но только если мы делаем это правильно. Есть две проблемы: когда именно делать повторную перерисовку DOM и как это сделать эффективно: 1.Когда данные изменяются и нуждается в обновлении. Есть два варианта узнать, что данные изменились:

  • Первый из них — «dirty checking» (грязная проверка) заключается в том, чтобы опрашивать данные через регулярные промежутки времени и рекурсивно проверять все значения в структуре данных.

  • Второй вариант — «observable» (наблюдаемый) заключается в наблюдении за изменением состояния. Если ничего не изменилось, мы ничего не делаем. Если изменилось, мы точно знаем, что нужно обновить.

2. Как? Что делает этот подход действительно быстрым:

  • Эффективные алгоритмы сравнения

  • Группировка операций чтения/записи при работе с DOM

  • Эффективное обновление только под-деревьев

Shadow DOM

Shadow DOM - используется для инкапсуляции. Благодаря ему в компоненте есть собственное «теневое» DOM-дерево, к которому нельзя просто так обратиться из главного документа, у него могут быть изолированные CSS-правила и т.д. Shadow DOM ссылается на способность браузера включать поддерево элементов DOM в рендеринг документа, но не в дерево DOM основного документа.

Теневой DOM – это способ создать свой, изолированный, DOM для компонента. Элементы из теневого DOM cтилизуются своими стилями из теневого дерева, не из главного документа.

Теневой DOM отделён от главного документа:

  1. Элементы теневого DOM не видны из обычного DOM через querySelector. В частности, элементы теневого DOM могут иметь такие же идентификаторы, как у элементов в обычном DOM (light DOM). Они должны быть уникальными только внутри теневого дерева.

  2. У теневого DOM свои стили. Стили из внешнего DOM не применятся.

Что такое компонент?

Компонент React — в его простейшей форме — это обычная функция JavaScript. Компоненты позволяют разделить пользовательский интерфейс на независимые, повторно используемые части и работать с каждой из частей отдельно. Функциональные и классовые компоненты

function Welcome(props) {
  // Возвращает DOM элемент. Например:
  return <h1>Привет, {props.name}</h1>;
}
// Отрисовываем компонент Button в браузере
ReactDOM.render(<Button label="Save" />, mountNode)

Данная функция — корректный компонент React, потому что он принимает один аргумент-объект «props» (который обозначает свойства) с данными и возвращает элемент React. Такие компоненты называются «функциональными», потому что они являются буквально функциями JavaScript.

Функциональные компоненты - функция, которая принимает props объект в качестве аргумента и возвращает набор HTML.

Также можно использовать класс из ES6 для определения компонента:

class Welcome extends React.Component {
  render() {
    return <h1>Привет, {this.props.name}</h1>;
  }
}

Два вышеуказанных компонента эквивалентны с точки зрения React.

Higher-Order Component (HOC)

Это один из продвинутых способов для повторного использования логики. Компонент высшего порядка — это функция, которая принимает компонент и возвращает новый компонент.

Компонент высшего порядка в React это паттерн, используемый для того, чтобы делить функционал между компонентами без повторения кода. Такие компоненты, по факту, не совсем являются компонентами, это скорее функции. Такая функция берёт компонент как аргумент и отдаёт компонент. Она переделывает компонент в другой компонент и добавляет дополнительные данные или фунционал.

import React from 'react';

const withSecretToLife = (WrappedComponent) => {
  class HOC extends React.Component {
    render() {
      return (
        <WrappedComponent
          {...this.props}
          secretToLife={42}
        />
      );
    }
  }
    
  return HOC;
};

export default withSecretToLife;
import React from 'react';
import withSecretToLife from 'components/withSecretToLife';

const DisplayTheSecret = props => (
  <div>
    The secret to life is {props.secretToLife}.
  </div>
);

const WrappedComponent = withSecretToLife(DisplayTheSecret);

export default WrappedComponent;

Наш компонент WrappedComponent, который по сути является прокачанной версией <DisplayTheSecret/>, позволит нам получить доступ к SecretToLife как к пропсу.

JSX

JSX — расширение языка JavaScript. Фундаментально, JSX является синтаксическим сахаром для функции React.createElement(component, props, ...children). Babel компилирует JSX в вызовы React.createElement().

JSX = JS + HTML + CSS

В HTML вы найдете атрибуты без каких-либо изменений. В JSX они переименованы в свою вариацию на горбатом регистре:

onchange => onChange

Так как JSX это JavaScript и class это зарезервированное слово, вы не можете написать:

<p className="description">

Life Cycle methods

Только для классовых компонентов!!!

В процессе работы компонент проходит через ряд этапов жизненного цикла. На каждом из этапов вызывается определенная функция, в которой мы можем определить какие-либо действия:

1.constructor(props): конструктор, в котором происходит начальная инициализация компонента

Конструкторы в React обычно используют для двух целей:

Конструктор — единственное место, где можно напрямую изменять this.state. В остальных методах необходимо использовать this.setState().

Не используйте побочные эффекты или подписки в конструкторе. Вместо этого используйте componentDidMount().

2. componentWillMount(): вызывается непосредственно перед рендерингом компонента

3. render(): рендеринг компонента

Единственный обязательный метод в подклассе React.Component

При вызове он проверяет this.props и this.state

Функция render() должна быть чистой. Это означает, что она не изменяет состояние компонента, всегда возвращает один и тот же результат, не взаимодействует напрямую с браузером.

render() не вызывается, если shouldComponentUpdate() возвращает false.

4. componentDidMount(): вызывается после рендеринга компонента. Здесь можно выполнять запросы к удаленным ресурсам

componentDidMount() вызывается сразу после монтирования (то есть, вставки компонента в DOM). В этом методе должны происходить действия, которые требуют наличия DOM-узлов. Это хорошее место для создания сетевых запросов.

Этот метод подходит для настройки подписок.

5. componentWillUnmount(): вызывается перед удалением компонента из DOM

В этом методе выполняется необходимый сброс: отмена таймеров, сетевых запросов и подписок, созданных в componentDidMount().

Кроме этих основных этапов или событий жизненного цикла, также имеется еще ряд функций, которые вызываются при обновлении состояния после рендеринга компонента:

  1. shouldComponentUpdate(nextProps, nextState): вызывается каждый раз при обновлении объекта props или state. В качестве параметра передаются новый объект props и state. Эта функция должна возвращать true (надо делать обновление) или false (игнорировать обновление). По умолчанию возвращается true. Но если функция будет возвращать false, то тем самым мы отключим обновление компонента, а последующие функции не будут срабатывать.

  2. componentWillUpdate(nextProps, nextState): вызывается перед обновлением компонента (если shouldComponentUpdate возвращает true)

  3. render(): рендеринг компонента (если shouldComponentUpdate возвращает true)

  4. componentDidUpdate(prevProps, prevState): вызывается сразу после обновления компонента (если shouldComponentUpdate возвращает true). В качестве параметров передаются старые значения объектов props и state.

И отдельно стоит отметить функцию componentWillReceiveProps(nextProps), которая вызывается при обновлении объекта props. Новые значения этого объекта передаются в функции в качестве параметра. Как правило, в этой функции устанавливаются те свойства компонента, в том числе из this.state, которые зависят от значений из props.

React Hooks

Только для функциональных компонентов!!!

100% обратно совместимы. Хуки не содержат изменений, которые могут поломать ваш существующий код.

Хуки — это функции, с помощью которых вы можете «подцепиться» к состоянию и методам жизненного цикла React из функциональных компонентов. Хуки не работают внутри классов — они дают вам возможность использовать React без классов.

Не используйте хуки внутри циклов, условных операторов или вложенных функций. Используйте хуки только на верхнем уровне.

UseState()

useState() API возвращает массив, первое значение содержит state (мы назвали его count, но его можно назвать как угодно) и второе это функция, которую мы вызываем для изменения состояния.

useState() принимает в качестве аргумента начальное значение state. В примере это 0 .

Так как useState() возвращает массив, мы используем деструктуризацию массива для доступа к каждому отдельному элементу, например: const [count, setCount] = useState(0), где:

count - это текущий state, а setCount это функция которая меняет state.

import React, { useState } from "react";
import ReactDOM from "react-dom";

const Counter = () => {
  const [count, setCount] = useState(0);
  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<Counter />, rootElement);

UseEffect()

В классовых компонентах, мы часто делаем side effect функции. Например, подписываемся на события или делаем запросы на получение данных, используя методы componentDidMount, componentWillUnmount и componentDidUpdate.

Hooks предоставляет useEffect() API, который принимает функцию в качестве аргумента.

Функция запускается при первом рендеринге компонента и при каждом последующем повторном рендеринге / обновлении. Сначала React обновляет DOM, а затем вызывает любую функцию, переданную в useEffect(). И всё это без блокировки рендеринга пользовательского интерфейса, даже при блокировке кода, в отличии от старых componentDidMount и componentDidUpdate. Что позволяет приложениям работать быстрее.

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const Counter = () => {
  const [count, setCount] = useState(0);
  const [name, setName] = useState("Alex");

  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);

  useEffect(() => {
    console.log(`Hi ${name} you clicked ${count} times`);
  });

  return (
    <div>
      <p>
        Hi {name} you clicked {count} times
      </p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <button onClick={() => setName(name === "Alex" ? "Alexey" : "Alex")}>
        Change name
      </button>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<Counter />, rootElement);

componentWillUnmount может быть достигнута путем возвращения функции из useEffect():

useEffect(() => {
  console.log(`Hi ${name} you clicked ${count} times`);
  return () => {
    console.log(`Unmounted`);
  };
});

Поскольку функция useEffect() запускается при каждом последующем рендеринге / обновлении, мы можем сказать React пропустить вызов для повышения производительности, добавив второй параметр, который является массивом, содержащим список переменных state, которые нужно отслеживать. React будет повторно запускать side effect только в том случае, если один из элементов в этом массиве меняется.

useEffect(() => {
  console.log(`Hi ${name} you clicked ${count} times`);
}, [name, count]);

Точно так же можно сказать React выполнить side effect только один раз (во время сборки и разборки), передав пустой массив:

useEffect(() => {
  console.log(`Hi ${name} you clicked ${count} times`);
}, []);

Styled components

Библиотека, которая позволяет писать CSS в JS c помощью шаблонных литералов из тегов.

const Button = styled.button`
  font-size: 2em;
  background-color: black;
  color: white;
`;

//Расширение стилей:
const Button = styled.button`
  color: palevioletred;
  font-size: 20px;
  margin: 10px;
  padding: 5px 20px;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

// Новый компонент на основе Button, но с новыми стилями
const TomatoButton = styled(Button)`
  color: tomato;
  border-color: tomato;
`;

render(
  <div>
    <Button> Normal Button </Button>
    <TomatoButton>Tomato Button</TomatoButton>
  </div>,
);

Useful link:

React vs Angular

  • React эффективно работает с памятью (virtual DOM).

  • React использует JavaScript (ES6), признанный веб-язык с 1995 года.

  • Angular использует TypeScript, выпущенный в 2012 году.

  • Статически типизированные языки великолепны, но не делают код более надежным.

  • Динамически типизированные языки требуют меньше времени для написания и дают больше гибкости для творчества.

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

  • В ES6 реализовано множество замечательных модулей, классов, операторов распространения, литералов, что позволяет писать чистый и структурированный код.

Минусы React:

  1. Самые большие минусы React и Redux заключаются не в особенностях реализации того, что они умеют, а в том, чего они не могут. Для того, чтобы создать сложное веб-приложение, вам понадобится много других технологий. Как только вы отойдёте от основных функций React, Redux и пары других библиотек, вы столкнётесь с множеством мнений о «правильных инструментах», с бесчисленным количеством решений и шаблонов, которые иногда легко интегрировать в приложение, а иногда — нет.

  2. React не однозначен и оставляет разработчикам возможность выбирать лучший способ развития. Это может быть решено сильным лидерством проекта и хорошими процессами.

  3. React отходит от компонентов на основе классов, что может стать препятствием для разработчиков, которым более комфортно работать с объектно-ориентированным программированием (ООП).

  4. JSX?

Плюсы:

  • Легко изучить, благодаря простому дизайну, использованию JSX (HTML-подобный синтаксис) для шаблонов и очень подробной документации. Разработчики тратят больше времени на написание современного JavaScript и меньше беспокоятся о коде, специфичном для фреймворка.

  • Очень быстрая, благодаря реализации React Virtual DOM и различным оптимизациям рендеринга.

  • Отличная поддержка рендеринга на стороне сервера, что делает его мощной платформой для контент-ориентированных приложений.

  • Первоклассная поддержка Progressive Web App (PWA) благодаря генератору приложений `create-react-app`.

  • Привязка данных является односторонней, что означает меньше нежелательных побочных эффектов.

  • Redux, самая популярная платформа для управления состоянием приложений в React, ее легко учить и использовать.

  • React реализует концепции функционального программирования (FP), создавая простой в тестировании и многократно используемый код.

Redux

Redux - библиотека, позволяющая управлять состояними приложения через один центр - сторе. Основана на архитектуре Flux.

Redux-thunk - middleware - библиотека, которая позволяет вызвать Action Creator функцию и возвращать при этом др функцию вместо объекта. Функция принимает метод dispatch как аргумент чтобы после того, как асинхр функция завершиться, использовать его для диспатча обычного синхр экшена внутри тела функции. Другими словами позволяет совершать API запросы и совершать какие-либо действия прямо в Action Creatore.

Redux-thunk(middleware) для асинхронных запросов.

MiddleWare - прослойка между диспатчем и редьюсером; усилитель или функция принимающая стор и возвр функцию, которая принимает dispatch.

принципы редакса

минусы редакса

JS

Отличие ES5 и ES6

This

Event Loop

Поток выполнения в браузере, равно как и в Node.js, основан на событийном цикле.

Понимание работы событийного цикла важно для оптимизаций, иногда для правильной архитектуры.

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

макротаски: setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, рендеринг пользовательского интерфейса microtasks: process.nextTick, Promises, Object.observe, MutationObserver

Микрозадачи приходят только из кода. Обычно они создаются промисами: выполнение обработчика .then/catch/finally становится микрозадачей. Микрозадачи также используются «под капотом» await, т.к. это форма обработки промиса.

Обработчики промисов .then/.catch/.finally всегда асинхронны. Даже когда промис сразу же выполнен, код в строках ниже .then/.catch/.finally будет запущен до этих обработчиков.

let promise = Promise.resolve();

promise.then(() => alert("промис выполнен"));

alert("код выполнен"); // этот alert показывается первым

Если вы запустите его, сначала вы увидите код выполнен, а потом промис выполнен. Это странно, потому что промис определённо был выполнен с самого начала. Это происходит из-за следующего.

Асинхронные задачи требуют правильного управления. Для этого стандарт предусматривает внутреннюю очередь PromiseJobs, более известную как «очередь микрозадач (microtask queue)» (термин V8).

Как сказано в спецификации:

  • Очередь определяется как первым-пришёл-первым-ушёл (FIFO): задачи, попавшие в очередь первыми, выполняются тоже первыми.

  • Выполнение задачи происходит только в том случае, если ничего больше не запущено.

Таким образом, обработчики .then/catch/finally вызываются после выполнения текущего кода.

Пример:

setTimeout(() => alert("timeout"));

Promise.resolve()
  .then(() => alert("promise"));

alert("code");

Какой здесь будет порядок?

  1. code появляется первым, т.к. это обычный синхронный вызов.

  2. promise появляется вторым, потому что .then проходит через очередь микрозадач и выполняется после текущего синхронного кода.

  3. timeout появляется последним, потому что это макрозадача.

Все микрозадачи завершаются до обработки каких-либо событий или рендеринга, или перехода к другой макрозадаче.

Useful link:

Promise

В ES6 появилась встроенная поддержка промисов. Промис это объект, который ждёт выполнения асинхронной операции, после которого (т.е. после выполнения) промис принимает одно из двух состояний: fulfilled (resolved, успешное выполнение) или rejected (выполнено с ошибкой). В сущности, промис - это возвращаемый объект, в который вы записываете два коллбэка вместо того, чтобы передать их функции.

Promise - observable, но отдает одно значение.

Обещания ~ функции обратного вызова. Callbacks => Promises.

Без обещаний присутствовала бы громозкость кода и огромное кол-во коллбэков в коллбэках (CallBackHell). В отличие от старомодных переданных коллбэков промис дает некоторые гарантии:

  • Коллбэки никогда не будут вызваны до завершения обработки текущего события в событийном цикле JavaScript.

  • Коллбеки, добавленные через .then даже после успешного или неудачного завершения асинхронной операции, будут также вызваны.

  • Несколько коллбэков может быть добавлено вызовом .then нужное количество раз, и они будут выполняться независимо в порядке добавления.

Но наиболее непосредственная польза от промисов - цепочка вызовов (chaining). «Чейнинг» (chaining), то есть возможность строить асинхронные цепочки из промисов – пожалуй, основная причина, из-за которой существуют и активно используются промисы. При чейнинге, то есть последовательных вызовах .then…then…then, в каждый следующий then переходит результат от предыдущего.

Если then возвращает промис, то до его выполнения может пройти некоторое время, оставшаяся часть цепочки будет ждать.

То есть, логика довольно проста:

  • В каждом then мы получаем текущий результат работы.

  • Можно его обработать синхронно и вернуть результат (например, применить JSON.parse). Или же, если нужна асинхронная обработка – инициировать её и вернуть промис.

Promise.resolve() и Promise.reject() короткий способ создать уже успешные или отклоненные промисы соответственно. Это иногда бывает полезно.

let promise = new Promise(function(resolve, reject) {
  setTimeout(() => resolve("done!"), 1000);
});

// resolve запустит первую функцию, переданную в .then
promise.then(
  result => alert(result), // выведет "done!" через одну секунду
  error => alert(error) // не будет запущена
);
let promise = new Promise(function(resolve, reject) {
  setTimeout(() => reject(new Error("Whoops!")), 1000);
});

// reject запустит вторую функцию, переданную в .then
promise.then(
  result => alert(result), // не будет запущена
  error => alert(error) // выведет "Error: Whoops!" спустя одну секунду
);

Promise.all() и Promise.race() - два метода запустить асинхронные операции параллельно.

Метод Promise.all(iterable) возвращает обещание, которое выполнится тогда, когда будут выполнены все обещания, переданные в виде перечисляемого аргумента, или отклонено любое из переданных обещаний.

Вызов Promise.race, как и Promise.all, получает итерируемый объект с промисами, которые нужно выполнить, и возвращает новый промис. Но, в отличие от Promise.all, результатом будет только первый успешно выполнившийся промис из списка. Остальные игнорируются.

Метод then() возвращает Promise. Метод может принимать два аргумента: колбэк-функции для случаев выполнения и отклонения промиса.

Промисификация – это когда берут асинхронную функциональность и делают для неё обёртку, возвращающую промис.

После промисификации использование функциональности зачастую становится гораздо удобнее.

В качестве примера сделаем такую обёртку для запросов при помощи XMLHttpRequest.

Замыкание

Замыкание - это комбинация функции и лексического окружения, в котором эта функция была определена. Другими словами, замыкание дает вам доступ к Scope внешней функции из внутренней функции. В JavaScript замыкания создаются каждый раз при созданиии функции, во время ее создания.

Замыкание это способ получения доступа и управления внешними переменными из функции.

Не нужно без необходимости создавать функции внутри функций в тех случаях, когда замыкания не нужны. Использование этой техники увеличивает требования к производительности как в части скорости, так и в части потребления памяти.

function getCounter() {
  let counter = 0;
  return function() {
    return counter++;
  }
}

let count = getCounter();

console.log(count());  // 0
console.log(count());  // 1
console.log(count());  // 2

Прототипы

JavaScript — это объектно-ориентированный язык, основанный на прототипировании, а не на классах. Прототипы - это механизм, с помощью которого объекты JavaScript наследуют свойства друг от друга.

Каждый конструктор имеет специальное свойство prototype. Каждый объект, созданный конструктором, содержит ссылку на свойство prototype своего конструктора. Эта ссылка хранится в свойстве __proto__.

JavaScript часто описывают как язык прототипного наследования — каждый объект, имеет объект-прототип, который выступает как шаблон, от которого объект наследует методы и свойства. Объект-прототип так же может иметь свой прототип и наследовать его свойства и методы и так далее. Это часто называется цепочкой прототипов и объясняет почему одним объектам доступны свойства и методы которые определены в других объектах.

Точнее, свойства и методы определяются в свойстве prototype функции-конструктора объектов, а не в самих объектах.

Если один объект имеет специальную ссылку __proto__ на другой объект, то при чтении свойства из него, если свойство отсутствует в самом объекте, оно ищется в объекте __proto__. Объект, на который указывает ссылка __proto__, называется «прототипом». Другими словами, прототип – это «резервное хранилище свойств и методов» объекта, автоматически используемое при поиске.

В JavaScript создается связь между экземпляром объекта и его прототипом (свойство __proto__, которое является производным от свойства prototype конструктора), а свойства и методы обнаруживаются при переходе по цепочке прототипов.

Знать примеры на каждый вопрос желательно

Common

Scrum, церемонии CI/CD/CD

ДОКЕР vs Virtual Machine

Docker — это программная платформа для быстрой разработки, тестирования и развертывания приложений. Docker упаковывает ПО в стандартизованные блоки, которые называются контейнерами.

Что представляет из себя Docker. Три основных термина в экосистеме Docker:

  • образ (image) – готовая файловая система, сформированная по инструкциям из Dockerfile и служащая прообразом для запускаемых контейнеров.

  • реестр (registry) – репозиторий образов. Docker Hub, о котором шла речь выше, - это публичный репозиторий, где хранится огромное количество образов;

  • контейнер (container) – запущенное приложение, т.е. совокупность процессов и образа.

Цитируя разработчиков Docker, «контейнер — это стандартная единица программного обеспечения, в которую упаковано приложение со всеми необходимыми для его работы зависимостями — кодом приложения, средой запуска, системными инструментами, библиотеками и настройками». Контейнер работает пока живет процесс запущенный в этом контейнере. Собственно контейнер как маленькая операционная система (хотя это конечно не так) с необходимыми библиотеками и зависимостями для работы приложения внутри него. Он позволяет «упаковать» приложение или веб-сайт со всем его окружением и зависимостями в контейнер, которым в дальнейшем можно легко и просто управлять: переносить на другой сервер, масштабировать, обновлять.

Преимущества Docker

  1. Docker – это в первую очередь удобство: выполнить многие действия – к примеру, создать готовое для запуска приложение или установить дополнительное ПО – становится намного проще и быстрее. Используя Docker, вы сможете оптимизировать свою работу и экономить время

  2. Образы контейнеров Docker содержат в себе все необходимые приложению библиотеки, поэтому конфликтов с другим ПО не будет.

  3. Docker, вы сможете легко перенести приложение в другую среду: достаточно загрузить образ в репозиторий и скачать его на сервере. И вы можете не беспокоиться, что запущенное приложение использует все ваши ресурсы – Docker позволяет настроить количество ресурсов, выделенное под каждое приложение.

  4. Легковесность, быстродействие и возможность работать на высоком уровне абстракции, делегируя проблемы с железом и ОС провайдеру, — это преимущества контейнеров, позволяющие снизить операционные расходы, связанные с разработкой и эксплуатацией приложений, делающих решения на их базе столь привлекательными для бизнеса.

  5. Техническим же специалистам контейнеры прежде всего полюбились за возможность упаковать приложение вместе с его средой запуска, решая тем самым проблему зависимостей в разных окружениях. Например, различие версий языковых библиотек на ноутбуке разработчика и в последующих окружениях рано или поздно приведёт к сбоям, и нужно будет как минимум потратить время на их анализ, а как максимум — решать проблему проникших в продакшен багов. Использование контейнеров устраняет проблему "А на моей машине все работало!

  6. Контейнеры позволяют сократить время разработки приложения и упрощают управление им в продакшене благодаря лёгкости в настройке и изменении конфигурации, возможности версионировать её вместе с кодом приложения и удобным инструментам оркестрирования, позволяющим быстро масштабировать инфраструктуру. Кроме того, фактическое отсутствие привязки контейнеров к хостинговой платформе даёт огромную гибкость при выборе или смене провайдера — вы можете запускать их без принципиальных отличий в конечном результате на личном компьютере, bare metal серверах и в облачных сервисах.

Чем контейнеры отличаются от виртуальных машин

Наиболее частым вопросом при выборе среды запуска приложения является вопрос о различии между контейнерами и виртуальными машинами — двумя самыми популярными опциями на текущий момент. Между ними есть принципиальная разница. Контейнер, в сущности, является ограниченным внутри ОС пространством, использующим для доступа к аппаратным ресурсам ядро host-системы. ВМ представляет собой машину целиком со всеми необходимыми для её работы устройствами. Из этого образуются отличия, имеющие практическое значение:

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

  • Контейнеры можно запускать только в той же операционной системе, что стоит на host-системе — то есть запустить Windows-контейнер на host-системе с Linux не получится (на персональных устройствах это ограничение обходится с помощью технологии виртуализации). Однако это не относится к разным дистрибутивам одной и той же ОС, например Ubuntu и Alpine Linux.

  • Контейнеры предоставляют меньшую степень изоляции, поскольку используют ядро host-системы, что потенциально создаёт бóльшие риски в эксплуатации при небрежном отношении к безопасности.

Кроссбраузерность/полиффилы в IE

Кроссбраузерность — это способность сайта корректно отображаться в различных браузерах. Ресурс должен работать одинаково во всех версиях обозревателей.

Как верстать кроссбраузерно?

  1. Используйте сброс или нормализацию стандартных стилей браузера. Reset.css или normalize.css. Если кратко говорить о подходах, то смысл reset-а в том, чтоб большинство дефолтных стилей браузеров обнулить (все отступы, форматирование и т.д) и на этой основе писать свое. Смысл normalize — привести все эти стили к единому виду и значениям. Подробнее можно изучить по ссылкам:) Есть много сторонников первого подхода, есть много сторонников второго. Можно очень долго с пеной у рта обсуждать преимущества или недостатки каждого из них, но всегда нужно помнить, что инструмент должен подходить под задачу. Выбирайте то, что вам подходит.

  2. Используйте вендорные префиксы, где это необходимо. Вендорные префиксы — это приставки, добавляемые в свойства CSS, используемые производителями (вендорами) браузеров для экспериментальных, еще не принятых в стандарт CSS свойств. То есть, например, если какой-нибудь из браузеров решил добавить что-нибудь крутое, но этот функционал и правила его поведения еще до конца не оговорены и не утверждены с составителями стандартов, то браузер может имплементировать его с соответствующей приставкой. Свойство с такой приставкой будет работать только в браузере, для которого эта приставка актуальна. Существуют следующие вендорные префиксы:

  • -o- для браузера Опера

  • -moz- для браузеров из семейства Mozilla

  • -ms- для Internet Explorer 8

  • -webkit- префикс для браузеров, построенных на движке Webkit, в частности Safari и Chrome (ну и конечно же, новый Edge:)

  • -icab- для браузера iCab (альтернативного, как заявлено на родном сайте, браузера для Apple)

  • -khtml- KHTML — компонент для просмотра HTML документов разработанный для среды KDE для UNIX-систем.

Например, мы уже давно можем стилизировать placeholder для input-ов, но какие-то браузеры имплементировали это как псевдоэлемент, а какие-то — как псевдокласс. Поэтому, чтобы стилизовать placeholder одинаково для всех браузеров, нужно писать примерно так:

::-webkit-input-placeholder { /* Chrome/Opera/Safari */
    color: pink;
}

::-moz-placeholder {          /* Firefox 19+ */
    color: pink;
}

:-ms-input-placeholder {      /* IE 10+ */
    color: pink;
}

:-moz-placeholder {           /* Firefox 18- */
    color: pink;
}

3. CSS-хаки. Это использование специальных свойств, понимаемых только определенными браузерами. Для каждого браузера имеются свои собственные хаки, с помощью которых можно добиться практически полной кроссбраузерности. Сами хаки можно найти в Интернете.

Пример css-хака, работающего только в Firefox:

@-moz-document url-prefix() {
    .hackBlock {
        background: blue;
    }
} 

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

4. Используйте полифиллы. Полифилл - код, чаще всего библиотека, которая добавляет в старые браузеры поддержку возможностей, которые в современных браузерах являются встроенными.

4. Новые свойства CSS и JS перед использованием проверяйте на сайте caniuse.com. Это ресурс, который отслеживает поддержку самыми популярными браузерами различных свойств CSS и JS. Если вы хотите использовать какую-то технологию, но точно не уверены, кроссбраузерная ли она, и можно ли ее использовать в соответствии с вашими правилами поддержки браузеров, заходите на caniuse и проверяйте. 5. Тестируйте свою работу в разных браузерах. 6. Интересуйтесь последними обновлениями в браузерах и во фронт-энде в целом. Масса сайтов, типа habr.ru, dou.ua, codeguida.com публикуют подборки с самыми интересными и свежими материалами по фронт-энду.

SELF PRESENTATION!

Кронос с января.

Took part in development of the "Override Wage and Work Rules" feature. It was a modal window, where users are able to override and edit wages and Work Rules.

  1. Built flow CI/CD and local DEV environment;

  2. Integrated UI with NodeJS and Backend.

Took part in code review, sprint planning, demo sessions, retrospectives.

Как справлялся с трудностями?

Зависит от таски, прежде всего самостоятельно, обращался к документации. Если понимал, что трачу овер времени, обращался за помощью к кей деву, ставил в известность Тим Лида. После работы чекал курсы по ангуляру.

Достижения

Бейдж от тим лида во время отпуска кей дева.

Технологии

Grunt, Webpack, Docker, Lodash, Git, Jenkins, BitBucket, TSLint, Jira, Confluence. JavaScript, ES6, TypeScript, AJAX, AngularJS, HTML5, CSS, LESS, Jasmine, Karma, NodeJS.

Тима

Dev Team: 5 members (3 BE, 2 FE) QA Team: 3 engineers (2 manual, 1 automation); SM: 1 member; BA: 1 member.

+Scrum

+FightClub

How to fill 'Past Projects' section in UPSA?

Examples:

Last updated