Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
env:
browser: true
node: true
es6: true
extends: 'eslint:recommended'
globals:
Atomics: readonly
SharedArrayBuffer: readonly
parserOptions:
ecmaFeatures:
jsx: true
ecmaVersion: 2018
sourceType: module
plugins:
- react
rules: {}
10 changes: 10 additions & 0 deletions .github/workflows/sitespeedio.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: sitespeedio
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- name: run sitespeed.io
run: docker run -v "$(pwd):/sitespeed.io" sitespeedio/sitespeed.io:latest https://18ee-95-91-241-147.ngrok-free.app/ -n 1 --budget.configPath ./homeBudget.json
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.6.3
2.7.7
6 changes: 3 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# rubocop:disable LineLength
source "https://rubygems.org"
ruby "2.6.3"
ruby "2.7.7"

# Enforce git to transmitted via https.
# workaround until bundler 2.0 is released.
Expand All @@ -16,7 +16,7 @@ end
gem "actionpack-action_caching", "~> 1.2"
gem "active_record_union", "~> 1.3"
gem "acts-as-taggable-on", "~> 5.0"
gem "acts_as_follower"
gem "acts_as_follower", github: "forem/acts_as_follower", branch: "master"
gem "addressable", "~> 2.5", ">= 2.5.2"
gem "administrate", "~> 0.11"
gem "ahoy_email", "~> 0.5"
Expand Down Expand Up @@ -122,7 +122,7 @@ group :development, :test do
gem "derailed", "~> 0.1"
gem "erb_lint", "~> 0.0", require: false
gem "faker", git: "https://github.com/stympy/faker.git", branch: "master"
gem "fix-db-schema-conflicts"
gem "fix-db-schema-conflicts", github: "jakeonrails/fix-db-schema-conflicts", branch: "master"
gem "memory_profiler", "~> 0.9"
gem "parallel_tests", "~> 2.27"
gem "pry-byebug", "~> 3.7"
Expand Down
29 changes: 21 additions & 8 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
GIT
remote: https://github.com/forem/acts_as_follower.git
revision: 06393d3693a1a3d4b390aec4976c8b8f3a81cf01
branch: master
specs:
acts_as_follower (0.2.1)
activerecord (>= 4.0)

GIT
remote: https://github.com/jakeonrails/fix-db-schema-conflicts.git
revision: ae9135e0bb1fb142dd483f883da0064b8be17732
branch: master
specs:
fix-db-schema-conflicts (3.1.1)
rubocop (>= 0.38.0)

