Система длинных текстов 4D сочетает в себе основы Webpack (Часть 1)

Webpack
Система длинных текстов 4D сочетает в себе основы Webpack (Часть 1)

Введение в вебпак

Обзор

  webpackявляется открытым исходным кодомJavaScriptИнструмент упаковки модулей, основная функция которого заключается в устранении зависимостей между модулями, организации каждого модуля в соответствии с определенными правилами и последовательностями и, наконец, объединении их в один или несколько.JSфайл, весь процесс называется упаковкой модуля.

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

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

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

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

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

Установить

  webpackМетоды установки включают глобальную установку и локальную установку.Глобальная установка привязывает переменную среды командной строки, устанавливает ее один раз и запускает везде. Локальная установка добавит его как зависимость проекта, которую можно использовать только внутри проекта.

   Если используется глобальная установка, когда над проектом сотрудничают несколько человек, из-заwebpackРазличные версии могут привести к противоречивым результатам вывода. и частично зависят отwebpackПлагин вызовет внутреннююwebpackмодуль, в этом случае его все равно нужно установить локальноwebpack.

   установить указанную версиюwebpack,Уведомлениеwebpack4+версия для установкиwebpack-cliинструмент командной строки.

npm i webpack@4.29.4 webpack-cli@3.2.3 --save-dev

  Можно просмотреть после успешной установкиwebpackиwebpack-cliномер версии. УведомлениеwebpackУстанавливается локально, поэтому не может использоваться из командной строки.webpackИнструкции, которые можно использовать только внутри проектаnpx webpackформа.

npx webpack -v
npx webpack-cli -v

Бэйл

  Создать в корневом каталогеindex.html,index.js,fn.js.

// index.html
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Hello World</title>
</head>

<body>
    <script src="./dist/bundle.js"></script>
</body>

</html>

// index.js
import fn from './fn.js'

fn()

// fn.js
export default function () {
    document.write('Hello World')
}

   Консоль запускает следующую команду упаковки, и браузер открываетindex.htmlпоказыватьHello World. вentryРесурсный упакованный вход,webpackОтсюда запускается поиск зависимости модуля и получается в проектеindex.jsиfn.jsдва модуля,output-filenameДля имени выходного ресурса оно появляется после упаковкиdistПод содержаниемbundle.jsдокумент,modeдля режима упаковки, в том числеdevelopment,production,noneТри режима, среда разработки обычноdevelopmentмодель.

работаетnpx webpack -hПроверятьwebpackЭлементы конфигурации и соответствующие параметры командной строки.

npx webpack --entry=./index.js --output-filename=bundle.js --mode=development

   Каждый раз при упаковке необходимо вводить длинную команду, которую можно редактироватьpackage.jsonфайла, добавив команды скрипта для упрощения набора текста. вscriptsдаnpmПредоставляет функцию команды сценария, которая может напрямую использовать инструкции, добавленные модулем (например,webpackзаменить предыдущийnpx webpack),бегатьnpm run buildзатем открыть сноваindex.html.

{
    ...
    "scripts": {
       "build": "webpack --entry=./index.js --output-filename=bundle.js --mode=development"
    }
    ...
}

  Когда проекту требуется все больше и больше конфигураций, в команду нужно добавить больше параметров, которые потом очень сложно поддерживать.webpackФайл конфигурации по умолчаниюwebpack.config.js, затем удалитеpackage.jsonПараметры упаковки, настроенные в .

// webpack.config.js
module.exports = {
    entry: './index.js',
    output: {
        filename: 'bundle.js'
    },
    mode: 'development'
}

// package.json
{
    ...
    "scripts": {
       "build": "webpack"
    }
    ...
}

   Необходимость повторного выполнения при изменении кодаnpm run buildупаковать и открытьindex.html,webpackПредоставляет более удобные инструменты разработкиwebpack-dev-serverПовысить эффективность разработки, когда он обнаружит, что исходный файл проекта был обновлен, он автоматически обновится.live-reloadingБраузер, показывающий обновленный контент.

npm i webpack-dev-server@3.1.14 --save-dev

Добавить кdevскрипт и настройкаwebpack.config.js.webpack-dev-serverОсновная работа заключается в том, чтобы поместить запакованный результат в память, а не писать в файл, каждый разwebpack-dev-serverКогда запрос получен, он просто возвращает упакованный результат в память браузеру. можно удалить поdistкаталог для проверки, даже еслиdistКаталог не существует, и функция обновления страницы по-прежнему работает нормально.

// package.json
{
    ...
    "scripts": {
       "dev": "webpack-dev-server",
       "build": "webpack"
    }
    ...
}

// webpack.config.js
module.exports = {
    ...,
    devServer: {
        publicPath: '/dist'
    }
}

модуль

CommonJs

  node.jsбудетjavascriptЯзык используется для программирования на стороне сервера, где требуется модульность из-за взаимодействия с операционной системой и другими приложениями на стороне сервера, в то время какnode.jsчастьcommonjsспецификации, и на ее основе были внесены некоторые коррективы.

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

  Экспорт — это единственный способ показать модуль внешнему миру,commonjsпрошедшийexportsилиmodule.exportsЭкспортируйте содержимое в модуль. Его внутренний механизм будетexportsуказал наmodule.exportsmodule.exportsПустой объект при инициализации. можно понимать какcommonjsСледующий код добавляется по умолчанию в заголовок каждого модуля. Будьте осторожны, чтобы не датьexportsПрисваивание приведет к тому, что его указание сломается, и не смешивайте их. Также оператор экспорта не представляет конец модуля, вexportsилиmodule.exportsКод позади выполняется как обычно, но обычно помещается в конец модуля.

var module = {
  exports: {}
}
var exports = module.exports

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

   Внутри модуляmoduleобъект имеет свойствоloadedИспользуется для записи того, загружен ли этот модуль, значение по умолчаниюfalse, который устанавливается при первой загрузке или выполнении модуляtrue, загрузите снова, чтобы проверитьmodule.loadedзаtrueбольше не будет выполняться. Выполнить следующим образомnode index.jsбудет выводитьfalse true.

