Полностью избавьтесь от страха новичка перед webpack!

Webpack

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

предисловие,Что вы должны знатьЭто очень важно, обязательно внимательно прочитайте!

предисловие

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

Прочитав его, вы обязательно скажете: «Это он? Вебпак это?».

Личное предложение: Например, create-react-app — хороший скаффолдинг, возможно, вы не сможете написать такой скаффолдинг, но вы должны уметь его понимать и уметь модифицировать исходный код, когда вам это нужно. Webpack, освоившего этот уровень, часто бывает достаточно. В конце я также добавлю, как написать загрузчик и плагин самостоятельно (но я верю, что вы будете знать, как это написать, если внимательно прочитаете)

Подготовьте среду и версию

node: ^12.16.1

webpack: ^4.44.2

webpack-cli: ^3.3.12

Webpack5 обновил некоторые новые функции, поэтому в этой статье будет рассказано о часто используемом webpack4. Но вам не нужно беспокоиться о том, как выучить 4, даже если у вас есть 5, причина та же, 4 может быть, это не 5, просто больше новых функций.

Что вы должны знать

концепция веб-пакета

webpack — это современное приложение JavaScriptсборщик статических модулей. Если вы познакомились с js достаточно рано, вы должны знать, что исходный проект не имеет такого инструмента упаковки.Файл эквивалентен модулю.В конце концов, эти файлы необходимо импортировать в html с помощью тегов скрипта в определенный порядок (потому что, если порядок неправильный, это приведет к ошибкам, таким как отсутствие зависимых переменных). Однако этот писательский проект не только хлопотный, но и неизящный.С появлением и развитием node.js появились такие инструменты упаковки (gulp, grunt, а теперь и самый популярный вебпак) на основе node.js, потому что node.js Имеет возможность работать с файлами. Таким образом, суть webpack заключается в том, чтобы упаковать для нас ссылки на js, и мы часто слышим, что различные загрузчики, различные плагины, горячие обновления, горячие замены модулей и т. д. являются сублимацией веб-пакета, так что веб-пакет может предоставить нам больше помощи.

  • Загрузчик: сам веб-пакет может упаковывать файлы только в формате js и json, но в реальном проекте у нас также есть другие файлы, такие как css, scss, png, ts и т. д. В настоящее время нам нужно использовать загрузчик, чтобы упаковать его. правильно.

    • Резюме: загрузчик используется при компиляции файлов, отличных от js и json
    • Обычные загрузчики:
    style-loader
    css-loader
    sass-loader
    ts-loader
    file-loader
    babel-loader
    postcss-loader
    ...
    
  • плагин: плагин может сделать некоторые вещи для вас, когда веб-пакет доходит до определенной стадии, подобно жизненному циклу в реакции/вью. Конкретный плагин (плагин) предназначен для внедрения логики расширения в определенное время в процессе построения веб-пакета, чтобы изменить результат построения и воздействовать на весь процесс построения.

разобраться в этих вещах

  • postcss: postcss — это инструмент для преобразования кода CSS с помощью инструментов и плагинов JavaScript. Можно понять его как babel.Сам по себе он мало влияет.Реализация многих наших специфических потребностей требует доработки его плагинов,а он больше похож на платформу. Например, в проекте нам нужен webpack для автоматического добавления префиксов совместимости к стилям css для нас Плагин, который на самом деле префиксы намautoprefixer, но предпосылка, что он может префиксить нас, заключается в том, что у нас есть postcss.Не поймите неправильно postcss как замену scss и меньше
    • Под термином «PostCSS» мы можем попеременно ссылаться на две вещи:
      1. Сам инструмент естьPostCSS(что вы получите, когда запустите его)npm install postcss,так же как
      2. Инструмент поддерживаетЭкосистема плагинов PostCSS
  • babel: babel — это компилятор JavaScript, который позволяет нам использовать синтаксис JavaScript следующего поколения, не беспокоясь о совместимости. Но для достижения определенного преобразования синтаксиса нам все равно придется использовать егоплагиндостигать
    • дает нам после babel7предустановка, так что нам больше не нужно комбинировать плагины самостоятельно, и мы можем написать любые пресеты, которые мы хотим запускать в любой среде (эквивалентно тому, чтобы помочь вам комбинировать плагины, которые необходимо использовать в этой среде, в каждом параметре пресета )
  • синтаксис es6+: Babel по умолчанию преобразует синтаксис, например: let, const, () => {}, class
  • возможности эс6+: Babel не преобразует функции, функции требуют совместимы кода JS Code для совместимости с более низкими версиями браузеров. Например: итератор, генератор, набор, карта, прокси, отражение, символ, обещание
  • @babel/core: @ Babel/Core — основная библиотека Babel, все основные API находятся в этой библиотеке, эти API доступны для вызовов Babel-Loader
  • @babel/preset-env: это предустановленный набор подключаемых модулей, который содержит набор связанных подключаемых модулей.В Bable различные подключаемые модули используются для руководства по выполнению преобразования кода. Этот плагин содержит все правила перевода es6 в es5.
  • @babel/polyfill: @babel/preset-env предоставляет только правила для преобразования синтаксиса, но не компенсирует некоторые новые функции, отсутствующие в браузерах, такие как некоторые встроенные методы и объекты, такие как Promise, Array.from и т. д. В настоящее время время, полифил требуется, чтобы быть прокладкой для js, чтобы компенсировать эти новые функции, отсутствующие в браузерах более ранних версий.Примечание. В Babel 7.4.0 этот пакет будет объявлен устаревшим.
  • core-js: это полифилл для стандартной библиотеки JavaScript, который можно загрузить по запросу. При использовании @babel/preset-env вы можете настроить версию core-js и метод импорта core-js.Примечание: @babel/polyfill зависит от core-js.
  • regenerator-runtime: Обеспечивает транскодирование функций генератора