GIT
remote: https://github.com/stympy/faker.git
revision: 9910aa58d92c018abab25d491191576fcc1a7707
Expand Down Expand Up @@ -58,7 +74,6 @@ GEM
tzinfo (~> 1.1)
acts-as-taggable-on (5.0.0)
activerecord (>= 4.2.8)
acts_as_follower (0.2.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
administrate (0.11.0)
Expand Down Expand Up @@ -302,13 +317,11 @@ GEM
faraday_middleware (>= 0.9)
loofah (>= 2.0)
sax-machine (>= 1.0)
ffi (1.9.25)
ffi (1.16.3)
figaro (1.1.1)
thor (~> 0.14)
fission (0.5.0)
CFPropertyList (~> 2.2)
fix-db-schema-conflicts (3.1.0)
rubocop (>= 0.38.0)
fog (1.41.0)
fog-aliyun (>= 0.1.0)
fog-atmos
Expand Down Expand Up @@ -600,7 +613,7 @@ GEM
connection_pool (~> 2.2)
netrc (0.11.0)
nio4r (2.3.1)
nokogiri (1.10.1)
nokogiri (1.10.2)
mini_portile2 (~> 2.4.0)
notiffany (0.1.1)
nenv (~> 0.1)
Expand Down Expand Up @@ -935,7 +948,7 @@ DEPENDENCIES
actionpack-action_caching (~> 1.2)
active_record_union (~> 1.3)
acts-as-taggable-on (~> 5.0)
acts_as_follower
acts_as_follower!
addressable (~> 2.5, >= 2.5.2)
administrate (~> 0.11)
ahoy_email (~> 0.5)
Expand Down Expand Up @@ -979,7 +992,7 @@ DEPENDENCIES
fastly-rails (~> 0.8)
feedjira (~> 2.2)
figaro (~> 1.1)
fix-db-schema-conflicts
fix-db-schema-conflicts!
fog (~> 1.41)
front_matter_parser (~> 0.2)
gemoji (~> 3.0.0)
Expand Down Expand Up @@ -1069,7 +1082,7 @@ DEPENDENCIES
zonebie (~> 0.6.1)

RUBY VERSION
ruby 2.6.3p62
ruby 2.7.7p221

BUNDLED WITH
1.17.3
24 changes: 24 additions & 0 deletions case-study.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Case-study оптимизации

## Cleanup

Отправной точкой работы над проектом стало задание бюджета на размер сборки JavaScript файлов для главной страницы сайта.
Установка дополнительного плагина `webpack-bundle-analyzer` позволила обнаружить нерациональное использование библиотеки Moment.js, а именно ее загрузки на каждой странице.

В первую очередь были сделаны два скриншота текущего состояния бандла до внесения изменений и после первого подхода, состоящего во временном отключении содержимого файла `proCharts.js` (графики, создаваемые с помощью `Chart.js` часто используют операции с датами и временем для построения координат, т.е. напрямую связаны с `Moment.js`, что так же отражено в зависимостях в файле `yarn.lock` между этими двумя библиотеками):

- `sitespeed-result/Bundle_before_changes.png`
- `sitespeed-result/Bundle_without_Moment.png`

Следующим шагом стало исследование проекта на предмет выявления места, где библиотека `Moment.js` (как зависимость для `Chart.js`) должна по задумке использоваться, чтобы загружать ее только там.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍👍


- `app/views/dashboards/pro.html.erb` шаблон использует файл `proCharts`: `<%= javascript_pack_tag "proCharts", defer: true %>`, который мы для проверки гипотезы закомментировали ранее.
- этот шаблон используется `app/controllers/dashboards_controller.rb` для пользователей с ролью `pro` (авторы статей и блогеры) и вызывается переходом по адресу `get "/dashboard/pro" => "dashboards#pro`
- в файле `config/webpack/environment.js` уже используется плагин для Webpack `CommonsChunkPlugin`, который, следуя документации https://webpack.js.org/plugins/commons-chunk-plugin/#passing-the-minchunks-property-a-function, позволяет настроить условие для включения библиотек в бандл `vendor.js`
- добавляем условия исключения Moment и Chart из этой функции настройки плагина и в результате уменьшаем размер бандла: `sitespeed-result/Bundle_after_repack.png`

Бюджет немного пришлось увеличить с 460000 до 468000, чтобы тест sitespeed.io стал выполняться. Очевидно, это связано с добавлением нескольких зависемостей в сборке (см `yarn.lock`)

## Настройка CI

Теперь настроим `CI` `Github Actions` для защиты от регрессии: файл `.github/workflows/sitespeedio.yml` использует сервис `ngrok` и создает публичный адрес для туннеля на локальный компьютер для тестирования укладывания в бюджет по размеру сборки.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

11 changes: 11 additions & 0 deletions config/webpack/development.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
const environment = require('./environment');

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
.BundleAnalyzerPlugin;
environment.plugins.append(
'BundleAnalyzer',
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: true,
}),
);

const config = environment.toWebpackConfig();

// For more information, see https://webpack.js.org/configuration/devtool/#devtool
Expand Down
29 changes: 17 additions & 12 deletions config/webpack/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,32 @@

// module.exports = environment;


const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
const { environment } = require('@rails/webpacker');
const webpack = require('webpack');

environment.plugins.append(
'CommonsChunkVendor',
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: (module) => {
minChunks: module => {
// this assumes your vendor imports exist in the node_modules directory
return module.context && module.context.indexOf('node_modules') !== -1
}
})
)
// exclude chart.js from vendor chunk
return (
module.context &&
module.context.indexOf('node_modules') !== -1 &&
module.context.indexOf('chart.js') === -1 &&
module.context.indexOf('moment') === -1
);
},
}),
);

environment.plugins.append(
'CommonsChunkManifest',
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
})
)
minChunks: Infinity,
}),
);

module.exports = environment
module.exports = environment;
7 changes: 7 additions & 0 deletions homeBudget.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"budget": {
"transferSize": {
"javascript": 468000
}
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"preact-render-spy": "^1.3.0",
"preact-render-to-json": "^3.6.6",
"prettier": "^1.16.4",
"webpack-bundle-analyzer": "^4.10.1",
"webpack-dev-server": "^2.11.3"
},
"dependencies": {
Expand Down
Binary file added sitespeed-result/Bundle_after_repack.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sitespeed-result/Bundle_before_changes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added sitespeed-result/Bundle_without_Moment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading