Webpack с Typescript
Используемый во многих современных проектах, Webpack — это удивительный инструмент, оптимизирующий ресурсы приложений, чтобы они работали более эффективно и результативно на любом устройстве. Webpack помогает компилировать и объединять модули в один файл, уменьшая HTTP-запросы и повышая производительность приложения.
С помощью webpack код TypeScript компилируется в файл JavaScript, удобный для браузера. С помощью загрузчиков веб-пакетов вы также можете конвертировать файлы SASS и LESS в один файл пакета CSS.
В этой статье мы узнаем, как использовать webpack для компиляции TypeScript в JavaScript, объединения исходного кода в один файл JavaScript и использования исходной карты для отладки. Мы также рассмотрим, как использовать плагины webpack.
Чтобы следовать этому руководству, вам понадобится следующее:
- npm
- Node.js: если у вас уже установлен Node.js, убедитесь, что он ≥v8.x.
- Базовые знания TypeScript
Webpack loaders
По умолчанию webpack понимает только файлы JavaScript, рассматривая каждый импортированный файл как модуль. webpack не может компилировать или связывать файлы, отличные от JavaScript, поэтому он использует загрузчик.
Загрузчики сообщают вебпаку, как компилировать и связывать статические ресурсы. Они используются для компиляции модулей TypeScript в JavaScript, обработки стилей приложений и даже анализа кода с помощью ESLint.
Несколько загрузчиков включают ts-loader, css-loader, style-loader и другие; мы обсудим их позже в этом уроке.
Настройка Webpack и TypeScript
Начнем с настройки нашего проекта. Во-первых, на вашем компьютере должен быть установлен TypeScript. Чтобы установить TypeScript глобально, используйте следующую команду:
npm install -g typescript
Глобальная установка TypeScript избавляет от необходимости устанавливать TypeScript каждый раз, когда вы начинаете новый проект.
Далее мы установим пакеты webpack и ts-loader в качестве зависимостей в нашем проекте:
npm init -y npm install -D webpack webpack-cli ts-loader webpack-dev-server>
Конфигурация Webpack
По умолчанию webpack не нуждается в файле конфигурации. Предполагается, что точка входа для вашего src/index.js
проекта есть и будет выводить минимизированный и оптимизированный результат в dist
/ main.js
во время production.
Если вы хотите использовать плагины или загрузчики, вам нужно будет использовать файл конфигурации webpack, позволяющий указать, как webpack будет работать с вашим проектом, какие файлы компилировать и где будет находиться выходной файл пакета.
Давайте добавим файл конфигурации webpack в наш проект. В корневой папке проекта создайте файл webpack.config.js
со следующими конфигурациями:
const path = require('path'); module.exports = { entry: './src/index.ts', module: { rules: [ { test: /\.ts?$/, use: 'ts-loader', exclude: /node_modules/, }, ], }, resolve: { extensions: ['.tsx', '.ts', '.js'], }, output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, devServer: { static: path.join(__dirname, "dist"), compress: true, port: 4000, }, };
Давайте рассмотрим некоторые параметры конфигурации веб-пакета. Во-первых, entry
опция является отправной точкой для приложения, где webpack начинает строить граф зависимостей. webpack перейдет к другим модулям на основе файла входа.
Опция output
сообщает webpack, где сохранять файлы пакетов, и позволяет вам назвать файл пакета. Наконец, module
опция сообщает webpack, как обрабатывать модули с определенными правилами с помощью загрузчиков.
Конфигурация TypeScript
Файл конфигурации TypeScript управляет компиляцией TypeScript в JavaScript и определяет различные параметры компилятора, необходимые для транспиляции TypeScript.
В корневой папке проекта создайте файл tsconfig.json
и добавьте следующие конфигурации:
{ "compilerOptions": { "noImplicitAny": true, "target": "ES5", "module": "ES2015" } }
Параметр target
— это версия JavaScript, в которую вы хотите транспилировать TypeScript, а module
формат используемого оператора импорта. Вы можете установить для модуля CommonJS, ES6 или UMD, поскольку webpack будет обрабатывать все модульные системы.
Конфигурация пакета
Теперь нам нужно добавить скрипт вебпака, который будет запускать файл webpack.config.js
для нас.
Чтобы добавить сценарий webpack, откройте файл package.json
и добавьте следующие сценарии в параметр сценария:
"develop": "webpack-dev-server --mode development", "build" : "webpack --mode production"
Теперь файл package.json
будет содержать следующие параметры конфигурации:
{ "name": "webpack-setup", "version": "1.0.0", "description": "", "main": "src/index.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "develop": "webpack-dev-server --mode development", "build": "webpack --mode production" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^6.7.1", "html-webpack-plugin": "^5.5.0", "mini-css-extract-plugin": "^2.6.1", "ts-loader": "^9.4.1", "webpack": "^5.74.0", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.11.1" } }
Теперь давайте создадим простую программу на TypeScript, которая будет вычитать два числа. Внутри src
папки создайте файл index.ts
и добавьте следующий код TypeScript:
import { subtract } from "./app"; function init() { const form = document.querySelector("form"); form?.addEventListener("submit", submitHandler); } function submitHandler(e: Event) { e.preventDefault(); const num1 = document.querySelector("input[name='firstnumber']") as HTMLInputElement; const num2 = document.querySelector("input[name='secondnumber']") as HTMLInputElement; const result = subtract(Number(num1.value), Number(num2.value)); const resultElement = document.querySelector("p"); if (resultElement) { resultElement.textContent = result.toString(); } } init();
Затем создайте еще один файл app.ts
и добавьте следующий код:
export function subtract(firstnumber: number, secondnumber: number): number { return firstnumber - secondnumber; }
Запуск develop
скрипта запустит приложение в режиме разработки:
npm run develop
Запуск build
скрипта запустит приложение в рабочем режиме:
npm run build
После запуска команды сборки webpack преобразует два файла TypeScript в код JavaScript и сгенерирует файл bundle.js
внутри папки dist
.
Создание HTML-страниц с помощью HtmlWebpackPlugin
HtmlWebpackPlugin
позволяет вебпаку создавать стандартную HTML-страницу, которая будет обслуживать сгенерированные файлы пакетов.
Когда имя файла пакета изменяется или хэшируется, HTMLWebpackPlugin
обновляются имена файлов на HTML-странице. Во-первых, для установки HtmlWebpackPlugin
выполните следующую команду:
npm install html-webpack-plugin --save-dev
Далее нам нужно импортировать и добавить HtmlWebpackPlugin
в плагин конфигурации webpack следующий параметр:
const HtmlWebpackPlugin = require("html-webpack-plugin"); const path = require('path'); module.exports = { entry: './src/index.ts', module: { rules: [ { test: /\.ts?$/, use: 'ts-loader', exclude: /node_modules/, } ], }, resolve: { extensions: ['.tsx', '.ts', '.js'], }, output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new HtmlWebpackPlugin({ title: 'our project', template: 'src/custom.html' }) ], devServer: { static: path.join(__dirname, "dist"), compress: true, port: 4000, }, };
Шаблон представляет собой пользовательский HTML-файл, сгенерированный HtmlWebpackPlugin
для внедрения на HTML-страницу. Чтобы создать собственный HTML-код, внутри src
папки создайте файл custom.html
и добавьте следующий HTML-код:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> <div class="cal"> <center> <form><br> <p>Result : <span id="display"></span></p> <input type="number" class="input" placeholder="Enter first number" name="firstnumber" value="1" min="1" min="9" /><br> <input type="number" class="input" placeholder="Enter second number" name="secondnumber" value="1" min="1" min="9" /><br><br> <button type="submit" class="button">Subtract</button> </form> </center> </div> </body> </html>
Вам не нужно включать теги script или link в пользовательский HTML-код; HtmlWebpackPlugin
позаботится об этом, связав URL-адрес файла пакета со сгенерированной страницей.
Объединение CSS сMiniCSSExtractPlugin
css-loader сообщает вебпаку, как работать с модулем CSS. Он интерпретирует @import
и URL()
как import/require()
и разрешает их. css-loader позволяет веб-пакету компилировать все файлы CSS и конвертировать их в формат JavaScript.
Объединение файлов CSS с загрузчиком стилей приводит к тому, что стили HTML-страницы не отвечают до тех пор, пока они не Bundle.js
будут полностью загружены. Загрузчик стилей внедряет CSS в DOM, но связанный файл JavaScript должен полностью загрузиться перед внедрением стилей. Чтобы решить эту проблему, мы можем использовать MiniCssExtractPlugin
.
Извлекает MiniCssExtractPlugin
файлы CSS и объединяет их в один bundle.css
файл. Это полезно для уменьшения размера ваших ресурсов CSS и предотвращения ненужных HTTP-запросов для их загрузки.
Мы можем установить css-loader, MiniCssExtractPlugin
выполнив в терминале приведенные ниже команды:
npm install css-loader --save-dev npm install mini-css-extract-plugin --save-dev
Теперь давайте добавим css-загрузчик и MiniCssExtractPlugin
в webpack.config.js
файл.
В верхней части файла webpack.config.js
импортируйте MiniCssExtractPlugin
модуль, используя приведенный ниже код:
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
Затем мы добавим к свойству новое правило rules
следующим образом:
… { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"] } …
Когда css-loader компилирует все файлы CSS в JavaScript, MiniCssExtractPlugin.loader
загружает CSS в файл пакета CSS.
Далее мы добавим MiniCssExtractPlugin
в плагин опцию следующим образом:
plugins: [ new HtmlWebpackPlugin({ title: 'our project', // Load a custom template (lodash by default) template: 'src/custom.html' }), new MiniCssExtractPlugin({ filename:"bundle.css"}) ]
Теперь, когда мы настроили css-loader
и MiniCssExtractPlugin
, давайте создадим файл CSS и импортируем его в формат index.ts
. Внутри src
папки создайте index.css
файл и добавьте следующий код CSS:
form { background-color:pink; margin-top:100px; border-radius:40px; } .cal{ width:550px; height:300px; margin-left:400px; } .button{ border-radius:10px; margin-top:20px; margin-bottom:20px; } .input{ border-radius:10px; margin-top:40px; }
Внутри index.ts
импортируйте стиль CSS следующим образом:
import styles "./main.css"
При запуске npm run build
CSS будет объединен и применен к index.html
. Когда вы запускаете приложение в режиме разработки и открываете его http://localhost:4000
в браузере, оно должно выглядеть следующим образом:
Минимизация CSS
Мы можем использовать css-minimizer-webpack-plugin
, чтобы уменьшить размер файлов CSS, удалив неиспользуемые правила CSS и оставив только необходимые.
css-minimizer-webpack-plugin
анализирует скомпилированный файл CSS и находит все неиспользуемые стили. Затем этот плагин удалит эти неиспользуемые стили из вашего окончательного файла CSS, тем самым уменьшив его размер.
Запустите команду установки ниже, чтобы установить css-minimizer-webpack-plugin
:
npm install css-minimizer-webpack-plugin --save-dev
Добавим css-minimizer-webpack-plugin
в конфигурацию веб-пакета. Сначала импортируйте плагин следующим образом:
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
Затем мы добавим новое свойство оптимизации в конфигурацию веб-пакета следующим образом:
optimization: { minimizer: [ new CssMinimizerPlugin() ], }
Когда мы запустим команду сборки, bundle.css
она будет минимизирована, но bundle.js
не будет.
Минимизатор по умолчанию bundle.js
был заменен установленной нами опцией минимизации. Чтобы решить эту проблему, нам нужно минимизировать JavaScript с помощью TerserWebpackPlugin
.
Минимизация JavaScript
В текущей версии вебпака на момент написания, v5.74.0 и новее, вам не нужно устанавливать пакет, TerserWebpackPlugin
поскольку он включен в комплект поставки. Сначала нам нужно импортировать TerserWebpackPlugin
:
const TerserPlugin = require("terser-webpack-plugin");
Затем добавьте TerserPlugin
к опции минимизации следующее:
optimization: { minimizer: [ new CssMinimizerPlugin(), new TerserPlugin() ], }
Если вы запустите build
сценарий и посмотрите файлы пакета в dist
папке, вы увидите, что JavaScript и CSS минимизированы.
С использованием Copywebpackplugin
Мы можем настроить веб-пакет для копирования ресурсов приложения из папки разработки в папку сборки, dist
используя CopyWebpackPlugin
. Этот плагин может копировать в папку такие файлы, как изображения, видео и другие ресурсы dist
.
Установите CopyWebpackPlugin
с помощью команды ниже:
npm install copy-webpack-plugin --save-dev
Теперь давайте добавим CopyWebpackPlugin
конфигурацию веб-пакета. Импортируйте плагин следующим образом:
const CopyPlugin = require("copy-webpack-plugin");
Далее мы добавим CopyWebpackPlugin
в плагин опцию. Свойство from
— это папка, из которой мы будем копировать, а to
свойство — это папка в dist
каталоге, в которую нужно скопировать все файлы:
... plugins: [ new HtmlWebpackPlugin({ title: 'our project', // Load a custom template (lodash by default) template: 'src/custom.html' }), new MiniCssExtractPlugin({ filename:"bundle.css"}), new CopyPlugin({ patterns: [ { from: "src/img", to: "img" } ] }), ] ...
Создайте новую img
папку и добавьте в нее изображения. После запуска команды сборки изображения будут скопированы в файл dist/img
.
Отладка с использованием sourceMap
Когда мы build
создаем пакет путем компиляции файлов TypeScript в файлы JavaScript, нам может потребоваться отладить и протестировать файл пакета с помощью DevTool нашего браузера.
Когда вы отлаживаете свой код с помощью DevTool браузера, вы заметите, что отображаются только файлы пакета. Всякий раз, когда в нашем коде TypeScript возникает ошибка, она будет указана только в файле пакета, что затрудняет отслеживание ошибок обратно в TypeScript для исправления. Однако, имея карту исходного кода, мы можем легко отладить TypeScript с помощью нашего DevTool:
Карты исходного кода отображают исходный исходный файл, что упрощает отладку TypeScript и исправление пакетов и минифицированного кода JavaScript.
Файлы исходных карт .map
содержат сведения как об исходных исходных файлах, так и о файлах пакета. DevTools использует этот файл для сопоставления исходного исходного файла с файлом пакета.
Чтобы сгенерировать .map
файлы для файлов пакета, нам необходимо настроить как веб-пакет, так и TypeScript. В файле конфигурации TypeScript добавьте sourceMap
параметр компилятора и установите для него значение true
:
{ "compilerOptions": { "noImplicitAny": true, "target": "ES5", "module": "ES2015", "sourceMap": true } }
Далее мы добавим devtool
свойство в конфигурацию веб-пакета и установим для него значение true
, сообщая веб-пакету генерировать соответствующую исходную карту для каждого файла пакета:
module.exports = { devtool: 'source-map', ... }
Когда вы запустите команду сборки, вы сможете напрямую отлаживать исходный исходный код:
Заключение
Поскольку популярность TypeScript продолжает расти, веб-пакет стал важным вариантом для разработчиков, желающих оптимизировать свои проекты. С помощью плагинов веб-пакета мы можем оптимизировать ресурсы приложения TypeScript.
В этом уроке мы пошагово рассмотрели процесс настройки веб-пакета с помощью TypeScript.