Дополнительные точки знаний (важно)

  • browserslist:browserslist фактически объявляет набор браузеров. Наш инструмент может выводить коды совместимости в соответствии с описанием этого набора. browserslist применяется к таким инструментам, как babel и postcss.

    • browserslist можно настроить в файле package.json, или вы можете написать один файл .browserslistrc для конфигурации

    • Инструмент автоматически найдет конфигурацию в .browserslistrc.Если файл .browserslistrc не найден, он будет искать в package.json

    • пример:

      // 在.browserslistrc中的写法
      > 1%
      last 2 versions
      
      // 还可以配置不同环境下的规则(在.browserslistrc中)
      [production]
      > 1%
      ie 10
      
      [development]
      last 1 chrome version
      last 1 firefox version
      
      // 在package.json中的写法
      {
        "browserslist": ["> 1%", "last 2 versions"]
      }
      
      // 还可以配置不同环境下的规则(在package.json中)
      // production和development取决你webpack中mode字段的配置
      {
       	"browserslist": {
      		"production": [
      			">0.2%",
      			"not dead",
      			"not op_mini all"
      		],
      		"development": [
      			"last 1 chrome version",
      			"last 1 firefox version",
      			"last 1 safari version"
      		]
      	} 
      }
      

    «> 1%» означает, что он совместим с браузерами, использование которых превышает 1% на рынке, а «последняя 1 версия Chrome» означает, что он совместим с предыдущей версией Google. Для получения подробной информации вы можете использовать командуnpx browserslist "> 1%"Способ увидеть, какой браузер включен,BrowsersList Адрес Github

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

  • chunks: фрагмент содержит по крайней мере один фрагмент, а фрагменты представляют собой набор нескольких фрагментов.

    // index.js
    import { a } from 'a.js'
    console.log('我是index文件')
    
    //a.js
    const a = '我是a文件'
    export { a }
    

    Для приведенного выше кода a.js — это чанки, а index.js — чанки.

    В конструкции веб-пакета вход представляет собой фрагменты, а выход - фрагменты (просто знайте эту концепцию)

Соберите проект веб-пакета

Инициализировать проект

  • Создать новую папку

    mkdir learnWebpack
    
  • в папку

    cd learnWebpack/
    
  • Инициализируйте файл package.json

    # 可以输入配置
    npm init
    
    # 默认配置创建
    npm init -y
    
    # 是用npm init -y后得到的内容
    {
      "name": "learnwebpack",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC"
    }
    

Установить

  • Установить зависимости webpack, webpack-cli

    # 我更喜欢yarn,当然你也可以使用npm
    yarn add webpack@4.44.2 webpack-cli@3.3.12 -D
    

Создать каталог

  • Создайте src в корневом каталоге и создайте index.js в src.

  • Добавьте кусок кода в index.js:

    console.log('hello webpack')
    
  • Добавить поле скриптов в файл package.json"start": "webpack"

      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "webpack"
      }
    
  • выполнить в командной строкеyarn start, мы обнаружим, что компиляция прошла успешно, но есть предупреждение! В webpack папка dist и файл main.js в папке dist автоматически создаются в корневом каталоге.

    • О предупреждении: ARNING в конфигурации Параметр «режим» не был установлен, для этого значения веб-пакет переключится на «производство». Установите для параметра «режим» значение «разработка» или «производство», чтобы включить значения по умолчанию для каждой среды. Вы также можете установить значение «Нет», чтобы отключить поведение по умолчанию. Подробнее:Веб-пакет Просто .org/config как у ATI...; Предупреждение дает понять, что мы не установили поле режима. Мы можем избавиться от предупреждения, просто настроив поле режима в конфигурации веб-пакета.

    • О папке dist и файле main.js: это использование с нулевой конфигурацией, которое первоначально рекламировалось webpack4. Очевидно, мы ничего здесь не настраивали, поэтому мы успешно упаковали код в src. Эта функция на самом деле заключается в том, что wabpack по умолчанию настраивает для нас простую конфигурацию упаковки.

      const path = require('path')
      module.exports = {
        extry: './src/index.js',
        output: {
          filename: 'main.js',
          path: path.resolve(__dirname, './dist') 
        }
      }
      
    • Примечание. Конфигурация по умолчанию не слишком проста. Прочитав эту конфигурацию, я хотел бы знать, почему, когда вы не находитесь под src или src index.js, когда мы создали, не используйте функцию нулевой конфигурации, не может быть причиной

Нулевая конфигурация для веб-пакета

Как мы видели выше, нулевая конфигурация очень слаба, и удовлетворить наши потребности в реальном проекте ему совершенно не под силу.

Если мы хотим настроить конфигурацию веб-пакета, нам нужно создатьwebpack.config.jsфайл, содержимое этого файла может переопределить нулевую конфигурацию веб-пакета

  • Используйте файл конфигурации по умолчанию: webpack.config.js

    # 使用webpack.config.js配置文件时,输入该命令即可启动webpack打包
    webpack
    
  • Используйте другие файлы конфигурации: такие как yzyConfig.js, вы можете передать--config yzyConfig.jsчтобы указать, какой файл конфигурации использует webpack для выполнения сборки

    # 通过--config来指定其他配置文件,并按照指定的配置文件的配置内容进行打包
    webpack --config yzyConfig.js
    

основные понятия конфигурации webpack

  • Фрагмент: относится к кодовому блоку. Блок может состоять из нескольких модулей, а также используется для слияния и сегментации кода (слияние и сегментация здесь в основном относятся к оценке стратегии отпечатка пальца). Стратегия отпечатка пальца — это просто хэш после имя файла.
  • bundle: окончательный выходной файл (файл в формате .js, который является нашим выходным файлом) после анализа и компиляции ресурса процессом webpack.
  • запись: точка входа для упаковки файла, веб-пакет будет рекурсивно искать зависимости в соответствии с записью, каждая зависимость будет обработана им и, наконец, упакована в файл коллекции.
  • вывод: настроить расположение, имя файла и т. д. упакованного вывода
  • Загрузчик: по умолчанию webpack поддерживает только файлы js и json, через загрузчик он может парсить другие типы файлов. Теоретически, пока есть соответствующий загрузчик, webpack может обрабатывать файлы любого типа.
  • Плагин: Основная обязанность загрузчика — сообщить веб-пакету больше типов файлов, а обязанность плагина — позволить ему контролировать процесс сборки и выполнять некоторые специальные задачи. Плагины очень мощные и могут выполнять широкий спектр задач.
  • режим: целевая среда, неиспользуемые целевые среды повлияют на решения об упаковке веб-пакета
    • производство: серия операций оптимизации, таких как сжатие кода
    • разработка: способствует обработке горячих обновлений, определяя, какой модуль изменяет поколение
    • none: ничего не делать, при упаковке будет предупреждение

настроить webpack.config.js

Цели строительства проекта

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

  • Реализовать загрузку css

  • Реализовать отображение эффекта css

  • Реализовать автоматическое дополнение префикса css

  • Реализовать экспорт css в виде файла

  • Автоматически генерировать html-файлы

  • Реализовать упаковку для очистки папки dist

  • Реализовать внедрение картинок в js файл

  • Реализовать внедрение изображений в файл css

  • Реализовать локальный сервис webpack

  • Реализовать многостраничную упаковку

