Статья впервые опубликована на:GitHub.com/US TB-Вуд, умри, о ты…
написать впереди
Webpack, возможно, является самой популярной библиотекой пакетов на данный момент.Когда webpack обрабатывает приложение, он рекурсивно строит граф зависимостей, который содержит все модули, необходимые приложению, а затем объединяет все эти модули в один или несколько пакетов. В этом посте будет представлена очень важная часть веб-пакета — оптимизация производительности. Код статьи здесь:GitHub.com/US TB-Вуд, умри, о ты…
Эта статья будет заключаться из следующих разделов:
- noParse
- ignorePlugin
- dllPlugin
- happypack
- Tree-Shaking
- Извлечь общедоступный код
- ленивая загрузка
- Горячее обновление
noParse
- Элемент конфигурации noParse позволяет Webpack игнорировать рекурсивный синтаксический анализ и обработку некоторых файлов, которые не являются модульными, что повышает производительность сборки. Причина в том, что некоторые библиотеки, такие как jQuery и ChartJS, огромны и не принимают модульных стандартов, а Webpack отнимает много времени и не имеет смысла анализировать эти файлы.
Включить noParse:
module: {
// 不去解析jquery的依赖关系
noParse: /jquery/
},
ignorePlugin
- момент 2.18 упакует все локализации с основной функциональностью). Вы можете использовать IgnorePlugin для игнорирования локализованного контента при упаковке.После экспериментов, после использования ignorePlugin 📦 Объем уменьшен с 1.2M до 800K
Метод включения ignorePlugin:
// 用法:
new webpack.IgnorePlugin(requestRegExp, [contextRegExp]);
//eg.
plugins: [new webpack.IgnorePlugin(/\.\/local/, /moment/)];
DllPlugin
- DllPlugin создан на основе идеи библиотеки динамической компоновки (dll) Windows. Этот плагин упакует стороннюю библиотеку в один файл, который является чистой библиотекой зависимостей. Эта библиотека зависимостей не будет перепакована вместе с вашим бизнес-кодом, она будет перепакована только при изменении версии самой зависимости.
Обработка файлов с dllplugin - это двухэтапный процесс:
- На основе файла конфигурации, специфичного для dll, упакуйте библиотеку dll.
let path = require("path");
let webpack = require("webpack");
module.exports = {
mode: "development",
entry: {
react: ["react", "react-dom"]
},
output: {
filename: "_dll_[name].js", // 产生的文件名
path: path.resolve(__dirname, "dist"),
library: "_dll_[name]"
},
plugins: [
// name要等于library里的name
new webpack.DllPlugin({
name: "_dll_[name]",
path: path.resolve(__dirname, "dist", "manifest.json")
})
]
};
- На основе файла webpack.config.js бизнес-код пакета
let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin");
let webpack = require("webpack");
module.exports = {
mode: "development",
// 多入口
entry: {
home: "./src/index.js"
},
devServer: {
port: 3000,
open: true,
contentBase: "./dist"
},
module: {
// 不去解析jquery的依赖关系
noParse: /jquery/,
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.js$/,
exclude: /node_modules/,
include: path.resolve("src"),
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"]
}
}
}
]
},
output: {
// name -> home a
filename: "[name].js",
path: path.resolve(__dirname, "dist")
},
plugins: [
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, "dist", "manifest.json")
}),
new webpack.IgnorePlugin(/\.\/local/, /moment/),
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html"
}),
new webpack.DefinePlugin({
DEV: JSON.stringify("production")
})
]
};
Happypack - конвертировать загрузчик из одного процесса в многопроцессный
- Как мы все знаем, веб-пакет является однопоточным, и даже если в данный момент есть несколько задач, вы можете встать в очередь на обработку только одну за другой. Это недостаток веб-пакета. К счастью, наш ЦП является многоядерным. Happypack полностью реализует преимущества ЦП в многоядерном параллелизме, поможет нам разложить задачи на несколько подпроцессов для одновременного выполнения и значительно повысит эффективность упаковки.
Как использовать счастливый пакет:
Просто перенесите конфигурацию в загрузчике на happypack:
let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin");
let webpack = require("webpack");
// 模块 happypack 可以实现多线程📦
let Happypack = require("happypack");
module.exports = {
mode: "development",
// 多入口
entry: {
home: "./src/index.js"
},
devServer: {
port: 3000,
open: true,
contentBase: "./dist"
},
module: {
// 不去解析jquery的依赖关系
noParse: /jquery/,
rules: [
{
test: /\.css$/,
use: "Happypack/loader?id=css"
},
{
test: /\.js$/,
exclude: /node_modules/,
include: path.resolve("src"),
use: "Happypack/loader?id=js"
}
]
},
output: {
// name -> home a
filename: "[name].js",
path: path.resolve(__dirname, "dist")
},
plugins: [
new Happypack({
id: "css",
use: ["style-loader", "css-loader"]
}),
new Happypack({
id: "js",
use: [
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"]
}
}
]
}),
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, "dist", "manifest.json")
}),
new webpack.IgnorePlugin(/\.\/local/, /moment/),
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html"
}),
new webpack.DefinePlugin({
DEV: JSON.stringify("production")
})
]
};
Tree-Shaking
- Основываясь на синтаксисе импорта/экспорта, Tree-Shaking может узнать, какие модули на самом деле не используются в процессе компиляции, и эти бесполезные коды будут удалены, когда они будут окончательно упакованы. Он подходит для обработки кода на уровне модуля, поэтому попробуйте использовать синтаксис импорта/экспорта es6.
Извлечь общедоступный код
Преимущества абстрагирования общего кода:
- Уменьшить сетевой трафик и затраты на сервер;
- Хотя скорость открытия пользователем веб-сайта в первый раз не оптимизирована, скорость посещения других страниц после этого значительно улучшится.
Включить код извлечения:
// webpack 4.x版本之前的commonChunkPlugins
optimization: {
// 分割代码块
splitChunks: {
// 缓存组
cacheGroups: {
// 公共模块
common: {
chunks: "initial",
minSize: 0,
// 最小公用模块次数
minChunks: 2
},
vendor: {
priority: 1,
// 抽离出来
test: /node_modules/,
chunks: "initial",
minSize: 0,
minChunks: 2
}
}
}
}
нагрузка по требованию
Мышление по запросу
- Не все одновременно загрузить содержимое файла, только эта часть нагрузки на данный момент необходимо использовать (сделать разделение заранее)
- Мгновенно загружайте то, что используется, когда требуется больше контента
Загрузка по запросу реализована через импорт es6.После использования import() для разделения кода ваш браузер должен поддерживать Promise API, чтобы код работал правильно, потому что import() возвращает Promise, который зависит от Promise. Для браузеров, которые изначально не поддерживают промисы, вы можете внедрить полифилл промисов.
let button = document.createElement("button");
button.innerHTML = "musion";
// vue,react的懒加载原理也是如此
button.addEventListener("click", function() {
// es6草案中的语法, jsonp实现动态加载文件
import("./source.js").then(data => {
console.log(data.default);
});
console.log("click");
});
document.body.appendChild(button);
Горячее обновление
Горячая замена модуля (HMR) — одна из самых полезных функций, предоставляемых webpack. Это позволяет заменять, добавлять, удалять различные модули во время выполнения без необходимости полного обновления для перезагрузки всей страницы.Основные идеи заключаются в следующем:
- Сохранить состояние приложения, потерянного при полной перезагрузке страницы
- Обновляйте только измененный контент, чтобы сэкономить время разработки
- Настройка стилей выполняется быстрее, почти эквивалентно изменению стилей прямо в отладчике браузера.
Включить УЧР
- Представлена библиотека webpack
- используется новый webpack.HotModuleReplacementPlugin()
- Установите для горячего поля в опции devServer значение true
let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin");
let webpack = require("webpack");
module.exports = {
mode: "production",
// 多入口
entry: {
index: "./src/index.js",
other: "./src/other.js"
},
devServer: {
// 启用热更新
hot: true,
port: 3000,
open: true,
contentBase: "./dist"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
include: path.resolve("src"),
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: ["@babel/plugin-syntax-dynamic-import"]
}
}
}
]
},
output: {
// name -> home a
filename: "[name].js",
path: path.resolve(__dirname, "dist")
},
plugins: [
new webpack.NamedModulesPlugin(), // 打印更新的模块路径
new webpack.HotModuleReplacementPlugin() // 热更新插件
]
};
Справочная статья
Как Webpack реализует горячие обновления?
Принцип и практика оптимизации производительности интерфейса
Можете обратить внимание на мой паблик-аккаунт «Muchen Classmate», фермера на гусиной фабрике, который обычно записывает какие-то банальные мелочи, технологии, жизнь, инсайты и срастается.