предисловие
Всего у этого предмета24Раздел, оглавление:
- Соберите проект и упакуйте файлы JS.
- Режим производства и разработки
- Переопределить ввод/вывод по умолчанию
- Транспиляция ES6 с помощью Babel 7
- Code Splitting
- Ленивая загрузка, предварительная выборка
- Автоматически генерировать файлы HTML
- Работа с файлами CSS/SCSS
- JS Tree Shaking
- CSS Tree Shaking
- Сводка по обработке изображения
- работа с файлами шрифтов
- Работа со сторонними библиотеками js
- Режим разработки и webpack-dev-сервер
- Режим разработки и режим производства・Настоящий бой
- Упаковка пользовательских функций
- Конфигурация ПВА
- Конфигурация TypeScript
- Конфигурация Эслинта
- Используйте DLLPlugin для ускорения упаковки
- Конфигурация многостраничной упаковки
- загрузчик записи
- Написать плагин
- Написать пакет
Первые 15 разделов основаны наWebpack4 прогрессивный учебникОсновываясь на моей собственной практике и понимании, спасибоСердечный загар😄
существуетWebpack4 прогрессивный учебникМодернизация на основе:
- использоватьbabel7
- настроить.browserslistrcдокумент
- использоватьmini-css-extract-pluginзаменятьextract-text-webpack-plugin
- использоватьoptimize-css-assets-webpack-pluginкомпрессияcss
- использоватьpostcssдляcssплюс каждый префикс браузера
- использоватьimage-webpack-loaderобрабатывать изображения
Последующие главы начинаются сmoocсетьРука об руку с вами, чтобы освоить новую версию Webpack4.0Организованные учебные заметки, спасибоDellLeeучитель 😄
Окружение выглядит следующим образом:
OS: 「win10」
node: 「10.5.0」
npm: 「6.1.0」
webpack: 「4.29.6」
webpack-cli: 「3.2.3」
Каждая глава соответствует демо 👉Адрес источника,Адрес сопроводительного документа, после клонирования исходного кода обратите внимание на запускnpm install
Установить зависимости
Я впервые пишу статью, надеюсь, вы укажете на не то место и исправите его как можно скорее.
1. Соберите проект и упакуйте файл JS.
Создайте пустую папку, инициализируйте, выполнив следующую командуpackage.json
npm init -y
npm init используется для инициализации нового файла package.json. Он задаст пользователю ряд вопросов, и если вы считаете, что вам не нужно изменять конфигурацию по умолчанию, просто нажмите Enter до конца. Если используется -y (для да), этап вопроса пропускается и создается новый файл package.json.
Представьте веб-пакет4:
npm i webpack --save-dev
Вам также понадобится webpack-cli, который представлен как отдельный пакет.Если вы не установите webpack-cli, вы не сможете использовать webpack в командной строке.
npm i webpack-cli --save-dev
Веб-версия этого проекта выглядит следующим образом:
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3"
Теперь откройте package.json и добавьте скрипт сборки:
Попробуйте запустить и посмотрите, что произойдет:
npm run build
В версиях до webpack 4 точка входа должна была быть определена через атрибут entry в файле конфигурации с именем webpack.config.js, например:
Начиная с webpack4, больше не нужно определять точку входа: по умолчанию она будет./src/index.js
Чтобы протестировать эту новую функцию, сначала создайте файл ./src/index.js.
бежать сноваnpm run build
пытаться
Упаковка прошла успешно, и запакованная папка получена в текущем корневом каталоге, т.е.distпапка
Это выглядит./src/index.jsв качестве точки входа по умолчанию. Кроме того, это будет./dist/main.jsПакет среднего модуля вывода, текущий объем кода небольшой, вы можете отформатировать его, чтобы увидеть эффект
На этом заканчивается упаковка JS
Ссылаться на:Начало работы с официальным сайтом webpack
2. Режим производства и разработки
Наличие 2 файлов конфигурации является распространенным шаблоном в webpack.
Типичный проект может иметь:
- Файлы конфигурации для разработки, горячего обновления конфигурации, междоменной конфигурации, настройки портов и т. д.
- Конфигурационные файлы для продакшна, настройка минимизации js, разделение кода и т. д.
В то время как для более крупных проектов может потребоваться 2 файла конфигурации, в webpack4 вы можете сделать это без единой строки конфигурации.
webpack4 представил режимы производства и разработки.
Внимательные друзья найдут вnpm run build
После упаковки будет сигнал тревоги
Параметр «режим» не установлен, веб-пакет вернется к «производственному». Установите для параметра «режим» значение «разработка» или «производство», чтобы включить значения по умолчанию для каждой среды. Вы также можете установить значение «none», чтобы отключить любое поведение по умолчанию.понять больше
- Откройте package.json и заполните раздел script следующим образом:
"dev": "webpack --mode development",
"build": "webpack --mode production"
- бегать
npm run dev
Откройте файл ./dist/main.js, который является файлом бандла (пакета) и не сжат!
- бегать
npm run build
Вы можете видеть, что файл ./dist/main.js был сжат.
На самом деле его можно найти и в терминале, посмотрев на размер сборки, размер файла в режиме dev 3,8 КБ, а размер файла в режиме prod всего 960 байт.
производственный режим включает различные оптимизации из коробки. Включает уплотнение, подъем объема, встряхивание деревьев и т. д.
С другой стороны, режим разработки оптимизирован для скорости и предоставляет только несжатый пакет.
В webpack4 все можно сделать без единой строчки конфигурации! Просто определите параметр --mode, чтобы получить все!
3. Переопределите ввод/вывод по умолчанию
1. Проверьте поддержку спецификации веб-пакета
webpack поддерживает спецификации ES6, CommonJS, AMD
Создайте папку поставщика с файлами minus.js, multi.js и sum.js, написанными в спецификациях CommonJS, AMD и ES6 соответственно.
// minus.js
module.exports = function(a, b) {
return a - b
}
// multi.js
define(function(require, factory) {
'use strict'
return function(a, b) {
return a * b
}
})
// sum.js
export default function(a, b) {
return a + b
}
существуетapp.jsВставьте указанные выше три файла js в файл
/**
* webpack 支持 ES6、CommonJs 和 AMD 规范
*/
// ES6
import sum from './vendor/sum'
console.log('sum(1, 2) = ', sum(1, 2))
// CommonJs
var minus = require('./vendor/minus')
console.log('minus(1, 2) = ', minus(1, 2))
// AMD
require(['./vendor/multi'], function(multi) {
console.log('multi(1, 2) = ', multi(1, 2))
})
2. Напишите файл конфигурации для переопределения ввода/вывода
webpack.config.js — это веб-пакетПо умолчаниюИмя конфигурационного файла, созданного в корневом каталоге
const path = require('path')
module.exports = {
entry: {
app: './app.js' // 需要打包的文件入口
},
output: {
publicPath: __dirname + '/dist/', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: 'bundle.js' // 打包后生产的 js 文件
}
}
path.resolve()
Метод преобразует путь или последовательность фрагментов пути в абсолютный путь.
__dirname
: Имя папки текущего модуля.
можно использоватьconsole.log
Просто выведите это
const path = require('path')
console.log('__dirname: ', __dirname)
console.log('path.resolve: ', path.resolve(__dirname, 'dist'))
module.exports = {
entry: {
app: './app.js' // 需要打包的文件入口
},
output: {
publicPath: __dirname + '/dist/', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: 'bundle.js' // 打包后生产的 js 文件
}
}
воплощать в жизньnpm run build
упаковать js-файл
Вы обнаружите, что создается папка dist и создаются два упакованных файла.
Это связано с тем, как AMD была представлена: если вы закомментируете запись AMD в app.js, будет упакован только один файл bundle.js.
При написании кода лучше всего использовать спецификации ES6 и CommonJS.
Когда вы комментируете AMD, после упаковки в dist есть несколько файлов, потому что при упаковкеСначала не удалял файл dist, а затем пакет, нам нужно использовать плагин, чтобы сделать это за нас, ссылка на GitHub:clean-webpack-plugin
① Установите плагин
npm install clean-webpack-plugin --save-dev
② Измените файл конфигурации веб-пакета.
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
entry: {
app: './app.js' // 需要打包的文件入口
},
output: {
publicPath: __dirname + '/dist/', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: 'bundle.js' // 打包后生产的 js 文件
},
plugins: [
new CleanWebpackPlugin() // 默认情况下,此插件将删除 webpack output.path目录中的所有文件,以及每次成功重建后所有未使用的 webpack 资产。
]
}
ВНИМАНИЕ!Если установленный плагин clean-webpack-plugin3.0версии, конфигурация должна быть изменена на:
// common js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
выполнить позжеnpm run build
просто хорошо
Упакованный файл js будет помещен в каталог dist в соответствии с нашей конфигурацией,Создайте html-файл, который ссылается на упакованный файл js., откройте F12, чтобы увидеть эффект
Справочная статья
Серия руководств webpack4 (1): упаковка JS
Учебное пособие по Webpack4: от нулевой конфигурации к рабочему режиму
4. Транспиляция ES6 с помощью Babel 7
(1) Понять Вавилон и его экологию
Современный Javascript в основном написан на ES6. Но не каждый браузер знает, как обращаться с ES6. Нам нужно какое-то преобразование, и этот шаг преобразования называется транспилированием. Транспиляция относится к использованию синтаксиса ES6 для перевода в поведение, понятное старым браузерам.
Webpack не знает, как выполнить преобразование, но имеетпогрузчик: относиться к ним как к транспиляторам.
babel-loaderЯвляется загрузчиком веб-пакетов (загрузчиком) для транспиляции ES6 и выше в ES5.
Для началаloader, нам нужно установить кучу зависимостей, следующееBabel7Господин,Предложение по обновлению
- @babel/core
- @babel/preset-env: содержит правила преобразования синтаксиса для ES6, 7 и т. д.
- @babel/plugin-transform-runtime: избегайте загрязнения глобальных переменных полифиллом и уменьшайте размер упаковки.
- @babel/polyfill: Встроенные прокладки преобразования методов и функций ES6.
- babel-loader: отвечает за преобразование синтаксиса ES6
Если вы выполняете транспиляцию с помощью babel7, вам необходимо установить@babel/core,@babel/preset-envа также@babel/plugin-transform-runtimeвместо babel-core, babel-preset-env и babel-plugin-transform-runtime, которые предназначены для babel6.
Причины использовать @babel/plugin-transform-runtime: Babel использует очень маленькие помощники для общих функций. По умолчанию это будет добавлено к каждому файлу, который в этом нуждается.Это повторение иногда не нужно, особенно если ваше приложение распределено по нескольким файлам.transform-runtimeПрограммный код, введенный Babel, можно повторно использовать дляСохранить код и уменьшить размер.
Причины использования @babel/polyfill: Babel по умолчанию преобразует только новый синтаксис (синтаксис) JavaScript, а не новые.API,НапримерГлобальные объекты, такие как Iterator, Generator, Set, Maps, Proxy, Reflect, Symbol, Promise и т. д.и некоторые методы, определенные для глобального объекта (например,Object.assign) не будет перекодирован. должен использовать@babel/polyfill, который обеспечивает прокладку для текущей среды. Так называемая прокладка призвана сгладить разницу между разными браузерами или разными средами.
(2) Установите зависимости и настройте
① Зависимости установки
npm i @babel/core babel-loader @babel/preset-env @babel/plugin-transform-runtime --save-dev
npm i @babel/polyfill @babel/runtime
② В корневом каталоге проекта создайте файл с именем.babelrcновый файл для настройкиBabel:
{
"presets": ["@babel/preset-env"],
"plugins": ["@babel/plugin-transform-runtime"]
}
Спасибо за раздел комментариевxcswebОтмечается, что если вы столкнулись со следующей ошибкой
WARNING: We noticed you're using the `useBuiltIns` option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the `corejs` option.
You should also be sure that the version you pass to the `corejs` option matches the version specified in your `package.json`'s `dependencies` section. If it doesn't, you need to run one of the following commands:
npm install --save core-js@2 npm install --save core-js@3
yarn add core-js@2 yarn add core-js@3
Не только для установки npm install --save core-js@3, но и для установки .babelrc set "corejs": 3
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3
}
]
],
"plugins": ["@babel/plugin-transform-runtime"]
}
③ загрузчик конфигурации webpack (загрузчик)
module: {
rules: [
{
test: /\.js$/, // 使用正则来匹配 js 文件
exclude: /node_modules/, // 排除依赖包文件夹
use: {
loader: 'babel-loader' // 使用 babel-loader
}
}
]
}
Окончательная конфигурация webpack.config.js:
④ Внедрить глобально в app.js@babel/polyfill
и написать синтаксис ES6 и выполнитьnpm run build
Пакет
// 全局引入
import '@babel/polyfill'
// 测试 ES6 语法是否通过 babel 转译
const array = [1, 2, 3]
const isES6 = () => console.log(...array)
isES6()
const arr = [new Promise(() => {}), new Promise(() => {})]
arr.map(item => {
console.log(item)
})
5 после упаковкиИспользуйте браузер IEОткройте файл index.html, чтобы увидеть, есть ли вывод в консоли.Если это новая версия Chrome, вы можете использовать синтаксис es6, поэтому используйтеIEэтоКорень всех золпытаться
глобальный импорт@babel/polyfill
Этот способ импорта полифилов, которые не нужны в коде, может увеличить размер пакета.
Изменять.babelrc
, переводить только то, что мы используем
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]
],
"plugins": ["@babel/plugin-transform-runtime"]
}
При этом закомментируйте глобальное введение этого кода и снова упакуйте его
// 全局引入
// import '@babel/polyfill'
Объем значительно уменьшен, но в большинстве случаев мы не знаем точно конкретных причин проблем совместимости в проекте, поэтомуЛучше импортировать по всему миру
(3) Разберитесь с файлом конфигурации .browserslistrc
browserslistrcКонфигурация для совместного использования целевого браузера и версии Node.js между различными внешними инструментами
Проверить список браузеровСтраницы, совместимые с браузером
когда вы добавляете следующее вpackage.json
, все инструменты автоматически найдут целевой браузер:
"browserslist": [
"> 1%",
"last 2 version",
"not ie <= 8"
]
также может создать.browserslistrc
Конфигурация записи файла отдельно
# 所支持的浏览器版本
> 1% # 全球使用情况统计选择的浏览器版本
last 2 version # 每个浏览器的最后两个版本
not ie <= 8 # 排除小于 ie8 以下的浏览器
В проекте до сих пор используетсяСоздавайте профили индивидуальноЭто легко понять, если вы считаете, что файл конфигурации не очень хорош, вы также можете написать его вpackage.json
середина
Справочная статья
Серия руководств webpack4 (2): Компиляция ES6
Личное понимание использования babel 7
5. Разделение кода
package.json
Зависимости, используемые файлом npm install install:
{
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
"devDependencies": {
"clean-webpack-plugin": "^2.0.0",
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3"
},
"dependencies": {
"lodash": "^4.17.11"
}
}
Мы создаем файл index.js в папке src/
import _ from 'lodash'
console.log(_.join(['a', 'b', 'c']))
Структура каталогов:
Настройте файл webpack.config.js
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js'
},
output: {
publicPath: __dirname + '/dist/', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
plugins: [new CleanWebpackPlugin()]
}
бегатьnpm run build
Пакет
Используйте упакованный файл в index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>代码分割</title>
</head>
<body>
<script src="./dist/main.bundle.js"></script>
</body>
</html>
Открыть в браузереindex.html
файл, войдите в консоль, вы увидите следующую информацию:a,b,c
Если мы снова изменим бизнес-код, измените код в index.js на
import _ from 'lodash'
console.log(_.join(['a', 'b', 'c'], '***'))
Переупакуйте, обновите страницу, чтобы увидетьa***b*****c**
Сторонний фреймворк, на который мы ссылаемся, упакован с нашим бизнес-кодом, так в чем же проблема?
Предположим, что lodash равен 1M, бизнес-код также равен 1M, а после упаковки предполагается, что он равен 2M.
Каждый раз, когда браузер открывает страницу, он должен загрузить файл размером 2 МБ, прежде чем сможет отобразить бизнес-логику, что увеличит время загрузки.
Обновление бизнес-кода будет сравниватьчасто, сторонний код в принципе не изменится, поэтому после переупаковки, при условии, что это 2M, после того, как пользователь снова откроет веб-страницу, файл 2M будет загружен снова.
браузер имееттайникДа, если файл не изменился, вам не нужно отправлять http-запрос, а получить его прямо из кеша, что может ускорить скорость загрузки страницы при обновлении страницы или входе на нее во второй раз.
Как это решить, вы можете использовать разделение кода в веб-пакете
До того, как webpack4 использовалcommonsChunkPluginразделить общий код, который был заменен после v4заброшенныйи использоватьsplitChunksPlugins
Прежде чем использовать splitChunksPlugins, сначала узнайте, что splitChunksPlugins — это модуль подразделения в основном модуле веб-пакета.Не требуется импорт npm
Теперь давайте настроимwebpack.config.jsдокумент
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js'
},
output: {
publicPath: __dirname + '/dist/', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
plugins: [new CleanWebpackPlugin()]
}
Выделенный фрагмент кода выше указывает веб-пакету выполнить разделение кода, вотchunks: 'all'
заключается в разделении всего кода, включая синхронный код и асинхронный код, по умолчанию webpackchunks: 'async'
сегментацияасинхронныйкод
Мы используемnpm run dev
упаковать код в среде разработки, чтобы кодне будет сжиматься, что нам удобно наблюдать, мы видим, что код разбит на два файла
Открытьdist/main.bundle.jsвы можете увидеть файл src/index.js внизу, который содержит код для бизнес-логики, но нет кода для lodash
Открытьdist/vendors~main.jsфайл, вверху вы видите модуль lodash
Откройте страницу снова, и консоль также выводит содержимое, что достигаетсяCode Splitting(разделение кода)
На самом деле, когда нет вебпака, тоже есть разбиение кода, но нам нужно вручную разбить его самим, а сейчас мы используем вебпак, через этот пункт конфигурации, он автоматически поможет нам сделать разбиение кода
Посмотрите внимательно на раздельное кодовое имя,vendors~main.js
, вносим изменения в имя сплита
еще вsplitChunks
в пункте конфигурации добавитьcacheGroups
объект
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
name: 'vendors'
}
}
}
}
Вы можете увидеть эффект, когда снова упакуете его.cacheGroupsКонфигурация по умолчанию будет определятьvendorsа такжеdefault
test: /[\\/]node_modules[\\/]/,
Использование обычной фильтрации толькоnode_modulesПредставленные сторонние библиотеки будут разделены
Чтобы проверить конфигурацию по умолчанию, мы устанавливаем для свойства splitChunks пустой объект и снова упаковываем
После упаковки обнаружил, что файл всего один, почему так?
потому чтоchunks
По умолчаниюasync
, будет только разделятьсяасинхронный, и раньше мы писали синхронный код, сначала импортировали lodash, а потом писали бизнес-логику, теперь делаем это асинхронно, и меняем код в index.js на следующий:
function getComponent() {
// 使用 异步的形式导入 lodash,default: _ 表示用 _ 代指 lodash
return import('lodash').then(({ default: _ }) => {
var element = document.createElement('div')
element.innerHTML = _.join(['hello', 'world'], '-')
return element
})
}
getComponent().then(element => {
document.body.appendChild(element)
})
разделенный здесь0.js
а такжеmain.bundle.js
, 0 назван с идентификатором в качестве числа
Поэтому обычно мы устанавливаем куски для всех, и упаковывается как асинхронный, так и синхронный код.
Теперь давайте скопируем конфигурацию по умолчанию с официального сайта webpack в наш webpack.config.js для анализа.
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
Конфигурация разделения кода вебпака такая, например, если мы хотим разделить сторонние библиотеки, такие как jQuery и lodash, то сначала он пройдет черезchunks、minSize、maxSize、minChunks
Подождите, после выполнения условий сгенерируйте два файла, jQuery и lodash, и поместите их вcacheGroupкэшируется вcacheGroupнастроен вГруппаЧтобы решить, следует ли интегрировать два файла в один пакет файлов или упаковать их отдельно, например, в приведенном выше кодеvendors, этоnode_modules
Все сторонние библиотеки упакованы вvendors.jsфайл, если вы хотите продолжить разделение, вы можете сделать это
cacheGroups: {
lodash: {
name: 'lodash',
test: /[\\/]node_modules[\\/]lodash[\\/]/,
priority: 5 // 优先级要大于 vendors 不然会被打包进 vendors
},
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
Спасибо за раздел комментариевanlinsirУказано, что если есть ошибка в упаковкеПоддержка экспериментального синтаксиса «dynamicImport» в настоящее время не включена.,Это потому чтоdynamicImportЭто все еще экспериментальный синтаксис, веб-пакет его не поддерживает, вам необходимо установить плагины для его поддержки. Конкретные шаги см.блог woo woo woo.cn на.com/beyond its/afraid…
Снова упакуйте его, и вы увидите, что lodash разделен. Позже сторонние библиотеки могут быть разбиты на js-файл с этой конфигурацией, напримерelement-ui,УведомлениенастраиватьpriorityЗначение очень важно, чем выше приоритет, тем быстрее будет упакован пакет.
Если index.js вводит A.js и B.js, а A и B также вводят общий, общий вводится дважды, и его можно назвать общим модулем.
Структура каталогов:
код показывает, как показано ниже:
// a,js
import './common'
console.log('A')
export default 'A'
// b.js
import './common'
console.log('B')
export default 'B'
// common.js
console.log('公共模块')
export default 'common'
// index.js
// 异步代码
import(/* webpackChunkName: 'a'*/ './a').then(function(a) {
console.log(a)
})
import(/* webpackChunkName: 'b'*/ './b').then(function(b) {
console.log(b)
})
// 异步代码
function getComponent() {
// 使用异步的形式导入 lodash,default: _ 表示用 _ 代指 lodash
return import('lodash').then(({ default: _ }) => {
var element = document.createElement('div')
element.innerHTML = _.join(['hello', 'world'], '-')
return element
})
}
getComponent().then(element => {
document.body.appendChild(element)
})
тот, что вышеасинхронныйСпособ написания может быть более запутанным, теперь упростите его, и веб-пакет прав.асинхронный кодпройти черезПримечанияВы можете напрямую изменить имя пакета. Следующие коды представлены в асинхронной форме.
// 异步代码
import(/* webpackChunkName: 'a'*/ './a').then(function(a) {
console.log(a)
})
import(/* webpackChunkName: 'b'*/ './b').then(function(b) {
console.log(b)
})
import(/* webpackChunkName: 'use-lodash'*/ 'lodash').then(function(_) {
console.log(_.join(['1', '2']))
})
Установите для minChunks значение 2, минимальное общее значение 2 раза для разделения
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
lodash: {
name: 'lodash',
test: /[\\/]node_modules[\\/]lodash[\\/]/,
priority: 10
},
commons: {
name: 'commons',
minSize: 0, //表示在压缩前的最小模块大小,默认值是 30kb
minChunks: 2, // 最小公用次数
priority: 5, // 优先级
reuseExistingChunk: true // 公共模块必开启
},
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
разделенный здесьlodash
и мы определили в комментарияхuse-lodash
, первая — это третья библиотека, а вторая — бизнес-код, написанный с использованием третьей библиотеки, которую также можно разделить
Причина, по которой здесь автоматически вводятся разделенные зависимости, вы можете просмотреть в упакованном видеmain.bundle.jsдокумент
Даже мы можем разбить точку, чтобы увидеть, как это работает, ниже приведена демонстрация анимации gif.Наиболее часто используемые элементы конфигурации приведены в таблице ниже.Дополнительные сведения о конфигурации см.Официальный сайт
элемент конфигурации | иллюстрировать | Пример |
---|---|---|
chunks | тип соответствующего блока | initial (начальный фрагмент), async (асинхронные фрагменты, загружаемые по запросу), all (все фрагменты) |
name | Используется для управления именованием отдельных блоков кода. | chunk-libs |
test | Расположение файла для указания совпадений групп кэша | /[\/]node_modules[\/]/ |
priority | Приоритет правила разделения, чем выше приоритет, тем первым будет соответствовать | priority: 20 |
minSize | Сжатие сверх размера | minSize: 30000 Значение по умолчанию — 30 КБ. |
minChunks | Минимальное количество блоков, которые должны совместно использовать модули перед разделением | minChunks: 2 |
reuseExistingChunk | Если текущий блок был отделен от основного модуля, он будетПовторное использованиевместо этого он генерирует новые куски | true |
Справочная статья
Серия руководств webpack4 (3): многостраничное решение — извлечение общего кода
6. Ленивая загрузка, предварительная выборка
Измените файл index.js на основе demo5 и удалите лишние файлы js.
document.addEventListener('click', function() {
import(/* webpackChunkName: 'use-lodash'*/ 'lodash').then(function(_) {
console.log(_.join(['3', '4']))
})
})
Этот код означает, что когда нажата страница, Lodash загружена асинхронно и содержимое выводится, а файл index.html открывается после упаковки. Демонстрация выглядит следующим образом:
Когда я захожу на страницу в первый раз, lodash и use-lodash не загружаются, когда я нажимаю на веб-страницу, браузер снова загружает ее, а консоль выводит содержимое, это кодленивая загрузка, если используетсяvue-routerдрузья должны знатьОтложенная загрузка маршрута, и официальный также рекомендует использовать ленивую загрузку, просто для объединения веб-пакета, на следующем рисунке показан проект, сгенерированный vue-cli3.
На самом деле ленивая загрузка происходит черезimportЧтобы загрузить модуль асинхронно, когда его загружать, это должно быть написано в соответствии с бизнесом, например, компоненты всплывающего окна, компоненты модального окна и т. д., все они появляются после нажатия кнопки.
Ленивая загрузка может ускорить загрузку веб-страниц.Если вы упаковываете все страницы, такие как страницы сведений и всплывающие окна, в файл js, если пользователи посещают только домашнюю страницу, им нужен только код домашней страницы, и не нужен код других страниц и добавить дополнительный код, это только увеличит время загрузки, поэтому мы можем лениво загружать маршрут и загружать соответствующий модуль только тогда, когда пользователь обращается к соответствующему маршруту
Ленивая загрузка — это концепция не в webpack, а в ES6.importСинтаксис, webpack может распознавать только синтаксис импорта и выполнять сегментацию кода.
То, что возвращается после импорта, — это then, указывающее, что этоpromiseтип, некоторые недорогие браузерыне поддерживаетсяобещания, напримерIE, если вы хотите использовать этот асинхронный код, вам нужно использоватьbabelтак же какbabel-polyfillсделать преобразование, потому что я использую версию 73chromeБраузер поддерживает синтаксис ES6, поэтому я могу использовать его без установки babel.
Измените файл index.js
document.addEventListener('click', function() {
const element = document.createElement('div')
element.innerHTML = 'Hello World'
document.body.appendChild(element)
})
Перепакуйте и откройте index.html , откройте консоль браузера, нажмитеctrl + shift + p
,войтиcoverage
Вы можете увидеть неиспользованную скорость кода js, загруженного на текущей странице, а красная область представляет собой неиспользуемый сегмент кода.
Демо:
Открытьcoverage
Если анализируемый файл не отображается, не забудьте обновить его
Здесь код в красной области сначала не используется, когда я нажимаю на страницу, она становится зеленой и появляется страницаHello World
Указание того, что код используется
Когда страница только что загружена, асинхронный код вообще не будет выполняться, но если мы его загрузим, это фактически приведет к потере производительности выполнения страницы.Webpack надеется взаимодействовать с такими функциями, и его следует поместить в асинхронную загрузку. . модуль для записи
Создайте новый файл click.js
function handleClick() {
const element = document.createElement('div')
element.innerHTML = 'Dell Lee'
document.body.appendChild(element)
}
export default handleClick
И измените файл index.js для асинхронной загрузки модуля:
document.addEventListener('click', () => {
import('./click.js').then(({ default: func }) => {
func()
})
})
переупаковывать, использоватьcoverageанализировать
Демо:
Когда страница загружается, бизнес-логика не загружается.При нажатии на страницу загружается модуль 1.js, который мы представили асинхронно в index.js.
Такой способ написания кода — самый быстрый способ загрузки страниц.Дело не в кешировании, а в использовании кода
Поэтому в процессе упаковки веб-пакета мы надеемся, что сможем написать больше асинхронного кода для повышения производительности веб-сайта, поэтому фрагменты в разделенных фрагментах веб-пакета по умолчанию являются асинхронными, асинхронными.
Асинхронный код может повысить производительность открытия вашей веб-страницы, а синхронный код должен добавить кеш, улучшение производительности очень ограничено, потому что кеш обычноОткройте страницу второй раз или обновите страницукеш полезен, но производительность веб-страницы, как правило, зависит от пользователя.Открытие веб-страницы в первый раз, глядя на первый экран.
Конечно, будет и другая проблема, то есть когда пользователь нажимает, загружается бизнес-модуль, если бизнес-модуль относительно большой, пользователь не видит эффект сразу после нажатия, а ждет несколько секунд, так что опыт это не хорошо, как решить эту проблему
Первый: если вы посещаете домашнюю страницу, вам не нужно загружать логику страницы сведений.После загрузки домашней страницы пользователя страница будет отображаться, пропускная способность страницы будет освобождена, и сеть будет отключена. быть бездействующим, поэтому вы можете «тайно» загрузить страницу сведений, а не загружать ее, когда пользователь нажимает
Это решение основано на веб-пакетеPrefetching/Preloadingхарактеристика
Изменить index.js
document.addEventListener('click', () => {
import(/* webpackPrefetch: true */ './click.js').then(({ default: func }) => {
func()
})
})
webpackPrefetch: true
Он будет ждать загрузки вашего основного JS, а когда пропускная способность сети будет простаивать, он загрузит его для вас заранее.
Обновите страницу после перепаковки, обратите внимание наNetwork
Когда веб-страница открыта, main.bundle.js загружается, а сеть простаивает. Предварительная загрузка 1.js занимает 14 мс. Когда я нажимаю на страницу, в сети есть еще один 1.js, который занимает 2 мс. , это потому что 1.js загружается в первый раз, и он кешируется браузером, когда я нажимаю, браузер напрямую извлекает его из кеша, и скорость отклика очень высокая
Здесь мы используемwebpackPrefetch
, а другой естьwebpackPreload
По сравнению с предварительной выборкой директива Preload имеет многоразница:
Prefetch
Для оптимизации дело не только в кеше, улучшение производительности кода, которое может принести кеш, очень ограничено, но и в том, как сделать кодПрименениеСамое высокое, некоторый код, который используется после взаимодействия, может быть записан в асинхронный компонент, а логика кода загружается в виде ленивой загрузки, что сделает скорость доступа к странице быстрее.Если вы думаете, что ленивая загрузка повлияет на пользовательский опыт , вы можете использовать Prefetch для предварительной загрузки, но в некоторых браузерахнесовместимый, будут проблемы с совместимостью, фокус не на том, как использовать Prefetch, а на оптимизации производительности фронтенд-кода,Кэширование не самый важный момент, самое главное это покрытие использования кода (coverage)
7. Автоматически генерировать файлы HTML
Считаете ли вы, что после операций, описанных в приведенных выше разделах, каждый раз изменять файл js, представленный в index.html, очень проблематично? После изменения имени пакета вы также должны соответствующим образом изменить имя js, представленное в index.html. Чтобы использовать плагин, чтобы помочь нам, после упаковкиАвтоматически генерировать файлы HTML,И автоматически импортируйте упакованный файл js
(1) Зависимости установки
npm i html-webpack-plugin html-loader --save-dev
package.json выглядит следующим образом:
{
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
"devDependencies": {
"clean-webpack-plugin": "^2.0.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3"
},
"dependencies": {
"lodash": "^4.17.11"
}
}
(2) Измените файл конфигурации
module.exports = {
plugins: [
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html' // 根据此模版生成 HTML 文件
})
]
}
HtmlWebpackPluginОн настраивается в опции плагина. Общие параметры имеют следующие значения:
- title: заголовок html, сгенерированный после упаковки
- имя файла: имя упакованного html файла
- template: файл шаблона (index.html в корневом каталоге исходного кода примера)
- куски: соответствует конфигурации записи, поддерживает несколько страниц и несколько записей
- minify: параметры сжатия
из-за использованияtitle
вариант, вам нужноtemplate
Добавить в заголовок html соответствующий параметру<%= htmlWebpackPlugin.options.title %>
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
module.exports = {
entry: {
page: './src/page.js'
},
output: {
publicPath: __dirname + '/dist/', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html' // 根据此模版生成 HTML 文件
})
],
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
lodash: {
name: 'chunk-lodash', // 单独将 lodash 拆包
priority: 10, // 优先级要大于 commons 不然会被打包进 commons
test: /[\\/]node_modules[\\/]lodash[\\/]/
},
commons: {
name: 'chunk-commons',
minSize: 1, //表示在压缩前的最小模块大小,默认值是 30kb
minChunks: 2, // 最小公用次数
priority: 5, // 优先级
reuseExistingChunk: true // 公共模块必开启
}
}
}
}
}
(3) Упаковка и тестирование
бегатьnpm run build
Откройте автоматически созданный index.html в папке dist.
Откройте файл index.html в браузере, откройте консоль и обнаружите, что есть вывод, ОК, файл HTML успешно сгенерирован автоматически.
Осторожные друзья могут найти проблему, JS, представленный в сгенерированном файле HTML,абсолютный путь, но после того, как реальный проект запакован, он развертывается на сервере.Использовать абсолютный путь точно нельзя, потому что абсолютный путь вашего локального компьютера не может быть найден на сервере.
Файл js, который мы хотим импортироватьИзменение абсолютного пути на относительный путь
Измените файл webpack.config.js.
Найдите выходную конфигурацию вывода, измените общедоступный путь publicPath и измените его на./
абсолютный путь
output: {
publicPath: './', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
Упакуйте его еще раз, посмотрите упакованный файл index.html и откройте браузер для проверки, это не проблема.
8. Обработка файлов CSS/SCSS
(1) Подготовка
Распространенные способы импорта CSS в HTML:<link>
этикетки и<style>
Существует два типа тегов, поэтому на этот раз они сочетаются с характеристиками веб-пакета для достижения следующих функций:
- Внедрить css через тег ссылки
- поместите css в тег стиля
На следующем рисунке показана структура кода каталога на этот раз:
На этот раз нам нужно использоватьcss-loader
,style-loader
Подождите, пока загрузчик, такой как babel, webpack не знает, как извлечь CSS в файлы. Необходимо использовать загрузчик для загрузки соответствующего файла
css-loader: отвечает за синтаксический анализ кода CSS, в основном для обработки зависимостей в CSS, таких как объявления @import и url(), которые ссылаются на внешние файлы.
style-loader преобразует результат, проанализированный css-loader, в код JS при запускеЯрлык стиля динамической вставкичтобы код CSS работал.
(2) Зависимости установки
npm i css-loader style-loader --save-dev
package.json
следующим образом:
{
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
"devDependencies": {
"clean-webpack-plugin": "^2.0.0",
"css-loader": "^2.1.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.5.0",
"style-loader": "^0.23.1",
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3"
}
}
изменить файл конфигурации
module.exports = {
module: {
rules: [
{
test: /\.css$/, // 针对 .css 后缀的文件设置 loader
use: ['style-loader', 'css-loader']
}
]
}
}
Настройте свойство rules в модуле, например, при настройке babel, сначала используйте обычные правила в тесте для фильтрации.css
файл, да.css
файл с помощью загрузчика,'style-loader', 'css-loader'
Пишите стили в base.css
*,
body {
margin: 0;
padding: 0;
}
html {
background: red;
}
И внедрить base.css в app.js
import style from './css/base.css'
Полный код конфигурационного файла:
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin') // 引入插件
module.exports = {
entry: {
app: './src/app.js'
},
output: {
publicPath: './', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
module: {
rules: [
{
test: /\.css$/, // 针对 .css 后缀的文件设置 loader
use: ['style-loader', 'css-loader'] // 使用 loader
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html', // 根据此模版生成 HTML 文件
chunks: ['app'] // entry中的 app 入口才会被打包
})
]
}
Упаковка проекта, просмотр папки dist
обнаружить иНе создается файл CSS, но открытие index.html оформлено в стиле
Причина в следующем:style-loader
, css-loader
После обработки двух загрузчиков код CSS будет преобразован в JS и упакован с помощью index.js.
можно найти по<style>
css для внедрения тегов
Если нам нужно отделить файл CSS отдельно, нам нужно использоватьmini-css-extract-pluginплагин.
использовалextract-text-webpack-plugin
плагин, этот плагин не совсем соответствует webpack4, теперь используйтеmini-css-extract-plugin
Обязательно обновите веб-пакет до4.2.0версии и выше. иначеmini-css-extract-pluginбудет недействительным!
ещеГорячее обновление не поддерживается, то есть, если вы меняете css в среде разработки, вам нужно вручную обновить страницу, чтобы увидеть эффект. В настоящее время этот плагин обычно используется в производственной среде, и «style-loader» по-прежнему используется в среде разработки.Подробнее см.Официальная конфигурация сайта
npm i mini-css-extract-plugin --save-dev
Измените файл конфигурации:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
module: {
rules: [
{
test: /\.css$/, // 针对 .css 后缀的文件设置 loader
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
}
Полный код:
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
module.exports = {
entry: {
app: './src/app.js'
},
output: {
publicPath: './', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
module: {
rules: [
{
test: /\.css$/, // 针对 .css 后缀的文件设置 loader
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader'
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html', // 根据此模版生成 HTML 文件
chunks: ['app'] // entry中的 app 入口才会被打包
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
}
Это просто генерирует отдельный файл css, но он не сжимается, импортируяoptimize-css-assets-webpack-pluginПлагин для реализации сжатия css
npm install optimize-css-assets-webpack-plugin --save-dev
Полный код:
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') // 压缩 css
module.exports = {
entry: {
app: './src/app.js'
},
output: {
publicPath: './', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
module: {
rules: [
{
test: /\.css$/, // 针对 .css 后缀的文件设置 loader
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader'
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html', // 根据此模版生成 HTML 文件
chunks: ['app'] // entry中的 app 入口才会被打包
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'), //用于优化\最小化 CSS 的 CSS处理器,默认为 cssnano
cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, //传递给 cssProcessor 的选项,默认为{}
canPrint: true //布尔值,指示插件是否可以将消息打印到控制台,默认为 true
})
]
}
Когда вы снова открываете файл css, вы можете обнаружить, что он был сжат, а открытие index.html также оформлено в стиле
(3) Обработка файлов SCSS
Зависимость установки sass:
npm i node-sass sass-loader --save-dev
Добавьте папку scss и файл main.scss в папку src.
стиль импорта main.scss
$bgColor: black !default;
*,
body {
margin: 0;
padding: 0;
}
html {
background-color: $bgColor;
}
Добавьте файл main.scss в app.js.
import './css/base.css'
import './scss/main.scss'
Изменить файл конфигурации
const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') // 压缩 css
module.exports = {
entry: {
app: './src/app.js'
},
output: {
publicPath: './', // js 引用的路径或者 CDN 地址
path: path.resolve(__dirname, 'dist'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
chunkFilename: '[name].js' // 代码拆分后的文件名
},
module: {
rules: [
{
test: /\.(scss|css)$/, // 针对 .scss 或者 .css 后缀的文件设置 loader
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
'sass-loader' // 使用 sass-loader 将 scss 转为 css
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html', // 根据此模版生成 HTML 文件
chunks: ['app'] // entry中的 app 入口才会被打包
}),
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'), //用于优化\最小化 CSS 的 CSS处理器,默认为 cssnano
cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, //传递给 cssProcessor 的选项,默认为{}
canPrint: true //布尔值,指示插件是否可以将消息打印到控制台,默认为 true
})
]
}
Позиция загрузчика в массиве module.rules.use. По правилам вебпака:Последний загрузчик выполняется первым, если писать сверху вниз, то первым будет выполняться нижний, если писать слева направо, то правый будет выполняться первым..
['style-loader', 'css-loader', 'sass-loader']
Порядок выполнения такойsass-loader --> css-loader --> style-loader
Сначала вы должны использовать sass-loader для компиляции scss в css., остальная часть конфигурации аналогична обработке файлов css.
После упаковки и открытия файла index.html вы обнаружите, что стиль был перезаписан стилем, прописанным в main.scss, и обработка scss прошла успешно.
(4) Добавить префикс браузера в CSS
Установитьpostcss-loaderа такжеautoprefixerполагаться
npm install postcss-loader autoprefixer --save-dev
Датьsrc/scss/main.css
добавьте этот код в
.example {
display: grid;
transition: all 0.5s;
user-select: none;
background: linear-gradient(to bottom, white, black);
}
Есть два способа настройкиpostcss, первый прописан прямо в webpack.config.js
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/, // 针对 .sass .scss 或者 .css 后缀的文件设置 loader
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
// 使用 postcss 为 css 加上浏览器前缀
{
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')]
}
},
'sass-loader' // 使用 sass-loader 将 scss 转为 css
]
}
]
}
После упаковки проверьте файл dist/app.css.
Второй способ — создать новый файл конфигурации postcss.config.js в каталоге того же уровня, что и webpack.config.js.
module.exports = {
plugins: [require('autoprefixer')]
}
Также в webpack.config.js
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/, // 针对 .sass .scss 或者 .css 后缀的文件设置 loader
use: [
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
'postcss-loader', // 使用 postcss 为 css 加上浏览器前缀
'sass-loader' // 使用 sass-loader 将 scss 转为 css
]
}
]
}
Поскольку правила в модуле выполняются в обратном порядке, приведенный выше порядок выполнения
sass-loader
->postcss-loader
->css-loader
->MiniCssExtractPlugin.loader
postcss-loader
Используется после css-loader и style-loader, но перед другими загрузчиками препроцессора, такими как sass | less | stylus-loader
Пополнить:
Используйте свойство importLoaders в css-loader
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/, // 针对 .sass .scss 或者 .css 后缀的文件设置 loader
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: css - loader,
options: {
importLoaders: 2
}
},
'postcss-loader', // 使用 postcss 为 css 加上浏览器前缀
'sass-loader' // 使用 sass-loader 将 scss 转为 css
]
}
]
}
importLoaders: 2Он представляет собой: css, встроенный в другой css, будет выполнять два предыдущих загрузчика, то есть postcss-loader и sass-loader.
Ссылаться на:руководство по официальному веб-сайту webpack