Реализовать загрузку css

Мы уже знаем, что файлы .css не могут быть должным образом упакованы в пакеты с помощью файлов webpack (объяснение пакетов см. в разделе «Основные концепции конфигурации Webpack»), поэтому нам нужен загрузчик в качестве загрузчика, чтобы правильно упаковать его в файлы пакетов.

содержание документа

step1.png

Установить css-загрузчик

 yarn add css-loader -D

Настроить css-загрузчик

const path = require('path')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: "development",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: "css-loader"
      }
    ]
  }
}

Запустите команду webpack, чтобы проверить, содержит ли dist/main.js содержимое файла css.

cssloaderdist.png

Мы обнаружили, что содержимое файла css было успешно упаковано. В настоящее время, если вы создадите html-страницу в папке dist, добавите класс box в элемент div и импортируете файл main.js, вы обнаружите, что вы вообще не увидите эффекта стиля. .

Поскольку в настоящее время содержимое в css вводится в js только в виде строки (эквивалентно JSON.stringify содержимого файла css), вы, естественно, не можете увидеть эффект.

Что вы хотите сделать, чтобы увидеть эффект? Конечно, поместите содержимое css в тег стиля! Но нам не нужно делать этот шаг, потому что у нас есть загрузчик стилей, который сделает это за нас!

Реализовать отображение эффекта css

Установить загрузчик стилей

yarn add style-loader -D

Настроить загрузчик стилей

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

Здесь следует отметить, что при использовании нескольких загрузчиков для одного и того же типа файла свойство use получает массив и выполняет его справа налево. Таким образом, загрузчик стилей должен быть написан перед загрузчиком css.

Запустите команду webpack и посмотрите результат

styleloaderdist.png

успех!

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

Реализовать автоматическое дополнение префикса css

Уже известно, что autoprefixer — это плагин для инструмента postcss, поэтому нам нужно установить postcss и postcss-loader.

Установить postcss, postcss-loader, autoprefixer,Здесь postcss-loader должен указать версию 4.x, потому что версия 4.x и webpack4 будут иметь проблемы с отчетами об ошибках.

yarn add autoprefixer postcss-loader@4.2.0 postcss -D

Настройте postcss-loader и автопрефиксер плагинов

const path = require('path')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader', 
          'css-loader', 
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [require('autoprefixer')]
              }
            }
          }
        ]
      }
    ]
  }
}

Когда загрузчику нужно записать конфигурацию, мы можем написать загрузчик как объект, атрибут загрузчика — это имя используемого загрузчика, а атрибут options — объект конфигурации загрузчика. Autoprefixer — это плагин для postcss, поэтому использование autoprefixer естественно прописано в конфигурации postcss-loader

Поскольку у postcss есть собственный профиль, вы также можете написать это:

// webpack.config.js
const path = require('path')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader', 'postcss-loader']
      }
    ]
  }
}

// 根目录下新建postcss.config.js文件
module.exports = {
  plugins: [require('autoprefixer')],
}

Здесь нам нужно настроить browserslist, иначе плагин не знает, каким правилам следовать для завершения префикса

// 在package.json文件中添加
// 这里的意思表示目标浏览器为ie浏览器,并需要兼容到ie8以上
"browserslist": ["ie > 8"]

бегатьwebpackкоманда, чтобы увидеть результат

postcssloaderdist.png

успех!

Реализовать экспорт css в виде файла

По мере роста проекта мы не хотим помещать так много стилей в тег стиля, мы хотим импортировать его с помощью тега ссылки, тогда нам нужно использоватьmini-css-extract-plugin

Установите плагин mini-css-extract

yarn add mini-css-extract-plugin -D

Настройте плагин mini-css-extract-plugin и его загрузчик.На данный момент нам не нужен style-loader.Нам нужно заменить style-loader на MiniCssExtractPlugin.loader

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader', 
          'postcss-loader'
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css"
    })
  ]
}
  • MiniCssExtractPlugin может настроить имя выходного файла
  • [имя] — заполнитель, какое имя при импорте и какое имя при экспорте
  • css/ означает экспорт в папку css

бегатьwebpackкоманда, чтобы увидеть результат

cssextractplugindist.png

успех!

Автоматически генерировать html-файлы

Мы обнаружили, что html под dist был создан нами вручную, что явно не элегантно.html-webpack-pluginПомогите решить!

