В этой статье я бы хотел поделиться своим опытом по разбиению бандлов для многостраничного сайта с помощью Webpack 4. Cначала создадим для каждой страницы свою точку входа. Рассмотрим на примере 4 страниц:
const path = require("path");
const PATHS = {
src: path.resolve(process.cwd(), "src"),
dist: path.resolve(process.cwd(), "dist")
};
module.exports = {
entry: {
common: `${PATHS.src}/js/common`,
index: `${PATHS.src}/js/index`,
contacts: `${PATHS.src}/js/contacts`,
about: `${PATHS.src}/js/about`,
}
}
При сборке для каждой страницы будет создан свой бандл. В точку входа common
я вынес общие скрипты для всех страниц. Чтобы подключить наши бандлы на страницы воспользуемся плагином Webpack'a HtmlWebpackPlugin.
Рассмотрим на примере:
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
filename: `${PATHS.dist}/index.html`,
template: `${PATHS.dist}/index.html`,
chunks: ["index", "common"]
})
...
]
...
};
В chunks
указываем бандлы, необходимые для этой страницы (очередность: справа на лево). Таким образом на страницу будет подключены сначала общие скрипты, а потом скрипты необходимые отдельно для этой страницы.
Если мы имеем общие модули/сторонние библиотеки подключенные на разных страницах, создадим общие бандлы для этих страниц.
Воспользуемся Webpack плагином SplitChunksPlugin. Собственно вот конфигурация:
module.exports = {
optimization: {
splitChunks: {
chunks: "all",
minSize: 1,
minChunks: 2
}
}
}
После сборки мы получим бандлы отдельно для каждой странички и бандлы, которые делят между собой наши страницы.
index.js
contacts.js
common.js
about.js
vendors~about-us~index.js
vendors~about-us~contacts.js
В бандл vendors~about-us~index.js буду вынесены общие скрипты для about-us
и index
, которые закешируються браузером, и при переходе со страницы index
на about
будут уже скачены браузером, и потребуеться только загрузить бандл about.js
.
Имена чанков можно изменить в конфиге этого плагина.
Чтобы подключить эти бандлы правильно на каждую нашу странцу воспользуемся HtmlWebpackPlugin. Конфигурация та же что и в начале статьи. Только вот вам прийдеться поставить альфа версию этого плагина, потому что на момент написания статьи этот плагин не подключал наши разделенные чанки, а подключал только точки входа.
npm i --save-dev html-webpack-plugin@next
После сборки мы получим вот такой код в index.html:
<script src="js/common.js"></script>
<script src="js/vendors~about-us~index.js"></script>
<script src="js/index.js"></script>
Комментарии (4)
Enverest
21.02.2019 10:11Тоже так использую. И мне не понятно почему нельзя просто прописать entry как параметр для HtmlWebpackPlugin. Имена chunks могут меняться например при добавления нового entry, его имя будет дописывать к существующим chunks. А если бы использовался entry — мне, как пользователю плагина, не пришлось бы менять существующий код.
Enverest
21.02.2019 10:23И HtmlWebpackPlugin stable версии работает с чанками, просто Webpack сломал обратную совместимость на минорной версии (4.6.1). Если поставить Webpack 4.6.0 и html-webpack-plugin 3.2.0, то текущий webpack конфиг так же будет работать.
noodles
Есть ли какой-то профит по сравнению с такой схемой:
в index.js каждой страницы (например домашней) подключаем
Один бандл, один запрос. Чуть больше объём, но без танцев с вебпаком.
Machinez
Да есть
При таком подходе, если у тебя изменится содержимое бандла, то пользователю придется перекачивать его полностью заново на замену закэшированному.
Обычно vendors выносят в отдельный бандл, т.к он крайне редко меняется, в отличии от кода самого приложения.