Webpack 5

Пошаговое введение в мир объединения приложений JS.

webpack - один из самых известных пакетов с накопительным пакетом. Вы можете использовать его, даже не подозревая об этом, например, Create-React-App использует webpack для объединения всех своих зависимостей. Он помогает разработчикам сосредоточиться на разработке и объединяет все ресурсы, модули и зависимости в один пакет. Теперь, когда вышел webpack 5, я подумал, что было бы неплохо познакомить всех с этой замечательной утилитой.

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

Так почему именно Webpack?

webpack - это сборщик статических модулей для современных приложений JavaScript. Когда webpack обрабатывает ваше приложение, он рекурсивно строит граф зависимостей, который включает каждый модуль в приложении. Скрытых зависимостей нет. Самое приятное, что нам нужно включить только один JS-файл, все остальные зависимости, внутренние и внешние, связаны внутри этого связанного файла.

Короче говоря, webpack - это единый инструмент для управления всем вашим кодом, а также ресурсами в одном месте.

Давайте начнем

Откройте новую папку и сначала запустите новый проект npm, используя «npm init».

Как только это будет сделано, пора добавить webpack. Поскольку это зависимость от разработчиков, мы используем параметр -D при установке.

npm i -D webpack webpack-cli

Я создал два отдельных файла JS, hw.js и button.js, и index.js действует как точка входа в приложение. Вы можете найти репо здесь.

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

const path = require('path');
module.exports={
 entry:'./src/index.js', the entry point to the application
 //this is where the bundled files will be placed
 output:{
  filename:'bundle.js',
  path:path.resolve(__dirname,'./dist'),
 },
 mode:'none'
}

Теперь добавьте сценарий сборки в package.json, чтобы сообщить webpack о создании нашего приложения. Это создаст папку dist с файлом bundle.js

"build": "webpack",

Теперь нам нужно импортировать этот файл bundle.js в наш HTML-файл, чтобы использовать его.

Погрузчики

При создании любого внешнего приложения существует несколько зависимостей, таких как HTML, JS, файлы стилей (CSS, SASS или LESS) и другие дополнительные ресурсы (изображения). По умолчанию webpack понимает JS, и если мы попытаемся импортировать зависимости, которые не известны webpack по умолчанию, обязательно возникнут ошибки сборки. Итак, нам нужно указать webpack, как импортировать разные модули. Именно здесь в игру вступают загрузчики.

Чтобы определить загрузчики, необходимо добавить новое свойство module в файл webpack.config. внутри объекта модуля необходимо добавить правила. Это правила, в которых отображаются расширения файлов и загрузчики.

Основное правило имеет свойство test, которое представляет собой regex (используется расширение файлов), и свойство use, которое представляет собой массив где вы определяете различные загрузчики.

module:{
 rules:[{
 test:/\.ext$/,
 use:[loader]
 }]
}

Давайте посмотрим на несколько сценариев:

1) Загрузка изображений: поскольку изображения представляют собой файлы, нам необходимо установить «загрузчик файлов».

module:{
 rules:[ {
 test:/\.(png|jpg)$/,
 use:['file-loader']
}]}

В webpack 5 для свойства publicPath по умолчанию установлено значение «авто». Но что, если бы у вас были изображения, размещенные в каком-либо CDN, вы можете укажите publicPath на этот адрес. Webpack автоматически построит путь src, добавив publicPath к изображению.

module.exports={
 entry:'./src/index.js', the entry point to the application
 //this is where the bundled files will be placed
 output:{
  filename:'bundle.js',
  path:path.resolve(__dirname,'./dist'),
  publicPath:'https://www.someCdn.com/'
 },
 mode:'none'
}

2) Загрузка стилей: чтобы добавить стили с помощью css или sass / scss, необходимо установить необходимые загрузчики. «style-loader» и «css-loader» являются необходимыми загрузчиками как для sass, так и для css. «sass-loader» и «node-sass» (зависимость для обработки SASS в CSS) требуются в случае файлов sass / scss.