// func.js
console.log(module.loaded)
module.exports = function() {
  return module.loaded
}

// index.js
const func = require("./func.js")

console.log(func())

ES6 Module

  ES6 ModuleОн также рассматривает каждый файл как модуль, каждый модуль имеет свою собственную область видимости, разница заключается в операторах импорта и экспорта.ES6 ModuleСтрогий режим используется автоматически, независимо от того, начинается ли модуль с'use strict', будет использовать строгий режим.

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

Разница между модулем CommonJS и ES6

Самое существенное различие между ними состоит в том, чтоCommonJsЗависимости от модулей являются динамическими, т. е. установление зависимостей модулей происходит на этапе выполнения кода, в то время какES6 ModuleЗависимости от модулей являются статическими, то есть установление зависимостей модулей происходит на этапе компиляции кода.

  CommonJsПуть к модулю может быть указан динамически, поддерживает входящие выражения или может быть передан черезifоператор, чтобы определить, следует ли загружать модуль. Таким образом, вCommonJsДо выполнения модуля невозможно определить четкие зависимости, поэтому импорт и экспорт модуля происходят на этапе выполнения кода.

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

  ES6 ModuleотносительноCommonJSИмеет следующие преимущества.

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

скопировать и связать

какCommonJsизmodule.exportsЭкспорт — это примитивный тип данных, импорт — это просто копия значения. Вывод после запуска следующего:1 1 2,так какindex.jsсерединаcountправдаadd.jsсерединаcountкопия значения , вызовaddфункция, хотя и измененнаяadd.jsсерединаcountзначение, но не влияет на значение, созданное во время импортаcountКопирование влияет.

// add.js
var count = 1

module.exports = {
  count,
  add() {
    count++
  },
  get() {
    return count
  }
}

// index.js
const { count, add, get } = require("./add.js")

console.log(count)
add()
console.log(count)
console.log(get())

какmodule.exportsЭкспорт — это эталонный тип данных, импорт — это копия эталона. Вывод после запуска следующего:{count: 1} {count: 2} true,так какindex.jsсерединаobjectправдаadd.jsсерединаobjectкопия справки, позывнойupdateObjectизмененныйadd.jsсерединаobject.countзначение, тоindex.jsсерединаobject.countизменится соответственно.

// add.js
const object = {
  count: 1
}

module.exports = {
  object,
  updateObject() {
    object.count++
  },
  getObject() {
    return object
  }
}

// index.js
const { object, updateObject, getObject } = require("./add.js")

console.log(object)
updateObject()
console.log(object)
console.log(getObject() === object)

  ES6 ModuleИмпортируемая переменная всегда указывает на переменную внутри модуля, и при ее использовании можно получить самое последнее значение переменной. Вывод после запуска следующего:1 2 2,index.jsсерединаcountиadd.jsсерединаcountСвязь связывания устанавливается между (binding), самое последнее значение привязки можно получить в режиме реального времени.

// add.js
export var count = 1
export function add() {
  count++
}
export function get() {
  return count
}

// index.js
import { count, add, get } from "./add.js"

console.log(count)
add()
console.log(count)
console.log(get())

Уведомлениеexport defaultОтношения привязки не будет.После выполнения следующего результата будет1 1 2.

// add.js
var count = 1

export default count
export function add() {
  count++
}
export function get() {
  return count
}

// index.js
import count, { add, get } from "./add.js"

console.log(count)
add()
console.log(count)
console.log(get())

Во-первыхexport default— это синтаксический сахар, упрощающий объем кода, когда модуль имеет только один экспорт. следующееexport defaultэкспортировать переменную примитивного типаcount.

var count = 1

export default count

ПотомJavaScriptизменит переменнуюcountво внутреннюю переменную*default*, затем переименуйте его вdefaultэкспорт.

var count = 1
var *default* = count

export { *default* as default }

Доexport defaultПричина отсутствия отношений связывания связана с преобразованием синтаксического сахара,index.jsсерединаcountТо, что на самом деле связано,add.jsвнутренние переменные в*default*, вместоcount.

// add.js
var count = 1
var *default* = count

export { *default* as default }
...

// index.js
import { default as count } from './add.js'
...

  CommonJsПри импорте переменной модуля это просто копия значения или ссылки. иES6 ModuleИмпортированные переменные всегда будут связывать переменные внутри модуля, формируя отношение привязки (binding),Уведомлениеexport defaultЭкспортируемые переменные не имеют отношений привязки, причина в том, чтоJavaScriptЭто вызвано преобразованием синтаксического сахара.

круговая зависимость

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

как следуетCommonJsЦиклическая зависимость в , выводmodule foo exports {} module bar exports bar.js. во-первыхindex.jsимпортировать и выполнятьfoo.js,foo.jsимпортировать и выполнятьbar.js,Потомbar.jsимпортировать вfoo.js, так как он был импортированfoo.jsНо выполнение не завершено, значение экспорта в это время является пустым объектом по умолчанию, и результат печатаетсяbar.jsЗаконченный. окончательное право исполненияfoo.js, процесс печати результата заканчивается.

// index.js
require("./foo.js")

// foo.js
const bar = require("./bar.js")

console.log("module bar exports ", bar)
module.exports = "foo.js"

// bar.js
const foo = require("./foo.js")

console.log("module foo exports ", foo)
module.exports = "bar.js"

  webpackУпаковка приведенного выше кода может быть упрощена следующим образом. когдаbar.jsимпортировать сноваfoo.js, прямой возвратinstalledModulesЗначение в , которое в данном случае является пустым объектом.

(function(modules) {
  var installedModules = {}

  function require(moduleId) {
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports
    }

    var module = (installedModules[moduleId] = {
      i: moduleId,
      exports: {}
    })

    modules[moduleId].call(module.exports, module, module.exports, require)

    return module.exports
  }

  return require("./index.js")
})({
  "./bar.js": function(module, exports, require) {
    const foo = require("./foo.js")

    console.log("module foo exports ", foo)
    module.exports = "bar.js"
  },

  "./foo.js": function(module, exports, require) {
    const bar = require("./bar.js")

    console.log("module bar exports ", bar)
    module.exports = "foo.js"
  },

  "./index.js": function(module, exports, require) {
    require("./foo.js")
  }
})