Установить html-webpack-plugin, а также сделать версию 4.x здесь

yarn add html-webpack-plugin@4.5.2 -D

Настроить html-webpack-плагин

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader', 
          'postcss-loader'
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ]
}

бегатьwebpackкоманда, чтобы увидеть результат

htmlplugindist.png

успех! Очевидно, HtmlWebpackPlugin генерирует для нас новую html-страницу на основе нашего шаблона и автоматически вводит зависимости в пакете dist. узнать большеКонфигурация плагина HtmlWebpack

Реализовать упаковку для очистки папки dist

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

Установите чистый-webpack-плагин

yarn add clean-webpack-plugin -D

Настроить чистый-webpack-плагин

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader', 
          'postcss-loader'
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new CleanWebpackPlugin()
  ]
}

В это время вы также произвольно создаете другой файл в папке dist, запускаетеwebpackКоманда посмотреть на результаты, вы обнаружите, что файлы, которые вы произвольно создали, исчезли. Проверьте это, и вы успешны

Реализовать внедрение картинок в js файл

Для достижения этой функции мы используем загрузчик URL, конечно, вы также можете использовать загрузчик файлов. url-loader — это обновленная версия file-loader, и он также зависит от file-loader внутри.И файловый загрузчик, и URL-загрузчик устарели после webpack5, вместо этого используйте модули активов

Установите URL-загрузчик и файловый загрузчик

yarn add url-loader file-loader -D

Вы можете задаться вопросом, почему установлен загрузчик файлов, потому что загрузчик url ​​зависит от загрузчика файлов. Если он не установлен, не будет проблем, когда url-loader преобразует изображение в base64 и импортирует его в бандл, но прямой вывод изображения в папку dist сообщит об ошибке, говоря вам, что файл-загрузчик отсутствует

настроить URL-загрузчик

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader', 
          'postcss-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            name: '[name].[ext]',
            limit: 1024 * 3
          }
        }
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new CleanWebpackPlugin()
  ]
}
  • [ext] указывает, какой формат используется при импорте и какой формат используется при экспорте.
  • limit представляет собой порог размера изображения, а изображения, превышающие порог, будут помещены в папку упаковки нетронутыми (это делает файл-загрузчик, при его внедрении в js он поможет вам сгенерировать адрес, т.е. соответствующий адрес после адреса доступа к упаковке), не более чем будет преобразован в base64 и помещен в файл пакета

Вставьте изображения в файл заявки

// index.js
import './index.css'
import mk85 from './assets/images/mk85.jpeg'
console.log(mk85) // mk85.jpeg
const img = document.createElement('img')
img.src = mk85
const BoxDiv = document.getElementsByClassName('box')
BoxDiv[0].appendChild(img)

бегатьwebpackкоманда, чтобы увидеть результат

urlloaderjsdist.png

Реализовать внедрение изображений в файл css

Мы по-прежнему используем url-loader для добавления картинок в css, но нам нужно немного изменить конфигурацию.

css-код

.box {
  width: 100px;
  height: 100px;
  /* background-color: yellowgreen; */
  background-image: url('./assets/images/mk85.jpeg');
  display: flex;
}

Прямая ссылка и упаковка, упаковка удалась! Откройте html-страницу и обнаружите, что я не вижу изображение, потому что адрес неверный. После упаковки образ mk85 находится в папке dist, а путь ссылки index.css по-прежнему mk85.jpeg, но index.css находится в папке css, поэтому, естественно, на него нельзя ссылаться. Как на него можно ссылаться? Самый простой способ — добавить/,Но есть ямы (на самом деле не ямы, это/images,./images,imageВ чем разница между тремя?). Добавлено: приложение create-реагировать также передается/добиться единой ссылки

urlloadercssdistF.png

Изменить конфигурацию загрузчика URL

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader', 
          'postcss-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            name: '[name].[ext]',
            limit: 1024 * 3,
            outputPath: "images/",
            publicPath: "/images",
          }
        }
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new CleanWebpackPlugin()
  ]
}
  • outputPath указывает, где находится вывод (предоставляется загрузчиком файлов)

  • name: images/[name].[ext]Имеет ли это тот же эффект, что и установка outputPath? Другое дело при работе с полем publicPath. Поэтому, когда вам не нужно настраивать поле publicPath, вы можете установить выходной путь по имени (предоставляется файловым загрузчиком)

    options: {
      name: '[name].[ext]',
      limit: 1024 * 3,
      outputPath: "images/",
      publicPath: "/images",
    }
      
    // 等价于
      
    options: {
      name: 'images/[name].[ext]',
      limit: 1024 * 3,
      publicPath: "/",
    }
    
  • publicPath представляет путь ссылки на ресурс