{
  test:/\.css$/,
  use:[style-loader', 'css-loader']
},
{
  test:/\.(scss|sass)$/,
  use:[style-loader', 'css-loader','sass-loader']
}

Загрузчики разрешаются справа налево, поэтому scss- ›css-›, а затем style-loader добавляет их в html, используя тег стиля.

3) Загрузка современных функций javascript: стандарты ECMA, которым соответствует JS, обновляются каждый год. Но не все браузеры могут обновлять и поддерживать эти функции. Для этого нам нужно использовать что-то, известное как транспилятор. Транспилятор преобразует последний код, например, из ES7 в стандартный JavaScript. Babel, самый известный из транспиляторов JS, предоставляет «babel-loader», который добавляется в конфигурацию webpack.

Необходимые devDependencies: «@ babel / core», «@ babel / plugin-scheme-class-properties», «@ babel / preset-env» и «babel-loader»,

{
 test:/\.js$/,
 exclude:/node_modules/,
 use:{ 
  loader:'babel-loader', 
  options:{
   presets:['@babel/preset-env'],
   plugins:['@babel/plugin-proposal-class-properties']
  }
 }
}

@ babel / plugin-scheme-class-properties: - плагин, используемый для поддержки функций класса JS. В Babel предустановка - это набор подключаемых модулей, используемых для поддержки определенных языковых функций.

С определенными загрузчиками объект модуля должен выглядеть так:

module:{
 rules:[
 {
  test:/\.(png|jpg)$/,
  use:['file-loader']
 },
 {
  test:/\.css$/,
  use:[style-loader', 'css-loader']
 },
 {
  test:/\.(scss|sass)$/,
  use:[style-loader', 'css-loader','sass-loader']
 },
 {
  test:/\.js$/,
  exclude:/node_modules/,
  use:{ 
   loader:'babel-loader', 
   options:{
    presets:['@babel/preset-env'],
    plugins:['@babel/plugin-proposal-class-properties']
   }
  }
 },
{
 test:/\.hbs$/,
 use:['handlebars-loader']
 }
]}

* Примечание. Я буду использовать ручки в приведенном ниже примере шаблона html. Вам необходимо установить «handlebars-loader» как зависимость разработчика и «handlebars» как обычную зависимость.

Плагины

С помощью загрузчиков вы указываете webpack, как загружать различные модули и файлы зависимостей. Но что, если вам нужно добавить определенные варианты поведения к тому, как связано приложение. Здесь в игру вступают плагины.

Плагины могут помочь изменить способ создания самих пакетов. Например, uglifyJSPlugin берет файл bundle.js и минимизирует его содержимое, чтобы уменьшить размер пакета.

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

module.exports={
 entry:'./src/index.js',
 output:{
  filename:'bundle.[contenthash].js',
  path:path.resolve(__dirname,'./dist'),
  publicPath:'/dist/'
 },
 mode:'none',
 module:{},
 plugins:[]
}

Давайте посмотрим на несколько сценариев:

1) Сокращение. При минимизации приложения размер пакета приложения уменьшается, и оно потребляет меньше интернет-трафика. Для минимизации нам нужно использовать «terser-webpack-plugin», в webpack 5 он встроен.

const TerserPlugin =  require('terser-webpack-plugin')
plugins:[new TerserPlugin()]

2) Извлечение CSS в отдельный пакет: извлечение CSS в отдельный пакет позволяет дополнительно уменьшить размер файла JS. «mini-css-extract-plugin» - это плагин для веб-пакетов, который помогает нам в этом.

const MiniCSSPlugin = require('mini-css-extract-plugin');
plugins:[
 new MiniCSSExtractPlugin({
      filename:'style.css'
 })
]

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

{
 test:/\.css$/,
 use:[MiniCSSPlugin.loader, 'css-loader']
}

3) Очистка выходной папки перед сборкой: Как можно заметить, каждый раз, когда создается новая сборка, выходная папка становится все более переполненной. Единственное решение здесь - очистить папку перед запуском сценария сборки. Лучший способ сделать это - автоматизировать процесс, и у нас есть плагин, который поможет сделать это «clean-webpack-plugin»

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
plugins:[
 new CleanWebpackPlugin({
  cleanOnceBeforeBuildPatterns:['**/*',path.join(process.cwd(),
  'extra/**/*')]
 })
]

* Примечание: «** / *» относится к папке dist (выходной путь), если вы хотите очистить другую папку, находящуюся за пределами выходного пути, вы можете использовать «path.join» (process.cwd (), 'extra / ** / *') »

4) Автоматизация шаблона HTML. До сих пор index.html приходилось создавать и обновлять вручную. В Webpack есть плагин для автоматизации этого процесса, мы можем использовать наш собственный шаблон или он генерирует шаблон по умолчанию. Плагин называется «html-webpack-plugin».

const HtmlWebpackPlugin = require('html-webpack-plugin')
plugins:[new HtmlWebpackPlugin(
{
 title:"Test App",
 template:"src/index.hbs", //handlebar file
 filename:'index.html'
})]

К свойствам, определенным в параметрах, можно получить доступ с помощью переменной htmlWebpackPlugin.options.

Сгенерированный шаблон:

Использование кеширования браузера

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

Чтобы добавить кеширование, можно использовать ключевое слово «[contenthash]» при определении имени файла:

output:{
 filename:'bundle.[contenthash].js',
 path:path.resolve(__dirname,'./dist'),
 publicPath:'/dist/'
},
plugins:[
 new MiniCSSExtractPlugin({
      filename:'style.[contenthash].css'
 })
]

Определение отдельных конфигураций для рабочей среды и среды разработки

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

* Примечание: по умолчанию TerserPlugin используется в производственном режиме, поэтому его можно вообще удалить из обеих конфигураций.

Для определения типа сборки можно использовать режим: mode: ’development’ или mode: ’production’,

С отдельными конфигами нам нужно определить новые скрипты в package.json:

“dev”: “webpack — config webpack.dev.config.js”,
“build”: “webpack — config webpack.prod.config.js”

Добавление сервера разработки

При создании любого приложения вносятся несколько изменений. Но создавать приложение вручную после каждого небольшого изменения стало бы головной болью. Это можно сделать, добавив «webpack-dev-server» (-D).

После установки webpack-dev-server мы можем обновить файл config.

devServer:{
 contentBase:path.resolve(__dirname,'./dist'),
 index:'index.html',
 port:8081,
 writeToDisk:true
},

После настройки devServer приложению также предоставляется порт, на котором оно будет размещено, что избавляет от необходимости размещать его отдельно. Также необходимо обновить скрипт для разработчиков:

“dev”: “webpack serve — config webpack.dev.config.js —-hot”
-- hot: is for hot reloading, so that every time a changes is made it would update the application build

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