как следуетES6 ModuleКруговая зависимость , выходной результатmodule foo exports undefined module bar exports bar.js.bar.jsтоже не могу получитьfoo.jsпроизводное значение , сCommonJSЭкспорт пустых объектов по умолчанию отличается, на этот разundefined.

// index.js
import foo from "./foo.js"

// foo.js
import bar from "./bar.js"

console.log("module bar exports ", bar)
export default "foo.js"

// bar.js
import foo from "./foo.js"

console.log("module foo exports ", foo)
export default "bar.js"

ИспользоватьES6 ModuleОсобенности креплений, модифицированные круглые крепления. во-первыхindex.jsимпортировать и выполнятьfoo.js,foo.jsимпортировать и выполнятьbar.js,bar.jsИмпортироватьfoo.js, так как в это времяfoo.jsне завершен,fooвсе еще дляundefined,Потомbar.jsФункция экспорта, возврат права на выполнениеfoo.js,foo.jsСнова экспортируйте функцию и верните право на выполнениеindex.js, и, наконец, выполнитьfooфункция, которая будет выполняться из-за отношения привязкиfoo.jsвнутренняя функция, воляinvokedустановлен вtrue, а затем выполнитьbar.jsфункция,barФункция выполняется сноваfooфункционировать, но из-заfoo.jsВнутриinvokedзаtrue,fooФункция не выполняется, поэтому порядок выполненияfoo bar foo.

// index.js
import foo from "./foo.js"

foo()

// foo.js
import bar from "./bar.js"
var invoked = false

export default function() {
  if (!invoked) {
    invoked = true
    bar()
    console.log("module bar exports ", bar)
  }
}

// bar.js
import foo from "./foo.js"

export default function() {
  console.log("module foo exports ", foo)
  foo()
}

AMD

  AMDТо есть он поддерживает спецификацию модуляризации на стороне браузера, а метод загрузки модулей является асинхронным, и выполнение последующих операторов не будет затронуто при загрузке модуля.RequireJSДостигнутоAMDСпецификация.

   определяетAMDмодуль, каталог включаетindex.htmlиindex.js,foo.js,bar.jsмодуль.require.jsМодули могут бытьcdnспособ представить,data-mainУказывает основной файл модуля.

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

  defineОпределить модуль.Параметры - это имя текущего модуля, зависимости текущего модуля и значение экспорта модуля (функция или объект, если это функция, экспортировать возвращаемое значение функции, если это объект , экспортируйте его напрямую).

  AMDПо сравнению со стандартным модулем с синхронной загрузкой синтаксис более подробный, а метод загрузки не такой понятный, как при синхронной загрузке.

// index.html
...
<body>
    <p>hello world</p>
    <script src="./require.js" data-main="./index.js"></script>
</body>

// index.js
require.config({
    paths: {
        "foo": "./foo",
        "bar": "./bar"
    }
})
require(["foo"], function (foo) {
    console.log('module foo exports ', foo)
}, function (err) {
    console.log(err)
})

// foo.js
define('foo', ['bar'], function (bar) {
    console.log('module bar exports ', bar)
    return 'foo.js'
})

// bar.js
define('bar', function () {
    return 'bar.js'
})

CMD

  CMDЭто еще одна спецификация модульности на стороне браузера, а также модуль асинхронной загрузки.SeaJsДостигнутоCMDСпецификация.

  AMDПорядок выполнения и порядок записи нескольких зависимых модулей не согласованы, в зависимости от скорости сети, какой из них загружается первым, а какой выполняется первым, а основная логика выполняется после загрузки всех зависимостей.

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

  AMDзависит от предпосылки,CMDЭто близкая зависимость.RequireJSиSeaJsОба предварительно загружают зависимые модули перед выполнением модулей, но время выполнения зависимых модулей отличается.RequireJsвыполняется под нагрузкой, аSeajsвыполняется при использовании.

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

// index.html
...
<body>
    <p>hello world</p>
    <script src="./sea.js"></script>
    <script src="./index.js"></script>
</body>

// index.js
seajs.config({
    paths: {
        foo: "./foo",
        bar: "./bar"
    }
})
seajs.use(['foo'], function (foo) {
    console.log('module foo exports ', foo)
})

// foo.js
define(function (require, exports, module) {
    var bar = require('bar')

    console.log('module bar exports ', bar)
    module.exports = 'foo.js'
})

// bar.js
define(function (require, exports, module) {
    module.exports = 'bar.js'
})

UMD

  UMDэтоJavaScriptОбщая спецификация определения модуля, которую можно использовать вJavaScriptработать во всех операционных средах.

одиночный модуль

немодульная среда

  Немодульные среды обычно монтируют свойства через глобальный объект. вfoo.jsЧтобы выполнить функцию немедленно,factoryВозвращаемое значение фабричной функции монтируется в глобальный объект,rootявляется глобальным объектом, значение которого равноwindowилиglobal, определяется операционной средой.

// index.html
...
<body>
    <p>hello world</p>
    <script src="./foo.js"></script>
    <script src="./index.js"></script>
</body>

// foo.js
(function (root, factory) {
    root.foo = factory()
})(this, function () {
    return 'foo.js'
})

// index.js
console.log(foo)

AMD

  AMDспособ удовлетворитьAMDСпецификация.


// index.html
...
<body>
    <p>hello world</p>
    <script src="./require.js" data-main='./index.js'></script>
</body>

// index.js
require.config({
    paths: {
        "foo": "./foo"
    }
})
require(["foo"], function (foo) {
    console.log(foo)
}, function (err) {
    console.log(err)
})

// foo.js
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define('foo', factory)
    } else {
        root.foo = factory()
    }
})(this, function () {
    return 'foo.js'
})

UMD

  UMDТо есть он поддерживает немодульные среды,CommonJS,AMD,CMDКанонический модуль.

