Webpack

Why does Webpack exist?

Webpack - это сборщик модулей. Он анализирует модули приложения, создает граф зависимостей, затем собирает модули в правильном порядке в один или более бандл (bundle), на который может ссылаться файл «index.html».

App.js ->       |
Dashboard.js -> | Bundler | -> bundle.js
About.js ->     |

What problem is webpack solving?

Обычно, при создании приложения на JavaScript, код разделяется на несколько частей (модулей). Затем в файле «index.html» необходимо указать ссылку на каждый скрипт.

<body>

    ...
    
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="libs/react.min.js"></script>
    <script src='src/admin.js'></script>
    <script src='src/dashboard.js'></script>
    <script src='src/api.js'></script>
    <script src='src/auth.js'></script>
    <script src='src/rickastley.js'></script>
</body>

What problem is webpack solving?

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

<body>

    ...
    
    <script src='dist/bundle.js'></script>
</body>

В папке dist обычно храним наш bundle.js который формируется нашим сборщиком (webpack).

What problem is webpack solving?

При необходимости можно заставить webpack осуществить некоторые преобразования модулей перед их добавлением в bundle. Например, преобразование SASS/LESS в обычный CSS, или современного JavaScript в ES5 для старых браузеров.

Webpack

npm init

Установка webpack. В вашем проекте должен быть файл package.json

Установка webpack. В вашем проекте должен быть файл package.json

npm i webpack webpack-cli --save-dev

Теперь в вашем проекте будет добавлен webpack в dev dependencies.

Webpack

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

Теперь обновим скрипт в нашем packege.json

Как только все будет сделано, вы можете запустить Webpack, набрав:

npm run build

Webpack

По умолчанию, Webpack (начиная с 4-й версии) не требует никакой настройки, если вы соблюдаете эти правила:

  1. точкой входа вашего приложения является ./src/index.js
  2. вывод (output) размещается в ./dist/main.js
  3. Webpack работает в production mode (режим производства)

Webpack

Если у нас точка вода в другом месте можем это указать в конфиге.

// webpack.config.js
module.exports = {
    entry: './src/index.js'
}

Webpack

Конечно, если понадобится, вы сможете настроить каждую мельчайшую деталь в Webpack. Конфигурационный файл Webpack -webpack.config.js хранится в корневой директории проекта.

// webpack.config.js
module.exports = {
    entry: './src/index.js'
}

Webpack

По умолчанию, вывод размещается в ./dist/main.js. В нижеприведенном примере, результат работы в Webpack генерируется в файле app.js:

// webpack.config.js

const path = require('path');

module.exports = {
  /*...*/
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'app.js'
  }
  /*...*/
}

Webpack

С помощью Webpack можно использовать оператор import или require в своем JavaScript коде для того, чтобы подключать файлы любого типа (например, CSS).

// webpack.config.js

const path = require('path');

module.exports = {
  /*...*/
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'app.js'
  }
  /*...*/
}

Webpack

По умолчанию при создании графика зависимостей на основе операторов import / require() вебпак способен обрабатывать только JavaScript и JSON-файлы.

Webpack

Едва ли в своем приложении вы решитесь не ограничиться JS и JSON-файлами, скорее всего, вам также потребуются стили, SVG, изображения и т.д. Вот где нужны лоадеры. Основной задачей лоадеров, как следует из их названия, является предоставление вебпаку возможности работать не только с JS и JSON-файлами.

Webpack

В Webpack загрузчики являются аналогами задач (tasks) в Grunt и Gulp. Они принимают содержимое файлов, а затем преобразуют его необходимым образом и включают результат преобразования в общую сборку. Например, они могут компилировать TypeScript, загружать компоненты Vue.js и многое другое.

Webpack

Например, в своем коде вы можете использовать:

import 'style.css' 

Указав конфигурацию данного загрузчика в файле webpack.config.js:

module.exports = {
  /*...*/
  module: {
    rules: [
      { test: /\.css$/, use: 'css-loader' }
    ]
  }
  /*...*/
}

Предварительно данный лоадер нужно установить.

npm install --save-dev css-loader

Webpack

Однако для того, чтобы наши стили работали корректно, нужно добавить еще один лоадер. Благодаря css-loader мы можем импортировать CSS-файлы. Но это не означает, что они будут включены в DOM. Мы хотим не только импортировать такие файлы, но и поместить их в тег <style>, чтобы они применялись к элементам DOM. Для этого нужен style-loader.

npm i style-loader --save-dev

Webpack

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
    }]
  }
}

Обратите внимание, что поскольку для обработки CSS-файлов используется два лоадера, значением свойства use является массив.

Webpack

npm install --save-dev babel-loader @babel/core @babel/preset-env webpack

Лоадеры могут использоваться не только для импорта файлов, но и для их преобразования. Самым популярным является преобразование JavaScript следующего поколения в современный JavaScript с помощью Babel. Для этого используется babel-loader.

Webpack

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  }
}

Webpack plugins

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

Webpack plugins

HTMLWebpackPlugin

Плагин HTMLWebpackPlugin автоматически создает HTML-файл в дириктории с бандлом с уже подключенным скриптом.

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin(),
  ]
}
npm i --save-dev html-webpack-plugin

Webpack plugins

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

const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin(),
    new CleanWebpackPlugin(),
  ]
}
npm install --save-dev clean-webpack-plugin

Webpack environments

Данные режимы (появившиеся в 4-й версии Webpack) настраивают среду, в которой будет работать Webpack. Режим может быть настроен на development или production (по умолчанию стоит production).

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
      { test: /\.(js)$/, use: 'babel-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin()
  ],
  mode: 'development',
}

Webpack environments

Режим development:

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

Webpack watch

Webpack может автоматически перестраивать бандл, когда в вашем приложении происходят изменения. Для этого добавьте данный скрипт:

{
  "name": "test-app",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "build": "webpack",
    "watch": "webpack --watch"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.58.1",
    "webpack-cli": "^4.9.0"
  }
}
npm run watch

Webpack watch

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

Webpack source map

С транспилированным кодом, зачастую, возникают проблемы при отладке кода в браузере или анализе ошибок. Так как транспилированный и трудночитаемый JavaScript, а не оригинальный код, затрудняет поиск и исправление ошибок. Source Map — это JSON-файл, который содержит информацию о том, как транспилировать код обратно в исходный код.

Source Maps можно сгенерировать, используя свойство конфигурации devtool:

Webpack source map

const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    module: {
        rules: [
            { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
            { test: /\.(js)$/, use: 'babel-loader' }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin()
    ],
    mode: 'development',
    devtool: 'inline-source-map',
}

Webpack source map

  • none: не добавляет Source Maps
  • source-map: идеально подходит для режима production, предоставляет отдельную Source Map, которую можно свернуть и добавляет ссылку в бандл, чтобы инструменты разработки знали о том, что Source Map доступна
  • inline-source-map: идеально подходит для режима development, встраивает Source Maps в качестве data:URL

Webpack

By Oleg Rovenskyi