Сохраняйте контроль: руководство по Webpack и React, Pt. 2

Опубликовано: 2022-03-11

В первой части этого руководства по React-Webpack мы обсудили, как настроить загрузчики и выполнить оптимизацию. Теперь мы рассмотрим более продвинутые методы, связанные с конкретными вариантами использования конфигурации React/Webpack.

TypeScript и React с Webpack: вход в Babel

Есть несколько способов использования TypeScript в вашем проекте React. Хотя ts-loader — хороший вариант, я хотел бы сосредоточиться на том, как транспилировать TypeScript с помощью @babel/preset-typescript , потому что многие библиотеки публикуют плагины Babel для оптимизации времени компиляции. Помимо обработки файлов TypeScript, это позволит нам использовать плагины Babel, предоставляемые различными библиотеками, такими как styled-components или react-intl.

Первое, что нам нужно сделать, это установить зависимости TypeScript и Babel:

 npm install -D typescript @babel/preset-typescript @types/react @types/react-dom

Затем мы создадим файл конфигурации TypeScript с помощью программы командной строки tsc :

 ./node_modules/.bin/tsc -init --lib dom --jsx react --isolatedModules

Приведенная выше команда создаст tsconfig.json , подходящий для написания кода для среды браузера. Параметр --isolatedModules некоторые ограничения, которые гарантируют, что код, который вы пишете, будет совместим с @babel/plugin-transform-typescript . Эта опция полезна для того, чтобы ваша IDE предупреждала вас, когда вы пишете код таким образом, который Babel не сможет преобразовать.

Далее мы собираемся обновить babel.config.js , добавив новый пресет:

 @@ -6,7 +6,8 @@ module.exports = { modules: false } ], - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], plugins: [ "@babel/plugin-transform-runtime",

И включите расширение файла .ts в webpack.config.js :

 @@ -11,7 +11,7 @@ module.exports = function(_env, argv) { return { devtool: isDevelopment && "cheap-module-source-map", - entry: "./src/index.js", + entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "dist"), filename: "assets/js/[name].[contenthash:8].js", @@ -20,7 +20,7 @@ module.exports = function(_env, argv) { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", @@ -61,6 +61,9 @@ module.exports = function(_env, argv) { } ] }, + resolve: { + extensions: [".js", ".jsx", ".ts", ".tsx"] + }, plugins: [ isProduction && new MiniCssExtractPlugin({

Приведенной выше конфигурации достаточно, чтобы иметь возможность транспилировать наш код, но на самом деле она не проверяет его. Нам нужно будет выполнить проверку типов в отдельном параллельном процессе с помощью fork-ts-checker-webpack-plugin .

Во-первых, нам нужно установить его:

 npm install -D fork-ts-checker-webpack-plugin

Затем мы добавим его в раздел plugins в webpack.config.js :

 @@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -78,6 +79,9 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new ForkTsCheckerWebpackPlugin({ + async: false }) ].filter(Boolean), optimization: {

Указание async: false предотвратит создание Webpack недопустимого кода и покажет ошибки компиляции в оверлее при запуске сервера разработки.

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

CSS, улучшенный через Webpack

В предыдущей статье мы рассмотрели основные стили с помощью css-loader . Есть несколько способов улучшить эту конфигурацию.

Предлагаемая конфигурация будет использовать преимущества модулей CSS, технологий Sass и PostCSS. Хотя они в некотором роде дополняют друг друга, вам не нужно использовать их все одновременно. В окончательной настройке будут включены все вышеперечисленные плагины, и мы оставим на ваше усмотрение возможность пропустить что-то, если вы уверены, что «вам это не понадобится».

CSS-модули

Модули CSS решают проблему глобальной области видимости в файлах CSS, генерируя рандомизированное уникальное имя для каждого класса CSS. С точки зрения файла JavaScript, использующего модуль CSS, ассоциация между исходным именем класса и рандомизированным представлена ​​​​объектом, экспортируемым загрузчиком. Он позволяет находить и использовать классы, указанные в файле CSS, таким образом, что случайное столкновение становится практически невозможным.

Поддержка модулей CSS уже включена в css-loader . Теперь нам нужно добавить новое правило, чтобы указать, когда используются модули CSS:

 @@ -33,11 +33,25 @@ module.exports = function(_env, argv) { }, { test: /\.css$/, use: [ isProduction ? MiniCssExtractPlugin.loader : "style-loader", "css-loader" ] }, + { + test: /\.module.css$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + modules: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {

При этом любой файл, оканчивающийся на .module.css , будет обрабатываться с включенными модулями CSS.

PostCSS

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

Во-первых, мы собираемся установить необходимые зависимости:

 npm install -D postcss-loader postcss-import postcss-preset-env

И обновите нашу конфигурацию CSS:

 @@ -47,9 +47,11 @@ module.exports = function(_env, argv) { { loader: "css-loader", options: { - modules: true + modules: true, + importLoaders: 1 } - } + }, + "postcss-loader" ] }, {

Мы собираемся настроить PostCSS с помощью следующих плагинов:

  • postcss-import : позволяет PostCSS обрабатывать операторы @import
  • postcss-preset-env : применяет полифиллы для поддержки современных функций CSS в большинстве браузеров.

Создайте файл с именем postcss.config.js и заполните его следующим:

 module.exports = { plugins: { "postcss-import": {}, "postcss-preset-env": {} } };

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

Sass/SCSS

Sass — еще один популярный фреймворк для обработки CSS. В отличие от PostCSS, Sass поставляется с «батарейками в комплекте». По умолчанию Sass предлагает поддержку вложенных правил, примесей и правил перезаписи для обеспечения обратной совместимости. Хотя PostCSS стремится сохранить стандартный синтаксис CSS, синтаксис Sass может отличаться от спецификации CSS. Несмотря на это, Sass является настолько универсальным решением, что его использование для создания CSS может оказаться более простым вариантом, но в зависимости от ваших требований.

Во-первых, мы собираемся установить необходимые зависимости:

 npm install -D sass-loader node-sass resolve-url-loader

Затем добавьте новый загрузчик в нашу конфигурацию Webpack:

 @@ -38,6 +38,25 @@ module.exports = function(_env, argv) { "css-loader" ] }, + { + test: /\.s[ac]ss$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + importLoaders: 2 + } + }, + "resolve-url-loader", + { + loader: "sass-loader", + options: { + sourceMap: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {

Мы предупредительно решили пару проблем с приведенным выше фрагментом:

  1. Мы представили resolve-url-loader после sass-loader , чтобы относительный импорт работал из @import ed Sass.

  2. Мы указали параметр importLoaders для css-loader для обработки файлов @import -ed с использованием следующих за ним загрузчиков.

С приведенной выше конфигурацией мы можем начать создавать наши стили, используя Sass/SCSS в дополнение к модулям PostCSS и CSS, которые мы описали ранее. Хотя все эти параметры можно включить одновременно, вам не обязательно использовать их все в одном проекте, поэтому вы можете выбрать тот инструмент, который лучше всего соответствует вашим требованиям.

Веб-воркеры

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

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

Во-первых, нам нужно установить worker-loader :

 npm install -D worker-loader

Затем добавьте его в наш файл конфигурации:

 @@ -31,6 +31,10 @@ module.exports = function(_env, argv) { } } }, + { + test: /\.worker\.js$/, + loader: "worker-loader" + }, { test: /\.css$/, use: [

Теперь все, что вам нужно сделать, чтобы начать использовать веб-воркеры, — это создать экземпляр класса, импортированного из файла, оканчивающегося на .worker.js , который реализует обычный API-интерфейс Worker.

Сервисные работники

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

Webpack упрощает настройку сервис-воркеров для вашего приложения с помощью модуля workbox-webpack-plugin. Во-первых, нам нужно установить его:

 npm install -D workbox-webpack-plugin

Затем мы добавим плагин в раздел plugins нашей конфигурации Webpack:

 @@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const WorkboxPlugin = require("workbox-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -75,6 +76,11 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new WorkboxPlugin.GenerateSW({ + swDest: "service-worker.js", + clientsClaim: true, + skipWaiting: true }) ].filter(Boolean), optimization: {

В приведенной выше конфигурации используются следующие параметры:

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

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

Наконец, нам нужно зарегистрировать сервис-воркера, когда пользователь открывает наше приложение:

 @@ -2,3 +2,9 @@ import React from "react"; import ReactDOM from "react-dom"; ReactDOM.render(<h3>React App</h3>, document.getElementById("root")); + +if ("serviceWorker" in navigator) { + window.addEventListener("load", () => { + navigator.serviceWorker.register("/service-worker.js"); + }); +}

Сервисные работники способны на гораздо большее, чем добавление автономных возможностей в наше приложение. Если вам нужна большая степень контроля над поведением сервис-воркера, вы можете вместо этого использовать подключаемый модуль InjectManifest . Написав свой собственный файл сервис-воркера, вы также можете включить кэширование для запросов API и использовать другие функции, включенные сервис-воркерами, такие как push-уведомления. Вы можете узнать больше о возможностях Workbox в разделе Advanced Recipes его официальной документации.

Расширенная конфигурация React Webpack: преимущество вашего проекта

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

Как всегда, вы можете найти полные файлы конфигурации на GitHub и обратиться к документации Webpack и его разделу плагинов, чтобы найти больше рецептов, применимых к вашим целям. Спасибо за чтение!