// foo.js
(function(root, factory) {
  if (typeof module === "object") {
    module.exports = factory()
  } else if (typeof define === "function" && define.amd) {
    define("foo", factory)
  } else if (typeof define === "function" && define.cmd) {
    define(function(require, exports, module) {
      module.exports = factory()
    })
  } else {
    root.foo = factory()
  }
})(this, function() {
  return "foo.js"
})

многомодульный

  UMDмодули зависят от другихUMDвремя модуля.

AMD

// index.html
...
<body>
    <p>hello world</p>
    <script src="./require.js" data-main='./index.js'></script>
</body>

// index.js
require.config({
    paths: {
        foo: "./foo",
        bar: "./bar"
    }
})
require(["foo"], function (foo) {
    console.log('module foo exports ', foo)
})

// foo.js
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define('foo', ['bar'], factory)
    } else {
        root.foo = factory(root.bar)
    }
}(this, function (bar) {
    console.log('module bar exports ', bar)
    return 'foo.js'
}))

// bar.js
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define('bar', factory)
    } else {
        root.bar = factory()
    }
}(this, function () {
    return 'bar.js'
}))

UMD

// foo.js
(function(root, factory) {
  if (typeof module === "object") {
    var bar = require("./bar")

    module.exports = factory(bar)
  } else if (typeof define === "function" && define.amd) {
    define("foo", ["bar"], factory)
  } else if (typeof define === "function" && define.cmd) {
    define(function(require, exports, module) {
      var bar = require("bar")

      module.exports = factory(bar)
    })
  } else {
    root.foo = factory(root.bar)
  }
})(this, function(bar) {
  console.log("module bar exports ", bar)
  return "foo.js"
})(
  // bar.js
  (function(root, factory) {
    if (typeof module === "object") {
      module.exports = factory()
    } else if (typeof define === "function" && define.amd) {
      define("bar", factory)
    } else if (typeof define === "function" && define.cmd) {
      define(function(require, exports, module) {
        module.exports = factory()
      })
    } else {
      root.bar = factory()
    }
  })(this, function() {
    return "bar.js"
  })
)

ввод и вывод ресурсов

концепция

  • module:всеjs,css,pngи т.д. файлыmoduleмодуль
  • chunk: блок кода,webpackМодуль, от которого зависит входной файл в процессе упаковки, а модуль зависит от других модулей.Набор вышеуказанных модулей называетсяchunk
  • bundle: пакетный файл,webpackУпакуйте сгенерированные исходные файлы

  module,chunk,bundleСуть в разных названиях одного и того же набора кодовой логики в разных сценариях преобразования. На этапе написания каждый отдельный файл являетсяmoduleмодуль. На этапе упаковки набор, состоящий из всех модулей, от которых зависит входной файл, представляет собойchunkкодовый блок. После упаковки и вывода каждый исходный файлbundleпакетный файл.

   визуализируйте сцену упаковки, чтобы описать вышеуказанные концепции, гдеwebpack.config.jsКонфигурационный файл выглядит следующим образом, функция плагина только в том, чтобы извлечь его отдельноcssдокумент.

// webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

module.exports = {
  entry: {
    index: "./index.js",
    main: "./main.js",
  },
  output: {
    filename: "[name].js",
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
            MiniCssExtractPlugin.loader,
            "css-loader"
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    }),
  ],
}

   Входные файлы соответственноindex.jsиmain.jsindex.jsпредставилindex.cssстиль иutilsфункция класса полезности,mian.jsявляется отдельным модулем.

// index.js
import './index.css'
import { log } from './utils.js'

log('index.js')

// index.css
p { 
  background: blue; 
}

// utils.js
export function log(val) {
  console.log(val)
}

// main.js
console.log('main.js')

   Примечание может быть связано с некоторыми плагинами иloaderверсия сwebpackРазница в зависимости версии приводит к ошибке упаковки.Возможно следующееpackage.jsonдокумент.

// package.json
{
    ...
    "devDependencies": {
        "webpack": "4.29.4",
        "webpack-cli": "3.2.3",
        "css-loader": "^0.28.9",
        "mini-css-extract-plugin": "^0.5.0"
    }
}

   Выполните команду упаковки для завершения, результат будет следующим.

在这里插入图片描述

  Исходный модульindex.css,utils.js,index.jsиmain.js, этап упаковкиindex.js,index.cssиutils.jsкодовый блокchunk 0,main.jsСоставьте блоки кодаchunk 1, после упаковки выводаindex.css,index.jsиmain.jsОба являются пакетными файлами.

—— module ———— chunk ———— bundle
 index.css                index.css
           \           /
 utils.js ——  chunk 0  —— index.js
           /
 index.js
 main.js  ——  chunk 1  —— main.js

Вход

  entryТо есть путь к файлу записи,webpackНачните упаковку на основе этого.

   Если вы передаете строку или массив строк,chunkбудет названmain.

   Если передается объект, ключ для каждого свойства будетchunkНазвание.

Тип строки

module.exports = {
    entry: './index.js',
    ...
}

тип массива

module.exports = {
    entry: ['./main.js', './index.js'],
    ...
}

тип объекта

module.exports = {
    entry: {
        index: './index.js',
        main: './main.js'
    },
    ...
}

тип функции

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

module.exports = {
  entry: () => "./index.js",
}

module.exports = {
  entry: () =>
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("./index.js")
      }, 5000)
    })
}

экспорт (выход)

filename

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

module.exports = {
    ...
    output: {
        filename: '../build/index.js',
    }
}

  webpackТакже поддерживается форма, похожая на язык шаблонов, для динамического создания имен файлов. следующееfilenameсерединаnameбудет заменен наchunk name, т. е. ресурс, генерируемый конечным проектом, равенindex.jsиmain.js.

module.exports = {
    entry: {
        index: './index.js',
        main: './main.js'
    },
    output: {
        filename: '[name].js',
    }
    ...
}

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

  • hash:webpackГенерируется путем упаковки всех ресурсовhash
  • id:Текущийchunkизid
  • chunkhash:Текущийchunkсодержаниеhash

path

  pathИспользуется для указания пути вывода ресурса, и значение должно быть абсолютным путем.Установите расположение вывода ресурса в проекте следующим образом.libсодержание.webpack4+Версия по умолчаниюdistКаталог, если не изменен выходной путь, в противном случае его не нужно настраивать отдельно.

