Spec-Zone.ru › webpack 4

Управление активами

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

До webpack фронтенд-разработчики использовали такие инструменты, как grunt и gulp, для обработки этих активов и перемещения их из их /src папки в их /dist или /build директорию. Та же идея использовалась для JavaScript-модулей, но инструменты, такие как webpack, будут динамически объединять все зависимости (создавая то, что известно как граф зависимостей). Это замечательно, потому что каждый модуль теперь явным образом указывает свои зависимости, и мы избежим объединения модулей, которые не используются.

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

Настройка

Давайте внесём небольшое изменение в наш проект перед началом:

dist/index.html

  <!doctype html>
  <html>
    <head>
-    <title>Getting Started</title>
+    <title>Asset Management</title>
    </head>
    <body>
-     <script src="main.js"></script>
+     <script src="bundle.js"></script>
    </body>
  </html>

webpack.config.js

  const path = require('path');

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

Загрузка CSS

Для того, чтобы import файл CSS изнутри JavaScript-модуля, необходимо установить и добавить style-loader и css-loader в вашу module конфигурацию:

npm install --save-dev style-loader css-loader

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
+   module: {
+     rules: [
+       {
+         test: /\.css$/,
+         use: [
+           'style-loader',
+           'css-loader',
+         ],
+       },
+     ],
+   },
  };

webpack использует регулярное выражение, чтобы определить, какие файлы следует искать и передать в определённый загрузчик. В этом случае любой файл, который оканчивается на .css будет передан style-loader и css-loader.

Это позволяет вам import './style.css' в файл, который зависит от этого стилирования. Теперь, когда этот модуль запущен, тег <style> со строковым CSS будет вставлен в <head> вашего html-файла.

Давайте попробуем это, добавив новый style.css файл в наш проект и импортировав его в наш index.js:

project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- style.css
    |- index.js
  |- /node_modules

src/style.css

.hello {
  color: red;
}

src/index.js

  import _ from 'lodash';
+ import './style.css';

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

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+   element.classList.add('hello');

    return element;
  }

  document.body.appendChild(component());

Теперь запустите вашу команду сборки:

npm run build

...
    Asset      Size  Chunks             Chunk Names
bundle.js  76.4 KiB       0  [emitted]  main
Entrypoint main = bundle.js
...

Откройте index.html в вашем браузере снова, и вы должны увидеть, что Hello webpack теперь имеет красный стиль. Чтобы увидеть, что сделал webpack, проинспектируйте страницу (не просматривайте исходный код страницы, так как он не покажет вам результат, потому что тег <style> динамически создаётся JavaScript) и посмотрите теги заголовка страницы. Он должен содержать блок стиля, который мы импортировали в index.js.

Обратите внимание, что вы можете, и в большинстве случаев должны, сжимать CSS для повышения скорости загрузки в производстве. Кроме того, существуют загрузчики практически для всех типов CSS, которые вы можете себе представить — postcss, sass и less, чтобы назвать несколько.

Загрузка изображений

Теперь мы подключаем наш CSS, но что насчёт наших изображений, таких как фоны и значки? Используя file-loader, мы можем легко включить их в нашу систему:

npm install --save-dev file-loader

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ],
        },
+       {
+         test: /\.(png|svg|jpg|gif)$/,
+         use: [
+           'file-loader',
+         ],
+       },
      ],
    },
  };

Теперь, когда вы import MyImage from './my-image.png', это изображение будет обработано и добавлено в вашу output директорию и переменная MyImage будет содержать окончательный URL этого изображения после обработки. При использовании css-loader, как показано выше, аналогичный процесс произойдёт для url('./my-image.png') внутри вашего CSS. Загрузчик распознает, что это локальный файл, и заменит путь './my-image.png' окончательным путем к изображению в вашей output директории. html-loader обрабатывает <img src="./my-image.png" /> аналогичным образом.

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

project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- icon.png
    |- style.css
    |- index.js
  |- /node_modules

src/index.js

  import _ from 'lodash';
  import './style.css';
