Блог экспериментатора инженера-разработчика: Infanty.
Я пишу how-to статьи на редкие темы или статьи обзоры - для себя и тех кто со мной работает.
Блог существует при поддержке: "Оккупационных сил Марса".

В рамках одного из проектов понадобилось разработать лендинг с авторизацией в панели администрирования и саму панель. При этом большая часть информации в панели администрирования должна была быть динамически обновляемой без перегрузки страницы. Ключевыми требованиями являлись: наличие поддержки мобильных браузеров и создание мобильного приложения на основе кода реализации фронтенда. К тому времени уже был реализован бэкенд с которым можно было взаимодействовать по API как из браузера (используя JavaScript), так и из мобильного или десктопного приложения. Было принято решение использовать для разработки Bootstrap и React.js в связке с React Native, Redux, Websocket и JWT.

React.js в данный момент является одной из самых популярных и быстро развивающихся JavaScript библиотек. Она разрабатывается при поддержке таких крупных интернет-гигантов как Facebook и Instagram. Так же важно знать, что для "комфортной" разработки JavaScript приложения (в том числе и на React.js) в 2017 году: дополнительно требуется - настройка вспомогательного окружения для разработки, сборки и тестирования проекта. На эту тему написана даже шуточная статья: "Каково оно учить JavaScript в 2016".

Node.js

Для работы вспомогательного окружения, в частности Webpack-а, требуется Node.js. Node.js это программная платформа, основанная на движке V8 (транслирующем JavaScript в машинный код), превращающая JavaScript из узкоспециализированного языка работающего в веб-браузере в язык общего назначения. Node.js добавляет возможность JavaScript взаимодействовать с устройствами ввода-вывода через свой API (написанный на C++), подключать другие внешние библиотеки, написанные на разных языках, обеспечивая вызовы к ним из JavaScript-кода. В основе Node.js лежит событийно-ориентированное и асинхронное (или реактивное) программирование с неблокирующим вводом/выводом.

Установим Node.js и менеджер пакетов для Node.js, набрав в консоли:

sudo apt-get update
sudo apt-get install nodejs npm 

Создадим папку для проекта, перейдём в неё и создадим файл package.json для хранения зависимостей создаваемого React.js приложения от модулей Node.js, набрав в консоли:

mkdir ./my-react-app
cd ./my-react-app
npm init --yes 

Имя проекта будет автоматически задано аналогичным имени папки проекта в которой создаётся package.json, при его создании. Для его исправления необходимо изменить следующую строку в package.json:

"name": "my-react-app" 

В дальнейшем при установке дополнительных модулей и библиотек Node.js необходимых для создаваемого React.js приложения или его вспомогательного окружения - будем указывать вспомогательные команды (--save или --save-dev), благодаря которым эти зависимости будут автоматически добавлены в файл: package.json в соответствующие разделы. Это позволит исключить из дистрибутива создаваемого приложения папку: node_modules, содержащую данные установленных дополнительных модулей. Конечному пользователю после разворачивания (копирования) приложения нужно будет лишь выполнить одну команду для установки на его компьютере "всего" вспомогательного окружения:

npm install 

Webpack

Webpack - сборщик который позволяет упаковывать JavaScript файлы приложения в один файл, дополнительно обрабатывая JavaScrip код при упаковке.

Установим Webpack (версии 3), набрав в консоли:

npm install --save-dev webpack

Пример простого JavaScript приложения

Рассмотрим реализацию примера простого приложения без использования Webpack. Для этого создадим в папке проекта - подпапку src с файлом index.js (содержащим код приложения), следующего содержания:

function component() {
  var element = document.createElement('div');

  // Для работы этой строки необходимо подключение библиотеки: Lodash.
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component()); 

После чего в папке проекта создадим файл index.html, следующего содержания:

<html>
  <head>
    <title>Getting Started</title>
    <script src="https://unpkg.com/lodash@4.16.6"></script>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html> 

Для проверки работы приложения откроем файл index.html в браузере и увидим надпись: "Hello webpack".

Основные недостатки такого приложения:

  • Из HTML кода не сразу очевидно, что JavaScript приложение зависит от внешней библиотеки: Lodash.
  • Если подключение библиотеки Lodash отсутствует или она подключена после приложения в HTML, то созданное нами приложение не будет функционировать.
  • Если библиотека Lodash подключена в HTML, но не используется, то браузер всё равно будет загружать код этой неиспользуемой библиотеки.

Пример сборки простого JavaScript с использованием Webpack

Модифицируем пример простого JavaScript приложения приведённого выше с использованием Webpack и устранением указанных недостатков. Для начала установим Lodash локально (а так же в зависимости package.json), набрав в консоли:

npm install --save lodash 

Изменим код index.js на:

import _ from 'lodash';

function component() {
  var element = document.createElement('div');

  // Lodash, уже импортирована в этом скрипте.
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component()); 

Изменим код index.html на:

<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    <script src="./dist/bundle.js"></script>
  </body>
</html> 

Кроме того, в папке проекта создадим подпапку dist и переместим в неё index.html. В этой папке будем хранить файлы которые в конечном итоге будут загружены пользователем в браузере. Т.е. в этой папке будут храниться в том числе файлы полученные в процессе сборки приложения Webpack-ом.

Соберём приложение с помощью Webpack-а, набрав в консоли:

./node_modules/.bin/webpack src/index.js dist/bundle.js 

Для проверки работы приложения откроем файл index.html в браузере и увидим надпись: "Hello webpack".

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

 ./node_modules/.bin/webpack -p src/index.js dist/bundle.js 

Использование файлов конфигурации для Webpack

Webpack поддерживает файлы конфигурации, позволяющие сократить количество вводимых данных в консоль при сборке приложения. Для рассмотренного выше JavaScript приложения, файл конфигурации webpack.config.js (в корневой директории проекта) будет выглядеть следующим образом:

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
}; 

Сборка приложения с помощью Webpack-а с использованием файла конфигурации будет выглядеть в консоли следующим образом:

./node_modules/.bin/webpack --config webpack.config.js 

Интеграция Webpack с NPM

Если в файл package.json (в корневой папке проекта), в секцию "scripts" добавить данные о сборщике ("build": "webpack"):

{
  ...
  "scripts": {
    ...
    "build": "webpack"
  },
  ...
} 

Внимание: не стоит забывать, что в package.json элементы перечисляются через запятую, но последний элемент её не имеет.

То для сборки приложения с помощью Webpack-а будет достаточно набрать в консоли:

npm run build 

Использование модулей для Webpack

Webpack поддерживает дополнительную обработку, объединяемых JavaScript файлов написанных с использованием расширения (JavaScript) ES2015, для работы кода таких файлов - в старых браузерах. Для активации такого функционала в Webpack установим Babel Core и Babel Loader (позволяет работать с JSX файлами):

npm install --save-dev babel-core
npm install --save-dev babel-loader 

После чего установим Babel пресеты: для ES2015 (официально ES6) и React (так как в дальнейшем приложения будут разрабатываться с использованием React.js), набрав в консоли:

npm install --save-dev babel-preset-es2015
npm install --save-dev babel-preset-react 

Создадим файл ".babelrc" в папке проекта с настройками конфигурации для Babel, следующего содержания:

{
  "presets": ["react", ["es2015", { "modules": false }]]
}
 

А так же исправим файл "webpack.config.js" в папке проекта:

const path = require('path');

module.exports = {
  entry: './src/app.js',
  output: { 
    path: path.resolve(__dirname, 'bin'),
    filename: 'app.bundle.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        include: path.resolve(__dirname, "src"),
        loader: 'babel-loader'
      }
    ]
  }
};  

Примечания:

  • Файл с исходным кодом приложения назван не index.js, а app.js.
  • Папка для вывода собранного приложения названа не dist, а bin.
  • А сам файл собранного приложения назван не bundle.js, а app.bundle.js.
  • Вместо параметра (и его значения): "include: path.resolve(__dirname, "src")", можно использовать параметр (и его значение): "exclude: /node_modules/,".

Примечания по Webpack-у

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