const path = require('path')

module.exports = {
    ...
    output: {
        ...
        path: path.join(__dirname, 'lib'),
    }
}

publicPath

  pathИспользуется для указания выходного местоположения ресурса,publicPathИспользуется для указания запрошенного местоположения ресурса.

   Запрошенное местоположение определяетсяjsилиcssЗапрошенный непрямой путь к ресурсу, напримерhtmlзагруженscript, или загружаются асинхронноjs,cssзапрошенные фотографии и т. д.,publicPathТо есть указать место запроса вышеуказанного ресурса.

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

// index.html
<html lang="zh-CN">
    ...
<body>
    <div id="app">hello world</div>
</body>

</html>

// index.js
console.log('index.js')

// package.json
{
  ...
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "^4.29.4",
    "webpack-cli": "^3.2.3",
    "html-webpack-plugin": "^3.2.0"
  }
}

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: './index.js',
    output: {
        filename: 'index.js',
        publicPath: '/lib/',
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html',
        })
    ]
}

бегатьnpm run buildПосле упаковки он будет сгенерирован в текущем корневом каталоге.distпапка, которая включаетindex.htmlиindex.js.

// index.html
<html lang="zh-CN">
  ...
  <body>
    <div id="app">hello world</div>
    <script type="text/javascript" src="/lib/index.js"></script>
  </body>
</html>

  VS CodeУстановка редактораLive SeverПлагин для эмуляции на этой машинеindex.htmlРеальная сцена развернута на сервер,index.htmlЩелкните правой кнопкой мыши внутриOpen with Live ServerЗапустите локальную службу и откройте интерфейс отладки браузера.NetworkЭлементы можно просмотреть следующим образомjsзапрос, которыйRequest URLТо есть запрос местоположения ресурса.

在这里插入图片描述

  publicPathРазница в итоге приведет к разным адресам запросов ресурсов, гдеpublicPathРазделенный на следующие три формы, текущийindex.htmlАдрес файлаhttp://127.0.0.1:5500/dist/index.html, имя ресурсаindex.js.

  • htmlСвязанный: Пути ресурсов против.htmlАссоциация каталога файлов, то есть путь к ресурсуhtmlпуть к каталогу плюсpublicPathи имя файла
———— publicPath ———————— Request URL
     ''                  http://127.0.0.1:5500/dist/index.js
     './js'              http://127.0.0.1:5500/dist/js/index.js
     '../assets/'        http://127.0.0.1:5500/assets/index.js
  • Относится к корневому каталогу: еслиpublicPathот'/'запускается, путь к ресурсу основан на пути к корневому каталогу страницы
———— publicPath ———————— Request URL
     '/'                 http://127.0.0.1:5500/index.js
     '/js'               http://127.0.0.1:5500/js/index.js
     '/dist/'            http://127.0.0.1:5500/dist/index.js
  • Абсолютный путь: в случае абсолютных путей статические ресурсы обычно помещаются вCDNвыше
———— publicPath ———————— Request URL
     'https://cdn.com/'  https://cdn.com/index.js
     '//cdn.com/'        http://cdn.com/index.js

devServer.publicPath

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

   При запускеdevServerРесурсы упакованы в память,devServerОн отправится в память, чтобы найти упакованный файл ресурсов, а затем перейдет в локальный каталог, чтобы найти содержимое,devServer.contentBaseВы можете контролировать, куда он идет для доступа к ресурсам локального каталога.

  contentBaseПо умолчанию используется текущая рабочая директория, если ресурс в памяти не найден, он перейдет вcontentBaseНайти в.

   Если не указаноdevServer.publicPath,devServerполучитеoutput.publicPathЗначение , чтобы избежать несоответствий между средой разработки и производственной средой, обычно сохраняютdevServer.publicPathиoutput.publicPathто же или не указаноdevServer.publicPath.

препроцессор

  webpackможет только справитьсяJavaScriptиJSONфайл, для других ресурсов, таких какcss, изображения или другие наборы синтаксисаtsНет возможности его загрузить.loaderпозволятьwebpackВозможность обработки других типов файлов и преобразования их вwebpackМодуль, который может получать, загружается,loaderПо сути, это предварительная обработка.

Каждыйloaderпо сути является функцией, грубо говоря, в видеoutput = loader(input),inputдля конвертируемого модуля,outputДля преобразованного модуля используйтеbabel-loaderбудетES6+код преобразуется вES5, приведенная выше формаES5 = babel-loader(ES6+).loaderможно связать, т.е.loaderВыход можно использовать как другойloaderввод в видеoutput = loaderA(loaderB(input))).

  loaderвключаютtestиuseдва свойства,testИспользуется для определения того, какие файлы будут преобразованы,useОпределяет, какой из них следует использовать при преобразованииloader.

элемент конфигурации

options

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

module.exports = {
    ...
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        ...
                    }
                }
            }
        ]
    }
}

exclude/include

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

{
    test: /\.js$/,
    exclude: /node_modules/
    ...
}

  includeУказывает, что включены только соответствующие модули, как показано ниже:srcсодержание.

{
    test: /\.js$/,
    include: /src/
    ...
}

какincludeиexcludeодновременно существуют,excludeболее высокий приоритет. Исключить следующим образомnode_modulesпод все модули.

{
    test: /\.js$/,
    exclude: /node_modules/,
    include: /node_modules\/lodash/
    ...
}

resource/issuer

  resourceявляется грузополучателем, иissuerявляются загрузчиками, оба из которых могут использоваться для более точного охвата правил модуля.

   Следующее толькоsrcв каталогеjsНа документы можно ссылатьсяcss.

{
    test: /\.css$/,
    use: ['style-loader', 'css-loader'],
    issuer: {
        test: /\.js$/,
        include: /src/
    }
}

вышеtest,include,excludeЭлементы конфигурации распределены по разным уровням, что менее читабельно. Лучше добавитьresourceОбъект обертывает внешнюю конфигурацию.

   Следующее кромеnode_modulesвнизjs,остальныеjsможно процитироватьcssдокумент. Толькоsrcв каталогеcssНа документы можно ссылаться.

{
    use: ['style-loader', 'css-loader'],
    issuer: {
        test: /\.js$/,
        exclude: /node_modules/
    },
    resource: {
        test: /\.css$/,
        include: /src/
    }
}

enforce

   используется для указанияloaderтипы, получать толькоpreилиpostДва типа.webpackсерединаloaderПорядок выполнения можно разделить наpre(приоритет),inline(вторая обработка),normal(обычная обработка),post(окончательная обработка), прямо определенная вышеloaderпо умолчаниюnormalтип,postиpreнужно использоватьenforeуказать.

   означает следующееeslint-loaderбудет во всем нормloaderвыполнял раньше. На самом деле не нужно указыватьenforceПросто гарантияloaderПорядок выполнения правильный, настроитьenforceОсновная цель — сделать правила модуля более понятными и читабельными.

rules: [
  {
    test: /\.js$/,
    enforce: "pre",
    use: "eslint-loader",
  },
]

Общий загрузчик

sass-loader

  sass-loaderдаscssПрепроцессор для файлов типов, обрабатывающий их синтаксис и компилирующий вcss.sass-loaderядро зависит отnode-sassnode-sassзависит отnode, обратите внимание при установкеnode-sassиnodeМежду версиями поддерживаются.

послеcss-loaderиметь дело сcssРазличные синтаксис загрузки@imoprtилиurl()функция преобразуется вrequire. просто поставьcssмодуль загружен вjsкод, фактически не используемый.

   Наконец,style-loaderбудетjsСтрока стиля обернута какstyleВкладки вставляются на страницу.

   Вышеуказанные сценарии обработки следующие, корневой каталог включаетindex.js,index.scss,index.html,package.jsonЖдать.

// package.json
{
  ...
  "scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "4.29.4",
    "webpack-cli": "3.2.3",
    "webpack-dev-server": "3.1.14",
    "html-webpack-plugin": "3.2.0",
    "css-loader": "^0.28.9",
    "style-loader": "^0.19.0",
    "node-sass": "^4.7.2",
    "sass-loader": "^6.0.7"
  }
}

// index.scss
$color: red;

p {
    color: $color;
}

// index.js
import './index.scss'

// index.html
<html lang="zh-CN">
    ...
<body>
    <p>hello world</p>
</body>

</html>

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: './index.js',
    output: {
        filename: 'index.js'
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: ['style-loader', 'css-loader', 'sass-loader'],
            }
        ],
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html',
        })
    ],
    mode: 'development',
}

бегатьnpm run dev, откройте страницу для просмотраcssстили были введены вhtmlбинго.

在这里插入图片描述

babel-loader

  babel-loaderиспользуется для обработкиES6+и скомпилировать его какES5, чтобы он мог использовать новейшие языковые функции в проекте, не беспокоясь о совместимости этих функций на разных платформах.

Установитьbabelнеобходимо установить одновременноbabel-loader,@babel/coreи@babel/preset-env. в@babel/coreдаbabel-loaderЗависимые модули ядра,@babel/preset-envЭто официально рекомендуемый префаб, который может автоматически добавлять необходимые плагины и исправления для компиляции в соответствии с целевым браузером или операционной средой, настроенной пользователем.ES6+код,babel-loaderВызывается как промежуточный мост@babel/coreизapiрассказатьwebpackчто делатьjs.

{
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: /node_modules/,
    options: {
        cacheDirectory: true,
        presets: [
            ['@babel/preset-env', { modules: false }]
        ]
    },
}

  babel-loaderобычно компилирует всеjsмодуль, который серьезно замедлит скорость упаковки и может изменить исходное поведение сторонних модулей, поэтому необходимоexcludeисключатьnode_modules.

  cacheDirectoryВключение механизма кеша при переупаковке неизмененных модулей попытается прочитать кеш, избегая высокопроизводительного процесса перекомпиляции.cacheDirectoryполучить путь типа string илиtrue,заtrueбудет использовать каталог кеша по умолчанию, когдаnode_modules/.cache/babel-loader.

  @babel/preset-envбудетES6 Muduleпревратиться вCommonJs, приведет кwebpackизtree-shakingнедействительно, можно установитьmodulesзаfalseвместо этого отключите это поведениеES6 Moduleпреобразование вwebpackиметь дело с.

  babel-loaderТакже поддерживает внешний.babelrcконфигурационный файл, будетpresetsиpluginsизвлечено.

// .babelrc
{
    "presets": [
        ["@babel/preset-env", { "modules": false }]
    ]
}

url-loader

  url-loaderМодуль для упаковки типов файлов менее чем заlimitПорог изображения для обработки и преобразования его вbase64кодирование.

   Конвертировать картинкуbase64В код введена кодировка, что позволяет уменьшить количество запросов и повысить производительность страницы. но и увеличитьjsилиhtmlРазмер файла большой, и изображения используются в проекте много раз, и каждое опорное место будет создано.base64кодирования, что приводит к избыточности кода. С другой стороны, браузеры могут кэшироватьhttpзапрошенное изображение. Поэтому его нужно сбалансировать и установить разумно.limitпорог.

{
  test: /\.(png|jpg|gif)$/,
  use: {
    loader: 'url-loader',
    options: {
      limit: 10240
    }
  }
}

file-loader

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

{
    test: /\.(png|jpg|gif)$/,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: 'img/[name].[hash:8].[ext]'
            }
        },
    ],
}

vue-loader

  vue-loaderиспользуется для обработкиvueфайл, извлекитеtemplate/script/styleкод, а затем передать их соответствующемуloaderиметь дело с. вcss-loaderиметь дело сstyleкод стиля,vue-template-compilerответственный заtemplateШаблон компилируется вrenderфункция визуализации,vue-loaderПоддержка по умолчаниюES6, каждыйvueКомпоненты могут быть созданыcssразмах и т.д.

использоватьvue-loaderСценарий следующий, корневой каталог включаетindex.html,index.js,App.vueи другие документы.