+ import Icon from './icon.png';

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

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');

+   // Add the image to our existing div.
+   const myIcon = new Image();
+   myIcon.src = Icon;
+
+   element.appendChild(myIcon);

    return element;
  }

  document.body.appendChild(component());

src/style.css

  .hello {
    color: red;
+   background: url('./icon.png');
  }

Давайте создадим новую сборку и снова откроем файл index.html:

npm run build

...
                               Asset      Size  Chunks                    Chunk Names
da4574bb234ddc4bb47cbe1ca4b20303.png  3.01 MiB          [emitted]  [big]
                           bundle.js  76.7 KiB       0  [emitted]         main
Entrypoint main = bundle.js
...

Если всё прошло успешно, вы теперь должны увидеть свой значок в качестве повторяющегося фона, а также элемент img рядом с нашим текстом Hello webpack. Если вы проинспектируете этот элемент, вы увидите, что фактическое имя файла изменилось на что-то вроде 5c999da72346a995e7e2718865d019c8.png. Это означает, что webpack нашёл наш файл в папке src и обработав его!

Логичным следующим шагом отсюда является минимизация и оптимизация ваших изображений. Обратите внимание на image-webpack-loader и url-loader для получения дополнительной информации о том, как вы можете улучшить процесс загрузки изображений.

Загрузка шрифтов

А как насчёт других активов, таких как шрифты? Загрузчики файлов и URL-адресов будут выводить любой файл, который вы загружаете через них, в вашу директорию сборки. Это означает, что мы можем использовать их для любого типа файла, включая шрифты. Давайте обновим наш webpack.config.js для обработки файлов шрифтов:

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ],
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader',
          ],
        },
+       {
+         test: /\.(woff|woff2|eot|ttf|otf)$/,
+         use: [
+           'file-loader',
+         ],
+       },
      ],
    },
  };

Добавьте несколько файлов шрифтов в свой проект:

project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- my-font.woff
+   |- my-font.woff2
    |- icon.png
    |- style.css
    |- index.js
  |- /node_modules

После настройки загрузчика и наличия шрифтов вы можете включить их с помощью объявления @font-face. Локальное url(...) наставление будет подхвачено webpack точно так же, как это было с изображением:

src/style.css

+ @font-face {
+   font-family: 'MyFont';
+   src:  url('./my-font.woff2') format('woff2'),
+         url('./my-font.woff') format('woff');
+   font-weight: 600;
+   font-style: normal;
+ }

  .hello {
    color: red;
+   font-family: 'MyFont';
    background: url('./icon.png');
  }

Теперь запустите новую сборку и посмотрим, как webpack обработает наши шрифты:

npm run build

...
                                 Asset      Size  Chunks                    Chunk Names
5439466351d432b73fdb518c6ae9654a.woff2  19.5 KiB          [emitted]
 387c65cc923ad19790469cfb5b7cb583.woff  23.4 KiB          [emitted]
  da4574bb234ddc4bb47cbe1ca4b20303.png  3.01 MiB          [emitted]  [big]
                             bundle.js    77 KiB       0  [emitted]         main
Entrypoint main = bundle.js
...

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

Загрузка данных

Ещё один полезный актив, который можно загрузить, — это данные, такие как файлы JSON, CSV, TSV и XML. Поддержка JSON фактически встроена, подобно NodeJS, что означает import Data from './data.json' будет работать по умолчанию. Для импорта CSV, TSV и XML можно использовать csv-loader и xml-loader. Давайте обработаем загрузку всех трёх:

npm install --save-dev csv-loader xml-loader

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ],
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader',
          ],
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          use: [
            'file-loader',
          ],
        },
+       {
+         test: /\.(csv|tsv)$/,
+         use: [
+           'csv-loader',
+         ],
+       },
+       {
+         test: /\.xml$/,
+         use: [
+           'xml-loader',
+         ],
+       },
      ],
    },
  };

Добавьте несколько файлов данных в свой проект:

project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- data.xml
    |- my-font.woff
    |- my-font.woff2
    |- icon.png
    |- style.css
    |- index.js
  |- /node_modules

src/data.xml

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Mary</to>
  <from>John</from>
  <heading>Reminder</heading>
  <body>Call Cindy on Tuesday</body>
</note>

Теперь вы можете import любой из этих четырёх типов данных (JSON, CSV, TSV, XML), и переменная Data к которой вы импортируете, будет содержать распарсенный JSON для удобного использования:

src/index.js

  import _ from 'lodash';
  import './style.css';
  import Icon from './icon.png';
+ import Data from './data.xml';

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

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');

    // Add the image to our existing div.
    const myIcon = new Image();
    myIcon.src = Icon;

    element.appendChild(myIcon);

+   console.log(Data);

    return element;
  }

  document.body.appendChild(component());

Перезапустите команду npm run build и откройте index.html. Если вы посмотрите в консоль в ваших разработческих инструментах, вы должны увидеть, как ваши импортированные данные регистрируются в консоли!

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

Глобальные активы

Самая интересная часть всего вышеупомянутого заключается в том, что загрузка активов таким образом позволяет группировать модули и активы более интуитивно. Вместо того, чтобы полагаться на глобальную /assets директорию, которая содержит всё, вы можете группировать активы с кодом, который их использует. Например, такая структура может быть очень полезной:

- |- /assets
+ |– /components
+ |  |– /my-component
+ |  |  |– index.jsx
+ |  |  |– index.css
+ |  |  |– icon.svg
+ |  |  |– img.png

Эта настройка делает ваш код гораздо более переносимым, так как всё, что тесно связано, теперь находится вместе. Предположим, вы хотите использовать /my-component в другом проекте, просто скопируйте или перенесите его в /components директорию там. До тех пор, пока вы установили все внешние зависимости и ваша конфигурация имеет те же загрузчики, вы должны быть в порядке.

Однако, предположим, что вы застряли в своих старых привычках или у вас есть некоторые активы, которые используются несколькими компонентами (представлениями, шаблонами, модулями и т. д.). В таком случае вы по-прежнему можете хранить эти активы в базовой директории и даже использовать псевдонимы, чтобы сделать их легче import.

Заключение

В следующих руководствах мы не будем использовать все разные активы, которые мы использовали в этом руководстве, поэтому давайте сделаем некоторую очистку, чтобы мы были готовы к следующей части руководств Управление выводом:

project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
-   |- data.xml
-   |- my-font.woff
-   |- my-font.woff2
-   |- icon.png
-   |- style.css
    |- index.js
  |- /node_modules

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
-   module: {
-     rules: [
-       {
-         test: /\.css$/,
-         use: [
-           'style-loader',
-           'css-loader',
-         ],
-       },
-       {
-         test: /\.(png|svg|jpg|gif)$/,
-         use: [
-           'file-loader',
-         ],
-       },
-       {
-         test: /\.(woff|woff2|eot|ttf|otf)$/,
-         use: [
-           'file-loader',
-         ],
-       },
-       {
-         test: /\.(csv|tsv)$/,
-         use: [
-           'csv-loader',
-         ],
-       },
-       {
-         test: /\.xml$/,
-         use: [
-           'xml-loader',
-         ],
-       },
-     ],
-   },
  };

src/index.js

  import _ from 'lodash';
- import './style.css';
- import Icon from './icon.png';
- import Data from './data.xml';
-
  function component() {
    const element = document.createElement('div');
-
-   // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
-   element.classList.add('hello');
-
-   // Add the image to our existing div.
-   const myIcon = new Image();
-   myIcon.src = Icon;
-
-   element.appendChild(myIcon);
-
-   console.log(Data);

    return element;
  }

  document.body.appendChild(component());

Следующее руководство

Давайте перейдём к Управлению выводом

Дополнительное чтение

  • Загрузка шрифтов на SurviveJS

© JS Foundation and other contributors
Licensed under the Creative Commons Attribution License 4.0.
https://v4.webpack.js.org/guides/asset-management

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API