бегатьwebpackкоманда, чтобы увидеть результат

urlloadercssS.png

Это сработало! Это тот результат, который мы хотим, но проблема возникает снова: когда вы открываете html-страницу, вы обнаруживаете, что не можете увидеть нормальное отображение картинки, которая здесь задействована.о/images,./images,imageВ чем разница между тремя

Проще говоря, если я запускаю службу, мой фактический путь — «localhost:8080/images/mk85.jpeg», если я не запускаю службу, это «/images/mk85.jpeg».

Итак, начинаем службу!

Реализовать локальный сервис webpack

Установить webpack-dev-сервер

yarn add webpack-dev-server -D

настроить URL-загрузчик

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader', 
          'postcss-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            name: '[name].[ext]',
            limit: 1024 * 3,
            outputPath: "images/",
            publicPath: "/images",
          }
        }
      }
    ]
  },
  devServer: {
    open: true,
    port: 8080,
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new CleanWebpackPlugin()
  ]
}
  • Просто добавьте конфигурацию devServer
  • open означает открыть браузер
  • port указывает номер порта службы

Примечание: это время не используетсяwebpackкоманда для запуска проекта, вам нужно использоватьwebpack-dev-serverначать

Реализовать многостраничную упаковку

Как следует из названия, многостраничный, естественно, имеет несколько html-страниц, каждая html-страница имеет свой собственный js-файл, а затемСколько входов, столько и выходов

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

multipleCatalogue.png

  • Здесь нет необходимости в src/index.js
  • Создайте новый webpack.multiple.config.js
  • Новый источник/страницы/логин/js/index.js
  • Новый src/pages/main/js/index.js

Установить glob, для обработки файлов

yarn add glob -D

настроить webpack.multiple.config.js

module.exports = {
  entry: {
    login: './src/pages/login/js/index.js',
    main: './src/pages/main/js/index.js'
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, './dist') 
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'login.html',
      chunks: ['login'] // chunks的名字对应entry中的名字
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'main.html',
      chunks: ['main']
    })
  ]
}

Закончено! вы можете использоватьwebpack --config ./`webpack.multiple.config.jsЗапустите команду. Результат будет таким, как вы хотите

Однако в этот момент вы, должно быть, думаете, нужно ли мне перенастраивать каждый раз, когда я пишу страницу? Это также слишком громоздко и не элегантно! Итак, давайте сейчас решим эту проблему, перейдем непосредственно к коду

// 我们写一个方法自动做我们上面配置的事情
const glob = require("glob")

const setMpa = () => {
  const entry = {}
  const htmlwebpackplugins = []
	// 通过glob库拿到我们的入口文件数组
  const entryFiles = glob.sync(path.resolve(__dirname, "./src/pages/*/*/index.js"))
	// console.log(entryFiles)
  // 打印结果
  // [
  //  '/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/login/js/index.js', 
  //  '/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/main/js/index.js'
  // ]
  entryFiles.forEach((item) => {
    const entryFile = item
    const match = entryFile.match(/src\/pages\/(.*)\/js\/index\.js$/)
    // console.log(match)
    // 打印结果
    // [
    //   'src/pages/login/js/index.js',
    //   'login',
    //   index: 43,
    //   input: '/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/login/js/index.js',
    //   groups: undefined
    // ]
    const pageName = match[1]
    entry[pageName] = entryFile
    htmlwebpackplugins.push(
      new HtmlWebpackPlugin({
        template: `./src/index.html`,
        filename: `${pageName}.html`,
        chunks: [pageName]
      })
    )
  })

  return {
    entry,
    htmlwebpackplugins,
  }
}

С помощью этого метода мы добавляем его в файл конфигурации

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const glob = require("glob")

const setMpa = () => {
  const entry = {}
  const htmlwebpackplugins = []
  const entryFiles = glob.sync(path.resolve(__dirname, "./src/pages/*/*/index.js"))
  entryFiles.forEach((item) => {
    const entryFile = item
    const match = entryFile.match(/src\/pages\/(.*)\/js\/index\.js$/)
    const pageName = match[1]
    entry[pageName] = entryFile
    htmlwebpackplugins.push(
      new HtmlWebpackPlugin({
        template: `./src/index.html`,
        filename: `${pageName}.html`,
        chunks: [pageName]
      })
    )
  })

  return {
    entry,
    htmlwebpackplugins,
  }
}
const { entry, htmlwebpackplugins } = setMpa()
module.exports = {
  entry,
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader', 
          'postcss-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            name: '[name].[ext]',
            limit: 1024 * 3,
            outputPath: "images/",
            publicPath: "/images",
          }
        }
      }
    ]
  },
  devServer: {
    open: true,
    port: 8080,
    hot: true
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
    }),
    new CleanWebpackPlugin(),
    ...htmlwebpackplugins
  ]
}

мы снова используемwebpack --config ./`webpack.multiple.config.jsЗапустите команду и добейтесь успеха!