// package.json
{
  ...
  "scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "4.29.4",
    "webpack-cli": "3.2.3",
    "webpack-dev-server": "3.1.14",
    "html-webpack-plugin": "3.2.0",
    "css-loader": "^0.28.9",
    "vue": "^2.5.13",
    "vue-loader": "^14.1.1",
    "vue-template-compiler": "^2.5.13"
  }
}

// index.js
import Vue from "vue"
import App from "./App.vue"

new Vue({
  el: "#app",
  render: (h) => h(App),
})

// index.html
<html lang="zh-CN">
    ...
<body>
    <div id="app"></div>
</body>

</html>

// App.vue
<template>
  <h1>{{ title }}</h1>
</template>

<script>
export default {
  name: "app",
  data() {
    return {
      title: "hello world",
    }
  }
}
</script>

<style lang="css">
h1 {
  color: blue;
}
</style>

// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = {
  entry: "./index.js",
  output: {
    filename: "[name].js",
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: "vue-loader",
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./index.html",
    }),
  ],
  mode: "development",
}

бегатьnpm run dev,App.vueбыл установлен наdiv#appэлемент,h1Шаблон в также отображается какhello world.

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

инициализация

  Пользовательская реализация одногоloader, для всехjsфайл с включенным строгим режимом, т.е. добавление в его заголовок'use strict'.

Создайтеstrict-loaderкаталог, выполнитьnpm initИнициализировать каталог, создатьloaderосновной файлindex.js.

// index.js
module.exports = function(content) {
  var useStrictPrefix = "'use strict'\n\n"

  return useStrictPrefix + content
}

  webpackТехнические ссылкиstrict-loaderuse.loaderссылка на абсолютный путьstrict-loader, можно изменить в любое времяloaderотладка исходного кода в .

// webpack.config.js
module.exports = {
  entry: "./index.js",
  output: {
    filename: "[name].js",
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: "F:/strict-loader",
        },
      },
    ],
  },
  devtool: "none",
  mode: "development"
}

// package.json
{
  ...
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "4.29.4",
    "webpack-cli": "3.2.3"
  }
}

// index.js
console.log("hello world")

Выполнение проектаnpm run build, часть исходного кода после упаковки и вывода выглядит следующим образом.

在这里插入图片描述

включить кеш

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

// strict-loader/index.js
module.exports = function(content) {
  if (this.cacheable) {
    this.cacheable()
  }

  var useStrictPrefix = "'use strict'\n\n"

  return useStrictPrefix + content
}

параметр опций

  loaderЭлементы конфигурации могут бытьuse.optionsпройти в. необходимо установитьloader-utilsБиблиотека зависимостей с некоторыми вспомогательными функциями, предоставляемыми ею.

npm i loader-utils@1.1.0 --save

  loaderПолучатьoptionsСпособ следующий.

// strict-loader/index.js
var loaderUtils = require("loader-utils")

module.exports = function (content) {
    ...
    var options = loaderUtils.getOptions(this) || {}

    console.log("options", options)
    ...
}

обработка стиля

Отдельные файлы стилей

  style-loaderОберните строку стиля какstyleтеги вставляются на страницу, но в рабочей среде вы хотите, чтобы стили существовали вcssфайл вместоstyleтег, потому что файл более удобен для кэширования на стороне клиента.

  webpack4-В основном используетсяextract-text-webpack-pluginплагин для извлечения стилей вcssдокумент.

единый стиль

  Корневой каталог включаетindex.html,index.js,index.cssи другие документы. будет следующимindex.jsупакован вindex.htmlв, из нихwebpack.config.jsсерединаExtractTextPlugin.extractсерединаuseИспользуется, чтобы указать, какие стили взять перед извлечениемloaderдля предварительной обработки,fallbackИспользуется для указания того, что использовать, когда плагин не может извлечь стили.loader,new ExtractTextPluginПараметр определяет имя выходного файла.

// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextPlugin = require("extract-text-webpack-plugin")

module.exports = {
  entry: './index.js',
  output: {
    filename: "[name].js",
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader",
        }),
      },
    ],
  },
  plugins: [
    new ExtractTextPlugin("index.css"),
    new HtmlWebpackPlugin({
      template: "./index.html",
    }),
  ],
  mode: "development"
}

// package.json
{
  ...
  "scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "4.29.4",
    "webpack-cli": "3.2.3",
    "webpack-dev-server": "3.1.14",
    "html-webpack-plugin": "3.2.0",
    "css-loader": "^0.28.7",
    "style-loader": "^0.19.0",
    "extract-text-webpack-plugin": "^4.0.0-beta.0"
  }
}

// index.html
<html lang="zh-CN">
  ...
  <body>
    <p>hello world</p>
  </body>
</html>

// index.js
import "./index.css"

// index.css
p { 
  color: blue; 
}

бегатьnpm run dev, чтобы увидеть, что извлеченные файлы ссылаются наindex.htmlсередина.

在这里插入图片描述

несколько файлов

   Когда имеется несколько файлов ввода, и разные файлы ввода представляют разныеcssстили, извлечь несколькоcssСтили следующие. Корневой каталог включаетfoo.js,foo.css,bar.jsиbar.css.

// foo.js
import "./foo.css"

// foo.css
p { 
  color: blue;
}

// bar.js
import "./bar.css"

// bar.css
h5 { 
  color: red; 
}

// index.html
<html lang="zh-CN">
  ...
  <body>
    <p>hello</p>
    <h5>world</h5>
  </body>
</html>

  package.jsonЗависимость соответствует одному файлу,webpack.config.jsНебольшая регулировка. следующее[name].cssсерединаnameотносится кchunk name,СейчасentryИмя, присвоенное записи (foo,bar).

// webpack.config.js
module.exports = {
  entry: {
    foo: "./foo.js",
    bar: "./bar.js",
  },
  ...
  plugins: [
    new ExtractTextPlugin("[name].css"),
    ...
  ],
}

бегатьnpm run dev, вы можете видеть, что несколько извлеченных файлов ссылаются наindex.htmlсередина.

在这里插入图片描述

какindex.jsпрошедшийimport()загружается асинхронноfoo.js,foo.jsзагружен вfoo.css, то в конце концовfoo.cssмогут быть загружены только синхронно или могут быть загружены только сstyleВставьте этикетку вhtml, не может быть загружен по требованию.

