1. Что такое веб-пакет
Webpack — это инструмент для упаковки, и его цель — упаковать все статические ресурсы. Некоторые люди спросят, почему webpack? Webpack является краеугольным камнем современных интерфейсных технологий, а традиционные методы разработки, такие как jquery, html и css, статическая веб-разработка отстают. Это эпоха MVVM, интерфейсов, управляемых данными. Вебпак анализирует структуру вашего проекта, находит модули JavaScript и другие языки расширения (Scss, TypeScript и т. д.), которые браузеры не могут запускать напрямую, и упаковывает их в подходящий формат для использования браузерами.
Во-вторых, основная концепция веб-пакета
1. Вход:Указывает, какой модуль веб-пакет должен использовать в качестве отправной точки для построения своего внутреннего графа зависимостей. После входа в точку входа webpack узнает, какие модули и библиотеки (напрямую и косвенно) зависят от точки входа.
2. Выход (экспорт):Сообщает веб-пакету, куда выводить результирующие файлы, которые он создает, и как называть эти файлы, по умолчанию ./dist.
3. Загрузчик (преобразователь модулей):Преобразуйте все типы файлов в действительные модули, которые может обработать webpack, а затем вы сможете воспользоваться возможностями упаковки webpack для их обработки.
4. Плагины:Внедряйте логику расширения в определенные моменты процесса сборки Webpack, чтобы изменить результат сборки или сделать то, что вы хотите.
5. Модуль:Разработчик разбивает программу на отдельные функциональные блоки, называемые модулями.
3. Процесс выполнения веб-пакета
После запуска WebPack модуль, настроенный в записи, начнет повторять все модули, зависящие от записи.Каждый раз, когда вы найдете модуль, вы найдете соответствующие правила преобразования в соответствии с настроенным загрузчиком.После преобразования модуля текущий Модуль является зависимым.Модуль, который будет записью как группа, запись, а все зависимые модули являются чанками.Наконец, WebPack преобразует весь CHUNK в выходной файл, и WebPack будет выполнять логику плагина во всем процессе.
Четыре, WebPack простой упаковочный чехол
【4.1】Подготовка
Создайте новую пустую папку для создания проекта, как показано ниже. Я создал папку с именем webpack_demo на диске D, использовал терминал для входа в папку и использовал команду npm init для инициализации файла package.json.
После ввода этой команды терминал запросит у вас ряд информации, такую как название проекта, описание проекта, автора и т. д., но если вы не планируете публиковать этот модуль, просто нажмите Enter до упора. (Вы также можете использоватьnpm init -y
Эта команда генерирует файл package.json по одному, чтобы терминал не задавал вам вопросов).
[4.2] Установить веб-пакет
Затем введите следующую команду в командной строке для установки веб-пакета.Если вы хотите сделать все за один шаг, сначала установите глобальный веб-пакет и локальный веб-пакет проекта, потому что некоторые модули будут использоваться позже.
npm install webpack --global // 安装全局webpack命令
npm install webpack webpack-cli --save-dev // 安装本地项目模块
// install 可简写为i,
// --global 可简写为-g
// --save 可简写为-S
// --save-dev 可简写为-D
【4.3】Новый файл
Создайте две новые папки в папке webpack_demo, а именно папку src и папку dist, затем добавьте файл index.js и файл hello.js в папку src и добавьте файл index.html в папку dist. На данный момент структура проекта выглядит следующим образом:
Экспорт модуля в hello.js
// hello.js
module.exports = function() {
let hello = document.createElement('div');
hello.innerHTML = "hello xxx!";
return hello;
};
Добавьте этот модуль hello.js в index.js.
// index.js
const hello = require('./hello.js');
document.querySelector("#root").appendChild(hello());
Вставьте упакованный js-файл bundle.js в index.html.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Webpack demo</title>
</head>
<body>
<div id='root'></div>
<script src="bundle.js"></script> <!--这是打包之后的js文件,我们暂时命名为bundle.js-->
</body>
</html>
【4.4】Упаковка
Введите следующую команду в терминале для упаковки
// webpack全局安装的情况下,output后面的是打包后的文件路径,bundle.js为打包后的js文件名
webpack src/index.js --output dist/bundle.js
// --output可简写为-o
// 上述命令相当于把src文件夹下的index.js文件打包到dist文件夹下的bundle.js,这样就生成了打包后的文件供index.html引入
Результат выглядит следующим образом:
Видно, что webpack компилирует index.js и hello.js одновременно, потому что файл index.js представляет модуль hello.js, теперь откройте index.html, чтобы увидеть результат.
Мы успешно использовали упакованный веб-пакет, а затем младший партнер сказал, что каждый раз, когда такая длинная команда ввода в терминале чувствует себя хорошо, Фана, а затем учится использовать файл конфигурации веб-пакета.
[4.5] Используйте файл конфигурации для использования WebPack
Создаем новый файл конфигурации webpack.config.js в корневом каталоге текущего проекта.Записываем следующий простой код конфигурации.На данный момент только входная конфигурация (эквивалентная нашему index.js, с которой начинается упаковка) и выходная конфигурация (эквивалент Мы упаковываем полученный bundle.js).
// webpack.config.js
const path = require('path');
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join( __dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
}
}
// path.join的功能是拼接路径片段
// __dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录,即D:\webpack_demo
С этим файлом конфигурации нам нужно только запустить команду webpack в терминале для упаковки, эта команда будет автоматически ссылаться на параметры конфигурации в файле webpack.config.js.
[4.6] Пользовательские команды скрипта в файле package.json
У Node-проектов обычно есть файл package.json, который используется для описания текущего проекта, который имеет атрибут scripts, который может настраивать команды скрипта, такие как команды упаковки, которые мы запускаем, затем вы можете добавлять пользовательские скрипты в скрипты как:
Затем вы можете использовать npm run build для запуска команды скрипта, в чем преимущество? Если командная строка короткая, то выгода конечно не очевидна, но как командная строка может быть очень длинной? Затем мы можем добавить команды, которые необходимо выполнять каждый раз здесь.После настройки скриптов значение ключа запуска npm эквивалентно запуску значения значения в терминале.
5. Создавайте местные сервисы
В приведенном выше случае мы просматриваем страницу, открывая локальный файл HTML. Все фреймворки vue и react работают на локальном сервере. Можем ли мы изменить его на это? Далее узнайте, как создавать локальные сервисы.
[5.1] webpack-dev-server настраивает локальный сервер
Webpack предоставляет необязательный локальный сервер разработки.Этот локальный сервер построен на node.js.Это отдельный компонент, который необходимо установить отдельно как зависимость проекта перед настройкой его в webpack:
npm install webpack-dev-server -D
[5.2] Элемент конфигурации devServer
- база контента:Этот элемент конфигурации указывает корневой каталог ресурсов сервера.Если contentBase не настроен, то contentBase по умолчанию использует текущий исполняемый каталог, как правило, корневой каталог проекта.
- порт:Указывает номер порта для открытия сервера, по умолчанию 8080.
- хозяин:Настройте адрес прослушивания сервера DevServer, по умолчанию 127.0.0.1.
- заголовки:Этот элемент конфигурации может вставлять некоторые заголовки ответа HTTP в ответ HTTP. Например:
headers: {
'X-foo': '112233'
}
- историяApiFallback:Это свойство элемента конфигурации используется для перенаправления на определенную страницу при возврате страницы 404. Обычно используется в одностраничных приложениях.Например, при доступе к маршруту, когда доступ к маршруту невозможен, через этот элемент конфигурации, когда значение атрибута установлено в true, он автоматически перейдет к index.html. Конечно, мы также можем вручную сопоставить маршрут через обычный
// 跳到index.html页面
historyApiFallback: true
// 使用正则来匹配路由
historyApiFallback: {
rewrites: [
{ from: /^\/user/, to: '/user.html' },
{ from: /^\/home/, to: '/home.html' }
]
}
- горячий:Этот элемент конфигурации относится к функции замены модуля.По умолчанию DevServer автоматически обновляет всю страницу для обеспечения предварительного просмотра в реальном времени после обнаружения обновления исходного кода.Однако после включения функции горячей замены модуля она не обновляет всю страницу В случае предварительного просмотра в реальном времени заменой старых модулей на новые.
- proxy : Иногда, когда мы используем веб-пакет для локального запуска сервера, поскольку мы используем доменное имя http://localhost:8081, но интерфейс нашего сервера другой, мы можем решить проблему междоменного доступа с помощью этой конфигурации.
// 假设服务端接口域名为:http://news.baidu.com
proxy: {
'/api': {
target: 'http://news.baidu.com', // 目标接口的域名
// secure: true, // https 的时候 使用该参数
changeOrigin: true, // 是否跨域
pathRewrite: {
'^/api' : '' // 重写路径
}
}
}
- в линию:Установите значение true, чтобы автоматически обновлять страницу при изменении исходного файла.
- Открыть:Это свойство используется для автоматического использования системного браузера по умолчанию для открытия веб-страниц при запуске DevServer и завершении первой сборки.
- Компресс:Настройте, включать ли сжатие gzip, логический тип, по умолчанию false
- наложение:Это свойство используется для отображения ошибок на странице браузера при возникновении ошибок компиляции. Значение по умолчанию этого свойства — false, при необходимости установите для этого параметра значение true
[5.3] Добавьте элементы конфигурации в webpack.config.js
// webpack.config.js
const path = require('path');
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
proxy: {
'/api': {
target: '',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
[5.4] Добавьте команду запуска в файл package.json
"scripts": {
"build": "webpack",
"dev": "webpack-dev-server --open"
},
Мы используем dev для запуска локального сервера, webpack-dev-server — это команда для запуска сервера, а --opn используется для автоматического открытия браузера после запуска сервера. Вы можете объединить несколько команд для совместной работы, то есть мы определяем имя команды dev для одновременного запуска команд webpack-dev-server и --opn.
Теперь запустите сервер, набрав npm run dev в терминале.
Таким образом, мы можем просмотреть страницу в http://localhost:8088/ (выйдите из сервера, используйте ctrl+c, а затем нажмите y для подтверждения выхода с сервера)
[5.5] Конфигурация отладки исходных карт
Как разработка, отладка кода, конечно, необходима.Тогда возникает проблема.После упакованных файлов вам не так просто найти не то место.Source Map
используется для решения этой проблемы. С помощью следующей конфигурации мы создадим соответствующий файл пакета при упаковке.map
файл, что делает скомпилированный код более читабельным и легким для отладки.
// webpack.config.js
const path = require('path');
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
},
devtool: 'source-map' // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
}
После настройки снова запускаем npm run build для пакета, тогда мы обнаружим, что в папке dist есть лишний bundle.js.map. Если в нашем коде есть ошибка, средство отладки браузера подскажет местонахождение ошибки.Это роль элемента конфигурации devtool: 'source-map'.
6. Погрузчики
Загрузчики являются одной из самых мощных функций веб-пакета.Через различные загрузчики веб-пакет имеет возможность вызывать внешние скрипты или инструменты для обработки файлов в разных форматах, таких как преобразование scss в css и преобразование ES66, ES7 и другого синтаксиса в синтаксис. которые текущий браузер может распознавать, конвертировать JSX в js и многие другие функции. Загрузчики должны быть установлены отдельно и должны быть настроены в элементе конфигурации модулей в webpack.comfig.js.Конфигурация загрузчиков включает следующие аспекты:
- test: регулярное выражение для соответствия расширению файлов, обрабатываемых загрузчиками (обязательно)
- loader: имя загрузчика (обязательно)
- include/exclude: Вручную добавить файлы (папки), которые должны быть обработаны, или заблокировать файлы (папки), которые не нужно обрабатывать (необязательно)
- options: предоставить дополнительные параметры настройки для загрузчиков (необязательно)
[6.1] Настройка css-загрузчика
Если мы хотим загрузить файл css, нам нужно установить style-loader и css-loader.
npm install style-loader css-loader -D
// webpack.config.js
const path = require('path');
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
},
devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
}
}
Создаем новый файл index.css в папке src и задаем стиль тела
/* index.css */
body {
background: gray;
}
Импортируйте его в index.js в папке src.
// index.js
import './index.css' // 导入css
const hello = require('./hello.js');
document.querySelector("#root").appendChild(hello());
Запустите npm run dev, чтобы запустить сервер, и вы обнаружите, что цвет фона страницы стал серым.
[6.2] Настройка sass
npm install sass-loader node-sass -D // 因为sass-loader依赖于node-sass,所以还要安装node-sass
// webpack.config.js
const path = require('path');
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
},
devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
}
}
Seven, Плагины (плагин)
Плагины используются для расширения функциональности Webpack, они действуют на протяжении всего процесса сборки и выполняют соответствующие задачи.
Загрузчики и плагины часто путают, но на самом деле это совершенно разные вещи, так сказать, загрузчики используются для обработки исходных файлов (JSX, Scss, Less..) в процессе сборки упаковки, по одному, плагины Это не напрямую управлять отдельными файлами, это напрямую влияет на весь процесс сборки.
【7.1】Использование плагинов
Чтобы использовать плагин, вам нужно установить его через npm, а затем добавить экземпляр плагина в элемент конфигурации plugins файла конфигурации webpack.config.js Давайте сначала воспользуемся простым плагином заявления об авторских правах.
// webpack.config.js
const path = require('path');
const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
},
devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究') // new一个插件的实例
]
}
После запуска NPM запустите сборку в пакет, мы просматриваем файл bundle.js под dist следующим образом:
[7.2] Автоматически генерировать HTML-файлы (HtmlWebpackPlugin)
До сих пор мы все использовали файл index.html, созданный в начале, а также вручную импортировали bundle.js.Если в будущем мы импортируем более одного файла js и изменим имя файла js, нам придется вручную изменить индекс. html в имени файла js index.html, поэтому можете ли вы автоматически генерировать index.html и автоматически ссылаться на упакованный js? Для решения этой проблемы используется плагин HtmlWebpackPlugin.
Вносим некоторые изменения в структуру проекта:
- удалить всю папку dist
- В папке SRC для создания нового файла шаблона шаблона index.html (пользовательское имя) (это необязательно, потому что если не установить шаблон, плагин HTMLWebpackPlugin будет генерировать HTML-файл по умолчанию, где мы создадим наш модуль разработки более гибким) , следующим образом:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id='root'>
</div>
</body>
</html>
Htmlwebpackplugin плагин установка
npm install html-webpack-plugin -D
Внедрите подключаемый модуль HtmlWebpackPlugin и настройте шаблон, который ссылается на наши настройки, следующим образом:
// webpack.config.js
const path = require('path');
const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入HtmlWebpackPlugin插件
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
},
devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件的实例
new HtmlWebpackPlugin({
template: path.join(__dirname, "/src/index.html")// new一个这个插件的实例,并传入相关的参数
})
]
}
Запустите npm run build для упаковки, и папка dist будет создана автоматически, включая три файла: index.html, bundle.js и bundle.js.map.
Почему папка dist создается автоматически? Поскольку мы определили в элементе конфигурации экспорта вывода, что расположение файла экспорта — это папка dist, а имя файла экспорта — bundle.js, HtmlWebpackPlugin автоматически поможет вам сослаться на файл с именем bundle.js в dist/index.html, Если вы измените имя файла экспорта в файле webpack.config.js, имя файла также будет автоматически изменено в dist/index.html, поэтому его будет удобнее изменить позже?
[7.3] Очистите папку dist (CleanWebpackPlugin)
webpack генерирует файлы и помещает их в папку dist, но webpack не может отследить, какие файлы на самом деле используются в проекте. Вообще рекомендуется чистить папку dist перед каждой сборкой, чтобы генерировались только те файлы, которые используются, в этом случае используется плагин CleanWebpackPlugin.
npm install clean-webpack-plugin -D
// webpack.config.js
const path = require('path');
const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入HtmlWebpackPlugin插件
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入CleanWebpackPlugin插件
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
},
devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件的实例
new HtmlWebpackPlugin({
template: path.join(__dirname, "/src/index.html")// new一个这个插件的实例,并传入相关的参数
}),
new CleanWebpackPlugin(), // 默认删除output中path对应文件
]
}
Теперь каждый раз, когда мы запускаем npm run build, мы обнаружим, что webpack сначала удалит папку dist, а затем создаст новую папку dist.
[7.4] Горячее обновление (HotModuleReplacementPlugin)
HotModuleReplacementPluginЭто очень практичный плагин, который может автоматически обновлять эффект предварительного просмотра после изменения кода.
Метод настройки:
- Добавьте параметр hot: true в элемент конфигурации devServer.
- Поскольку HotModuleReplacementPlugin поставляется с модулем веб-пакета, после введения веб-пакета его можно использовать непосредственно в элементе конфигурации плагинов.
// webpack.config.js
const path = require('path');
const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入HtmlWebpackPlugin插件
const CleanWebpackPlugin = require('clean-webpack-plugin'); // 引入CleanWebpackPlugin插件
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
},
devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件的实例
new HtmlWebpackPlugin({
template: path.join(__dirname, "/src/index.html")// new一个这个插件的实例,并传入相关的参数
}),
new CleanWebpackPlugin(['dist']), // 所要清理的文件夹名称
new webpack.HotModuleReplacementPlugin() // 热更新插件
]
}
После того, как npm run dev запустит проект, мы попытаемся изменить содержимое hello.js и обнаружим, что эффект предварительного просмотра в браузере будет автоматически обновлен.
8. Оптимизация и расширение проекта
[8.1] Разделение кода
В нашем конфигурационном файле webpack.config.js на самом деле так много вещей, которые не нужно настраивать, и если в будущем будут добавлены дополнительные конфигурации, он не будет ослеплять, поэтому лучший способ — разделить его для удобства управления:
1. Мы создаем три новых файла в корневом каталоге, а именно webpack.common.js, webpack.dev.js и webpack.prod.js, которые представляют общедоступные файлы конфигурации, файлы конфигурации среды разработки и производственную среду (ссылаясь на среду) файл конфигурации.
2. Установите плагин модуля слияния:
npm install webpack-merge -D
3. Разделите код webpack.config.js на три вновь созданных файла, а затем удалите файл webpack.config.js следующим образом:
// webpack.common.js
const path = require('path');
const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入HtmlWebpackPlugin插件
module.exports = {
entry: path.join(__dirname, "/src/index.js"), // 入口文件
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "bundle.js" // 打包后输出文件的文件名
},
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ['style-loader', 'css-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件的实例
new HtmlWebpackPlugin({
template: path.join(__dirname, "/src/index.html")// new一个这个插件的实例,并传入相关的参数
}),
new webpack.HotModuleReplacementPlugin() // 热更新插件
]
}
// webpack.dev.js
const path = require('path');
const merge = require('webpack-merge'); // 引入webpack-merge功能模块
const common = require('./webpack.common.js'); // 引入webpack.common.js
module.exports = merge(common, { // 将webpack.common.js合并到当前文件
devServer: {
contentBase: path.join(__dirname, "dist"),
hot: true,
port: '8080',
inline: true,
open: true,
overlay: true,
},
})
// webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入CleanWebpackPlugin插件
module.exports = merge(common, { // 将webpack.common.js合并到当前文件
devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
plugins: [
new CleanWebpackPlugin(),
]
})
4. Установите команду сценариев package.json
"scripts": {
"build": "webpack --config webpack.prod.js",
"dev": "webpack-dev-server --open --config webpack.dev.js"
},
Мы изменили команду сборки на webpack --config webpack.prod.js, что означает указывать конфигурацию упаковки на файл конфигурации webpack.prod.js Почему нам нужно было использовать только команду webpack перед ее запуском? Поскольку команда webpack по умолчанию указывает на имя файла webpack.config.js, теперь мы изменили имя файла, поэтому нам нужно настроить его так, чтобы оно указывало на новый файл, а инструкции в команде dev остались прежними.
Затем мы запускаем npm run build и npm run dev, и эффект должен быть таким же, как до того, как мы разделили код.
【8.2】Несколько входов и несколько выходов
Пока у нас есть один входной файл и один выходной файл, что, если у меня будет более одного входного файла? Давай попробуем:
Есть три способа записи записи в webpack.common.js, а именно строки, массивы и объекты.Обычно мы больше используем объекты, поэтому меняем на способ записи объектов.Во-первых, мы находимся в папке src.Создать новый файл index2.js с любым именем. Поскольку существует несколько записей, должно быть несколько выходов для взаимно однозначной корреспонденции, поэтому конфигурации входа и выхода следующие:
entry: {
index: path.join(__dirname, "/src/index.js"),
index2: path.join(__dirname, "/src/index2.js")
},
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "[name].js" // 打包后输出文件的文件名
},
// index2.js
function page2() {
let element = document.createElement('div');
element.innerHTML = '我是第二个入口文件';
return element;
}
document.getElementById('root').appendChild(page2());
Затем мы запускаем npm run build to package и обнаруживаем, что в папке dist будет больше файлов index2.js, а index.html также автоматически импортирует index2.js, а затем запускаем npm run dev, чтобы отобразить следующее:
【8.3】Отдельный CSS
Идея webpack заключается в том, чтобы упаковать CSS и JS в один файл, но что, если мы хотим разделить CSS?
npm install extract-text-webpack-plugin@next -D // 加上@next是为了安装最新的,否则会出错
После установки вышеуказанных плагинов импортируйте и используйте плагин в файле webpack.common.js:
// webpack.common.js
const path = require('path');
const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入HtmlWebpackPlugin插件
const ExtractTextPlugin = require('extract-text-webpack-plugin') //引入分离插件
module.exports = {
entry: {
index: path.join(__dirname, "/src/index.js"),
index2: path.join(__dirname, "/src/index2.js")
},
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "[name].js" // 打包后输出文件的文件名
},
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ExtractTextPlugin.extract({ // 这里我们需要调用分离插件内的extract方法
fallback: 'style-loader', // 相当于回滚,经css-loader处理过的css最终再经过style-loader处理
use: ['css-loader']
})
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
}
]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件的实例
new HtmlWebpackPlugin({
template: path.join(__dirname, "/src/index.html")// new一个这个插件的实例,并传入相关的参数
}),
new webpack.HotModuleReplacementPlugin(), // 热更新插件
new ExtractTextPlugin('css/index.css') // 将css分离到/dist文件夹下的css文件夹中的index.css
]
}
После запуска сборки npm run вы найдете еще один файл css в папке dist.
[8.4] Удалите избыточный CSS
Иногда мы пишем много CSS, и мы можем неосознанно писать и повторять некоторые стили, что приводит к избыточному коду, который мы забываем проверить перед выходом в интернет.В этом аспекте мы должны постараться оптимизировать его, и у веб-пакета есть это Функция.
npm install purifycss-webpack purify-css glob -D
После установки настройте его в файле webpack.prod.js, введите плагины purifycss-webpack и glob и используйте их.
// webpack.prod.js
const path = require('path');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入CleanWebpackPlugin插件
const PurifyCssWebpack = require('purifycss-webpack'); // 引入PurifyCssWebpack插件
const glob = require('glob'); // 引入glob模块,用于扫描全部html文件中所引用的css
module.exports = merge(common, { // 将webpack.common.js合并到当前文件
devtool: 'source-map', // 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
plugins: [
new CleanWebpackPlugin(),
new PurifyCssWebpack({
paths: glob.sync(path.join(__dirname, 'src/*.html')) // 同步扫描所有html文件中所引用的css
})
]
})
Давайте попробуем добавить дополнительный код в файл index.css:
/* index.css */
body {
background: gray;
}
/* 冗余css */
.a {
color: black;
font-size: 14px;
background: red;
}
/* 冗余css */
.b {
height: 50px;
line-height: 50px;
border: none;
}
Затем запускаем npm run build и обнаруживаем, что в упакованном index.css нет лишнего.a
а также.b
Коды:
【8.5】Обработка изображений
Если мы хотим использовать изображения, мы должны установить два погрузчика
// 虽然我们只需使用url-loader,但url-loader是依赖于file-loader的,所以也要安装
npm install url-loader file-loader -D
Затем настройте загрузчик URL в webpack.common.js.
// webpack.common.js
const path = require('path');
const webpack = require('webpack'); // 这个插件不需要安装,是基于webpack的,需要引入webpack模块
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入HtmlWebpackPlugin插件
const ExtractTextPlugin = require('extract-text-webpack-plugin') //引入分离插件
module.exports = {
entry: {
index: path.join(__dirname, "/src/index.js"),
index2: path.join(__dirname, "/src/index2.js")
},
output: {
path: path.join(__dirname, "/dist"), // 打包后的文件存放的地方
filename: "[name].js" // 打包后输出文件的文件名
},
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ExtractTextPlugin.extract({ // 这里我们需要调用分离插件内的extract方法
fallback: 'style-loader', // 相当于回滚,经css-loader处理过的css最终再经过style-loader处理
use: ['css-loader']
})
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.(png|jpg|svg|gif)$/, // 正则匹配图片格式名
use: [
{ loader: 'url-loader' // 使用url-loader }
]
},
]
},
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'), // new一个插件的实例
new HtmlWebpackPlugin({
template: path.join(__dirname, "/src/index.html")// new一个这个插件的实例,并传入相关的参数
}),
new webpack.HotModuleReplacementPlugin(), // 热更新插件
new ExtractTextPlugin('css/index.css') // 将css分离到/dist文件夹下的css文件夹中的index.css
]
}
Мы изменили фон index.css на картинку
/* index.css */
body {
background: url('./images/bg.jpg') no-repeat;
background-size: 200px 250px;
color: #fff;
}
После запуска npm run dev он показывает следующее:
Мы обнаружим, что фоновое изображение стало base64, потому что веб-пакет будет автоматически оптимизировать изображение и отправлять меньше запросов, но что, если я захочу превратить его в путь?
Мы можем изменить конфигурацию загрузчика webpack.common.js и добавить параметры:
module: {
rules: [
{
test: /\.css$/, // 正则匹配以.css结尾的文件
use: ExtractTextPlugin.extract({ // 这里我们需要调用分离插件内的extract方法
fallback: 'style-loader', // 相当于回滚,经css-loader处理过的css最终再经过style-loader处理
use: ['css-loader'],
publicPath: '../' // 给背景图片设置一个公共路径
})
},
{
test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件
use: ['style-loader', 'css-loader', 'sass-loader'], // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的
},
{
test: /\.(png|jpg|svg|gif)$/, // 正则匹配图片格式名
use: [
{
loader: 'url-loader', // 使用url-loader
options: {
limit: 1000, // 限制只有小于1kb的图片才转为base64,例子图片为1.47kb,所以不会被转化
outputPath: 'images', // 设置打包后图片存放的文件夹名称
},
}
]
},
]
},
【8.6】Код сжатия
В версии webpack4.x js будет автоматически сжиматься при упаковке, а когда npm run dev запускает сервер, при изменении кода горячее обновление выполняется очень медленно, это связано с тем, что webpack автоматически упаковывает его для вас после того, как вы изменить его.В результате эффективность в среде разработки очень низкая, поэтому нам нужно отличать среду разработки от рабочей среды, что отражает удобство нашего разделения кода.webpack.dev.js представляет собой конфигурацию среды разработки среда, webpack.dev.js представляет собой конфигурацию среды разработки, а webpack.prod.js представляет собой конфигурацию производственной среды.На данный момент нам нужно только настроить команду соответствующей среды в файле package.json :
"scripts": {
"build": "webpack --config webpack.prod.js --mode production",
"dev": "webpack-dev-server --open --config webpack.dev.js --mode development"
},
--mode production означает, что это производственная среда при упаковке, и js будет сжат сам по себе, а --mode development означает, что в настоящее время это среда разработки и ее не нужно сжимать. Это также решает проблему предупреждения, которая осталась в прошлом.
После запуска npm run dev я обнаружил, что скорость намного лучше, хи-хи!
Статья постоянно обновляется каждую неделю, вы можете искать в WeChat "Особенности интерфейса"Прочтите это в первый раз, ответьте [видео】【книги】 Получите 200 ГБ видеоматериалов и 30 книг в формате PDF.