резюме

Даже если вы выполнили здесь простую настройку проекта webpack, не спешите смотреть вниз и думать, действительно ли вы понимаете загрузчик и плагин.Если вы хотите написать загрузчик и плагин, есть ли у вас какие-либо идеи?

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

реализовать загрузчик

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

Во-первых, loader — это функция, обратите внимание, что здесь она не может быть функцией стрелки.

Напишите загрузчик, который заменяет строки

// replaceLoader.js
module.exports = function (soure) {
  console.log(soure, this) // 这里可以自己打印看一下信息,内容太长我就不放进来了
	return source.replace('hello webpack', "你好呀,webpack!")
}
  • загрузчик это функция
  • Функции стрелок нельзя использовать, потому что используется контекст this
  • Soure получает исходный код файла для обработки
  • Исходный код файла, обрабатываемого по возврату, также является исходным кодом файла, полученного следующим загрузчиком.

использовать загрузчик

{
  test: /\.js$/,
  use: path.resolve(__dirname, './loader/replaceLoader.js')
}

бегатьwebpackкоманда, чтобы увидеть результат

customloader.png

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

реализовать плагин

онлайн ссылка,Написать документацию к плагину на официальном сайте

То же самое просто, мы много раз пользовались плагином, и выяснили, нужен ли нам новый. Очевидно, что пользовательский загрузчик — это конструктор.

Смотрим на формат:

class PluginName {
	constructor (options) {
	}
	apply(compiler) {
		...
	}
}
  • Здесь должен быть прописан метод применения, webpack запустит плагин через метод применения
  • PluginName можно записать как обычную функцию, а применить ее нужно примонтировать к объекту-прототипу (PluginName.prototype)
  • Применение в классе class не может быть записано как стрелочная функция
  • веб-пакетХук компилятора, Проверьте хук, чтобы определить, какой шаг в вашем плагине хочет сделать?

Напишите фальшивый html-webpack-плагин, который выводит файл fake.html.

class HtmlPlugin {
	constructor (options) {
	}
	apply(compiler) {
		compiler.hooks.emit.tap('HtmlPlugin', (compolation) => {
      const content = '<html><body>fake html</body></html>'
      compolation.assets['fake.html'] = {
        source: function () {
          return content
        },
        size: function () {
          return content.length
        }
      } 
    })
	}
}
module.exports = HtmlPlugin

использовать этот плагин

plugins: [
  new HtmlPlugin()
]

бегатьwebpackкоманда, чтобы увидеть результат

customplugin.png

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

Политика отпечатков пальцев

О кешировании браузера

  • современный браузерБудет механизм кэширования
  • Когда мы впервые посещаем веб-сайт A, файл, загруженный с помощью y.js, кэшируется.
  • Когда мы посещаем веб-сайт A во второй раз, браузер обнаруживает, что y.js уже находится в кеше.
    • Если в кеше есть y.js, используйте кешированный файл
    • Преимущество: сокращение запросов на ресурсы
    • Недостаток: когда содержимое y.js обновляется, последнее содержимое y.js нельзя получить без принудительного обновления браузера.
  • Мы можем решить эту проблему, добавив идентификатор
    • y.123.js загружается при первом посещении
    • Второй визит обнаруживает, что кеш есть, используйте y.123.js в кеше
    • В это время содержимое файла y на сервере изменилось, и имя также изменено на y.111.js.
    • Третий визит обнаружил, что файла y.111.js нет, а последний y.111.js загружается корректно.

Обращение более простое объяснение, и конкретные детали, которые вы можете не знать, понять метод кэширования этого механизма кэширования.

Использование стратегии отпечатков пальцев в веб-пакете

использовать:

filename: '[name].[hash].[ext]',
  • Хэш: Возьмите элемент как единое целое. Если содержимое элемента изменится, будет сгенерирован новый хеш. Если содержимое не изменится, хэш останется неизменным.
    • Если какой-либо файл, который необходимо упаковать во всем проекте, изменится, хэш-значение всех файлов в результате упаковки изменится.
  • chunkhash: в чанках, когда содержимое файла изменяется, хэш модуля всей группы чанков будет меняться
    • Предполагая, что упакованный экспорт имеет a.123.js и c.123.js
    • файл представляет файл b
    • Изменено содержимое файла b
    • Результаты переупаковки: a.111.js и c.123.js.
    • Хэш-значение a будет затронуто, но хеш-значение c не будет затронуто.
  • contenthash: блок основан на собственном контенте, и зависимости не учитываются
    • Предполагая, что упакованный экспорт имеет a.123js и b.123.css
    • файл представляет файл b
    • Изменено содержимое файла b
    • Результат перепаковки - a.123.js и b.111.css
    • Хэш-значение a не изменяется

Замена горячего модуля

Вы, должно быть, использовали эту функцию, вы просто не знаете об этом!

Сцены:

  • Запустите локальную службу проекта
  • Изменено содержимое файла .css
  • Браузер не обновляется, но измененное содержимое по-прежнему вступает в силу

Это горячая замена модуля Совет: Либо css, либо js могут выполнять горячую замену модуля, но я лично рекомендую делать только горячую замену модуля css. Поскольку горячая замена модуля js требует написания кода для его замены, если нет особых обстоятельств, горячая замена модуля js не очень полезна.

Сделаем замену горячего модуля css

Примечание. Горячая замена модуля не поддерживает извлеченные файлы css и может быть размещена только в стиле, поэтому требуется загрузчик стилей.

настроить webpack.config.js

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlPlugin = require('./plugin/htmlPlugin')
const Webpack = require('webpack')

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, './dist') 
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.js$/,
        use: path.resolve(__dirname, './loader/replaceLoader.js')
      },
      {
        test: /\.css$/,
        use: [
          // MiniCssExtractPlugin.loader,
          'style-loader',
          'css-loader', 
          'postcss-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            name: '[name].[ext]',
            limit: 1024 * 3,
            outputPath: "images/",
            publicPath: "/images",
          }
        }
      }
    ]
  },
  devServer: {
    open: true,
    port: 8080,
    hot: true
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].css",
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new CleanWebpackPlugin(),
    new HtmlPlugin(),
    new Webpack.HotModuleReplacementPlugin()
  ]
}

Подумав, я все-таки прикрепил полный файл конфигурации (немного переживал, что он будет занимать слишком много места на странице)

  • Во-первых, замените предыдущий MiniCssExtractPlugin.loader обратно на style-loader.
  • Добавить на сервер разработкиhot: true
  • Импортировать WebPack:const Webpack = require('webpack')
  • Добавьте в плагин:new Webpack.HotModuleReplacementPlugin()

бегатьwebpack-dev-serverКоманда, чтобы увидеть эффект!

Что нового в вебпаке 5

Без лишних слов, просто перейдите по ссылке,Что нового в вебпак5

Совет: Когда вы используете webpack4, независимо от того, устанавливаете ли вы плагин (плагин) или загрузчик, попробуйте посмотреть, какая версия плагина сейчас. установите его версию 4.х, иначе при упаковке возникнет неизвестная ошибка

конец

Первоначально в этой статье была написана только часть [Создание проекта веб-пакета], а затем она была опубликована и отмечена как незавершенная. Я хотел кратко написать следующий контент (на самом деле это довольно утомительно писать подробно), но я увидел сообщение, призывающее к этому. быть в курсе. , Когда я выразил свою похвалу, я решил написать эту статью и разослать ее всем. На данный момент, благодаря этой статье, количество моих поклонников изменилось с 0 до 18. Большое спасибо за ваше одобрение.Это также большая поддержка для меня. Я постараюсь написать хорошую статью и поделиться ею со всеми.

Наконец, я надеюсь, что все не забудут свои первоначальные намерения и добьются прогресса и будут расти вместе! Как и мой идентификатор Nuggets, я желаю всем KDDA (сохраните мечту в живых)