нагрузка по требованию

  Webpack4+в основном используютmini-css-extract-pluginизвлекатьcssстили, которые можно динамически вставлятьlinkТеги загружаются по запросу.

  Корневой каталог включаетindex.js,index.css,foo.jsиfoo.cssи другие документы.

// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

module.exports = {
  entry: "./index.js",
  output: {
    filename: "[name].js",
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          "css-loader",
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./index.html",
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  mode: "development",
}

// package.json
{
  ...
  "scripts": {
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "devDependencies": {
    "webpack": "4.29.4",
    "webpack-cli": "3.2.3",
    "webpack-dev-server": "3.1.14",
    "html-webpack-plugin": "3.2.0",
    "css-loader": "^0.28.7",
    "mini-css-extract-plugin": "^0.5.0"
  }
}

// index.js
import "./index.css"

setTimeout(() => {
  import("./foo.js")
}, 2000)

// index.css
p { 
  color: blue; 
}

// foo.js
import "./foo.css"

// foo.css
h5 { 
  color: red; 
}

// index.html
<html lang="zh-CN">
  ...
  <body>
    <p>hello</p>
    <h5>world</h5>
  </body>
</html>

бегатьnpm run dev,2sЗаднийheadбудет динамически вставляться вlinkэтикетки иscriptЭтикетка.

在这里插入图片描述

postcss

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

postcss-loader

  postcss-loaderМожет использоваться отдельно или сcss-loaderиспользуется в комбинации, когда используется отдельноpostcss-loader, не рекомендуется использоватьcssиспользуется в@import, иначе будет сгенерирован избыточный код.

  postcss-loaderнуждаться вcss-loaderиstyle-loaderпосле использования, но после других препроцессоров (таких какsass-loaderИспользуйте это раньше.

  postcssТребуется отдельный файл конфигурации, который необходимо создать в корневом каталогеpostcss.config.js, без добавления каких-либо функций можно временно вернуть пустой объект.

// webpack.config.js
{
   test: /\.css/,
   use: ['style-loader', 'css-loader', 'postcss-loader'],
}

// package.json
"devDependencies": {
    ...
    "css-loader": "^0.28.7",
    "postcss-loader": "^2.1.2",
    "style-loader": "^0.19.0"
}

// postcss.config.js
module.exports = {}

autoprefixer

  autoprefixerзаcssАвтоматически добавлять префиксы поставщиков браузеров в соответствии сCan I UseДанные определяют, следует ли добавлять префикс к функции.

  Корневой каталог включаетindex.css,index.html,index.jsиpostcss.config.jsЖдать.

// package.json
"devDependencies": {
    ...
    "autoprefixer": "^8.1.0"
}

// postcss.config.js
const autoprefixer = require('autoprefixer')

module.exports = {
  plugins: [
    autoprefixer({
      grid: true,
      browsers: ['> 1%', 'last 3 versions', 'ie 8'],
    })
  ]
}

// index.css
div { 
  display: grid; 
}

// index.js
import './index.css'

   упаковано какgridдобавлена ​​функцияieпрефикс.

在这里插入图片描述

stylelint

  stylelintЯвляетсяcssинструмент обнаружения кода, похожий наeslint, к которому можно добавить различные правила для унификации качества стиля кода проекта.

  postcss.config.jsиpackage.json,index.cssЧасти следующие, из которыхdeclaration-no-importantиспользуется в коде!importantстиль выдает предупреждение.

// package.json
"devDependencies": {
    ...
    "postcss-loader": "^2.1.2"
}

// postcss.config.js
const stylelint = require('stylelint')

module.exports = {
  plugins: [
    stylelint({
      config: {
        rules: {
          'declaration-no-important': true,
        },
      },
    })
  ],
}

// index.css
div {
  color: red !important;
}

   Следующее предупреждающее сообщение будет выведено на консоль при выполнении упаковки.

在这里插入图片描述

cssnext

  cssnextВы можете использовать последнюю версию в своем проектеcssСинтаксические особенности.

// package.json
"devDependencies": {
    ...
    "postcss-cssnext": "^3.1.0"
}

// postcss.config.js
const postcssCssnext = require('postcss-cssnext')

module.exports = {
  plugins: [
    postcssCssnext({
      browsers: ['> 1%', 'last 2 versions'],
    })
  ]
}

// index.css
:root {
  --highlightColor: #666;
}

p {
  color: var(--highlightColor);
}

   Результат после упаковки следующий.

在这里插入图片描述

CSS Modules

  CSS Modulesпредставляет собой стильное модульное решение, в котором каждыйcssИмеет отдельную область действия, не конфликтует с внешним миром и может импортироваться по относительным путям.cssмодуль, который может бытьcomposesповторно использовать другиеcssмодуль.

  CSS ModulesНе нужно устанавливать дополнительные модули, открывайтеcss-loaderизmodulesэлементы конфигурации.

вlocalIndentNameуказать скомпилированныйcssстиль имени класса,nameотносится к имени модуля,localОтносится к исходному идентификатору селектора,hash:base64:5за5немногоhashзначение, этоhashЗначение вычисляется из имени и идентификатора модуля.

// webpack.config.js
{
   test: /\.css/,
   use: [
      "style-loader",
      {
         loader: "css-loader",
         options: {
          modules: true,
          localIdentName: "[name]__[local]__[hash:base64:5]"
         }
      }
  ]
}

// index.css
.title { 
  color: red; 
}

// index.js
import style from './index.css'

document.write(`<div class='${style.title}'>hello wolrld</div>`)

   Проверьте имя скомпилированного класса после упаковки.

在这里插入图片描述

Следующий

🎉 Напишите в конце

🍻Ребята, если вы видели это и считаете, что эта статья была вам полезна, ставьте лайк 👍 илиStar✨Поддержите!

Кодирование вручную, если есть ошибки, исправьте их в комментариях 💬~

Ваша поддержка — самая большая мотивация для меня обновляться💪~

GitHub,Blog,Наггетс,CSDNСинхронизированное обновление, подписывайтесь 😉~