Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
js: splitted into bundles and chunks
Browse files Browse the repository at this point in the history
Initially we had one single entrypoint that generated one large output
file.

The idea of this patch was to split unecessary code into different
entrypoints (authenticated and unauthenticated) and split vendors files
into a different chunk.

Now it produces smaller bundles and chunks that will be downloaded
asynchronously and increase the speed up of pages the first time.

Also removed unused and uncessary code from lifeitup vendor file.

Signed-off-by: Vítor Avelino <[email protected]>
  • Loading branch information
Vítor Avelino committed Aug 3, 2018
1 parent 004cd69 commit 82199e9
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 234 deletions.
49 changes: 46 additions & 3 deletions app/assets/javascripts/bootstrap.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,47 @@
jQuery(function ($) {
$('a[rel~=popover], .has-popover').popover();
$('a[rel~=tooltip], .has-tooltip').tooltip();
import Vue from 'vue';

import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';

import Alert from './shared/components/alert';

import { setTimeOutAlertDelay, refreshFloatAlertPosition } from './utils/effects';

dayjs.extend(relativeTime);

$(function () {
if ($.fn.popover) {
$('a[rel~=popover], .has-popover').popover();
}

if ($.fn.tooltip) {
$('a[rel~=tooltip], .has-tooltip').tooltip();
}

// process scheduled alerts
Alert.$process();

refreshFloatAlertPosition();

// disable effects during tests
$.fx.off = $('body').data('disable-effects');
});

// necessary to be compatible with the js rendered
// on the server-side via jquery-ujs
window.setTimeOutAlertDelay = setTimeOutAlertDelay;
window.refreshFloatAlertPosition = refreshFloatAlertPosition;

// we are not a SPA and when user clicks on back/forward
// we want the page to be fully reloaded to take advantage of
// the url query params state
window.onpopstate = function (e) {
// phantomjs seems to trigger an oppopstate event
// when visiting pages, e.state is always null and
// in our component we set an empty string
if (e.state !== null) {
window.location.reload();
}
};

Vue.config.productionTip = process.env.NODE_ENV !== 'production';
30 changes: 3 additions & 27 deletions app/assets/javascripts/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,17 @@ import 'bootstrap/js/collapse';
// Life it up
import 'vendor/lifeitup_layout';

import './bootstrap';
import './vue-shared';
// misc
import './plugins';
import './polyfill';

// modules
import './modules/admin/registries';
import './modules/users';
import './modules/dashboard';
import './modules/explore';
import './modules/repositories';
import './modules/namespaces';
import './modules/teams';
import './modules/webhooks';

import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';

import Alert from './shared/components/alert';

import { setTimeOutAlertDelay, refreshFloatAlertPosition } from './utils/effects';

dayjs.extend(relativeTime);

// Actions to be done to initialize any page.
$(function () {
// process scheduled alerts
Alert.$process();

refreshFloatAlertPosition();

// disable effects during tests
$.fx.off = $('body').data('disable-effects');

// necessary to be compatible with the js rendered
// on the server-side via jquery-ujs
window.setTimeOutAlertDelay = setTimeOutAlertDelay;
window.refreshFloatAlertPosition = refreshFloatAlertPosition;
});
import './bootstrap';
14 changes: 0 additions & 14 deletions app/assets/javascripts/modules/users/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,14 @@ import AppTokensWrapper from './components/application-tokens/wrapper';

import UsersIndexPage from './pages/index';
import UsersEditPage from './pages/edit';
import UsersSignUpPage from './pages/sign-up';
import UsersSignInPage from './pages/sign-in';

const USERS_SELF_EDIT_ROUTE = 'auth/registrations/edit';
const USERS_SIGN_IN_ROUTE = 'auth/sessions/new';
const USERS_SIGN_UP_ROUTE = 'auth/registrations/new';

$(() => {
const $body = $('body');
const route = $body.data('route');
const controller = $body.data('controller');

if (route === USERS_SIGN_UP_ROUTE) {
// eslint-disable-next-line
new UsersSignUpPage($body);
}

if (route === USERS_SIGN_IN_ROUTE) {
// eslint-disable-next-line
new UsersSignInPage($body);
}

if (controller === 'admin/users' || route === USERS_SELF_EDIT_ROUTE) {
// eslint-disable-next-line no-new
new Vue({
Expand Down
20 changes: 20 additions & 0 deletions app/assets/javascripts/modules/users/unauthenticated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import UsersSignUpPage from './pages/sign-up';
import UsersSignInPage from './pages/sign-in';

const USERS_SIGN_IN_ROUTE = 'auth/sessions/new';
const USERS_SIGN_UP_ROUTE = 'auth/registrations/new';

$(() => {
const $body = $('body');
const route = $body.data('route');

if (route === USERS_SIGN_UP_ROUTE) {
// eslint-disable-next-line
new UsersSignUpPage($body);
}

if (route === USERS_SIGN_IN_ROUTE) {
// eslint-disable-next-line
new UsersSignInPage($body);
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,3 @@ Vue.http.interceptors.push((request) => {
request.headers.set('X-CSRF-Token', token);
}
});

// we are not a SPA and when user clicks on back/forward
// we want the page to be fully reloaded to take advantage of
// the url query params state
window.onpopstate = function (e) {
// phantomjs seems to trigger an oppopstate event
// when visiting pages, e.state is always null and
// in our component we set an empty string
if (e.state !== null) {
window.location.reload();
}
};

Vue.config.productionTip = process.env.NODE_ENV !== 'production';
12 changes: 12 additions & 0 deletions app/assets/javascripts/unauthenticated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

// Bootstrap
import 'bootstrap/js/tooltip';

// misc
import './polyfill';

// modules
import './modules/explore';
import './modules/users/unauthenticated';

import './bootstrap';
4 changes: 3 additions & 1 deletion app/views/layouts/application.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ html
meta content="#205683" name="theme-color"

= render "shared/config"
= javascript_include_tag(*webpack_asset_paths("application"))
= javascript_include_tag(*webpack_asset_paths("vendors~application~unauthenticated"), defer: true)
= javascript_include_tag(*webpack_asset_paths("vendors~application"), defer: true)
= javascript_include_tag(*webpack_asset_paths("application"), defer: true)
= yield :js_header

body data-controller="#{js_controller}" data-route="#{js_route}" class="#{'is-admin' if current_user.admin?}" data-disable-effects="#{Rails.env.test?}"
Expand Down
3 changes: 2 additions & 1 deletion app/views/layouts/authentication.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ html
meta content="/favicon/browserconfig.xml" name="msapplication-config"
meta content="#205683" name="theme-color"

= javascript_include_tag(*webpack_asset_paths("application"))
= javascript_include_tag(*webpack_asset_paths("vendors~application~unauthenticated"), defer: true)
= javascript_include_tag(*webpack_asset_paths("unauthenticated"), defer: true)
= yield :js_header

body.login data-controller="#{js_controller}" data-route="#{js_route}"
Expand Down
102 changes: 58 additions & 44 deletions config/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,45 +27,16 @@ var config = {

entry: {
application: './main.js',
unauthenticated: './unauthenticated.js',
},

output: {
path: path.join(ROOT_PATH, 'public/assets/webpack'),
publicPath: '/assets/webpack/',
filename: IS_PRODUCTION ? '[name]-[chunkhash].js' : '[name].js',
chunkFilename: IS_PRODUCTION ? '[name]-[chunkhash].chunk.js' : '[name].chunk.js',
},

plugins: [
// Manifest filename must match config.webpack.manifest_filename
// webpack-rails only needs assetsByChunkName to function properly
new StatsPlugin('manifest.json', {
chunkModules: false,
source: false,
chunks: false,
modules: false,
assets: true,
}),

new VueLoaderPlugin(),

// fix legacy jQuery plugins which depend on globals
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
}),

new webpack.IgnorePlugin(/^\.\/jquery$/, /jquery-ujs$/),

WEBPACK_REPORT && new BundleAnalyzerPlugin({
analyzerMode: 'static',
generateStatsFile: true,
openAnalyzer: false,
reportFilename: path.join(ROOT_PATH, 'webpack-report/index.html'),
statsFilename: path.join(ROOT_PATH, 'webpack-report/stats.json'),
}),
].filter(Boolean),

resolve: {
extensions: ['.js', '.vue'],
mainFields: ['jsnext', 'main', 'browser'],
Expand Down Expand Up @@ -112,23 +83,66 @@ var config = {
},
],
},

optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
default: false,
vendors: {
priority: 10,
test: /[\\/](node_modules|vendor[\\/]assets[\\/]javascripts)[\\/]/,
},
},
},
},

plugins: [
// Manifest filename must match config.webpack.manifest_filename
// webpack-rails only needs assetsByChunkName to function properly
new StatsPlugin('manifest.json', {
chunkModules: false,
source: false,
chunks: false,
modules: false,
assets: true,
}),

new VueLoaderPlugin(),

// fix legacy jQuery plugins which depend on globals
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
}),

new webpack.IgnorePlugin(/^\.\/jquery$/, /jquery-ujs$/),

WEBPACK_REPORT && new BundleAnalyzerPlugin({
analyzerMode: 'static',
generateStatsFile: true,
openAnalyzer: false,
reportFilename: path.join(ROOT_PATH, 'webpack-report/index.html'),
statsFilename: path.join(ROOT_PATH, 'webpack-report/stats.json'),
}),
].filter(Boolean),
};

if (IS_PRODUCTION) {
config.optimization = {
minimizer: [
new UglifyJSPlugin({
sourceMap: true,
cache: true,
parallel: true,
uglifyOptions: {
output: {
comments: false
}
config.optimization.minimizer = [
new UglifyJSPlugin({
sourceMap: true,
cache: true,
parallel: true,
uglifyOptions: {
output: {
comments: false
}
})
],
};
}
})
];

config.plugins.push(
new webpack.NoEmitOnErrorsPlugin(),

Expand Down
Loading

0 comments on commit 82199e9

Please sign in to comment.