Commit ee600a84 authored by Jacob Schatz's avatar Jacob Schatz

Merge branch 'webpack-auto-config' into 'master'

Automatically Generate Webpack Entry Points

See merge request gitlab-org/gitlab-ce!16865
parents a58f8c32 65407c38
...@@ -12,9 +12,9 @@ import ShortcutsIssuable from './shortcuts_issuable'; ...@@ -12,9 +12,9 @@ import ShortcutsIssuable from './shortcuts_issuable';
import Diff from './diff'; import Diff from './diff';
import SearchAutocomplete from './search_autocomplete'; import SearchAutocomplete from './search_autocomplete';
(function() { var Dispatcher;
var Dispatcher;
(function() {
Dispatcher = (function() { Dispatcher = (function() {
function Dispatcher() { function Dispatcher() {
this.initSearch(); this.initSearch();
...@@ -49,46 +49,16 @@ import SearchAutocomplete from './search_autocomplete'; ...@@ -49,46 +49,16 @@ import SearchAutocomplete from './search_autocomplete';
}); });
switch (page) { switch (page) {
case 'sessions:new':
import('./pages/sessions/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:boards:show':
case 'projects:boards:index':
import('./pages/projects/boards/index')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:environments:metrics': case 'projects:environments:metrics':
import('./pages/projects/environments/metrics') import('./pages/projects/environments/metrics')
.then(callDefault) .then(callDefault)
.catch(fail); .catch(fail);
break; break;
case 'projects:merge_requests:index': case 'projects:merge_requests:index':
import('./pages/projects/merge_requests/index')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:issues:index': case 'projects:issues:index':
import('./pages/projects/issues/index')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:issues:show': case 'projects:issues:show':
import('./pages/projects/issues/show')
.then(callDefault)
.catch(fail);
shortcut_handler = true; shortcut_handler = true;
break; break;
case 'dashboard:milestones:index':
import('./pages/dashboard/milestones/index')
.then(callDefault)
.catch(fail);
break;
case 'projects:milestones:index': case 'projects:milestones:index':
import('./pages/projects/milestones/index') import('./pages/projects/milestones/index')
.then(callDefault) .then(callDefault)
...@@ -318,9 +288,6 @@ import SearchAutocomplete from './search_autocomplete'; ...@@ -318,9 +288,6 @@ import SearchAutocomplete from './search_autocomplete';
shortcut_handler = true; shortcut_handler = true;
break; break;
case 'projects:show': case 'projects:show':
import('./pages/projects/show')
.then(callDefault)
.catch(fail);
shortcut_handler = true; shortcut_handler = true;
break; break;
case 'projects:edit': case 'projects:edit':
...@@ -352,9 +319,6 @@ import SearchAutocomplete from './search_autocomplete'; ...@@ -352,9 +319,6 @@ import SearchAutocomplete from './search_autocomplete';
.catch(fail); .catch(fail);
break; break;
case 'groups:show': case 'groups:show':
import('./pages/groups/show')
.then(callDefault)
.catch(fail);
shortcut_handler = true; shortcut_handler = true;
break; break;
case 'groups:group_members:index': case 'groups:group_members:index':
...@@ -363,7 +327,7 @@ import SearchAutocomplete from './search_autocomplete'; ...@@ -363,7 +327,7 @@ import SearchAutocomplete from './search_autocomplete';
.catch(fail); .catch(fail);
break; break;
case 'projects:project_members:index': case 'projects:project_members:index':
import('./pages/projects/project_members/') import('./pages/projects/project_members')
.then(callDefault) .then(callDefault)
.catch(fail); .catch(fail);
break; break;
...@@ -605,7 +569,7 @@ import SearchAutocomplete from './search_autocomplete'; ...@@ -605,7 +569,7 @@ import SearchAutocomplete from './search_autocomplete';
} }
break; break;
case 'profiles': case 'profiles':
import('./pages/profiles/index/') import('./pages/profiles/index')
.then(callDefault) .then(callDefault)
.catch(fail); .catch(fail);
break; break;
...@@ -662,8 +626,8 @@ import SearchAutocomplete from './search_autocomplete'; ...@@ -662,8 +626,8 @@ import SearchAutocomplete from './search_autocomplete';
return Dispatcher; return Dispatcher;
})(); })();
})();
$(window).on('load', function() { export default function initDispatcher() {
new Dispatcher(); return new Dispatcher();
}); }
}).call(window);
...@@ -33,7 +33,7 @@ import './projects_dropdown'; ...@@ -33,7 +33,7 @@ import './projects_dropdown';
import './render_gfm'; import './render_gfm';
import initBreadcrumbs from './breadcrumb'; import initBreadcrumbs from './breadcrumb';
import './dispatcher'; import initDispatcher from './dispatcher';
// eslint-disable-next-line global-require, import/no-commonjs // eslint-disable-next-line global-require, import/no-commonjs
if (process.env.NODE_ENV !== 'production') require('./test_utils/'); if (process.env.NODE_ENV !== 'production') require('./test_utils/');
...@@ -265,4 +265,6 @@ $(() => { ...@@ -265,4 +265,6 @@ $(() => {
removeFlashClickListener(flashEl); removeFlashClickListener(flashEl);
}); });
} }
initDispatcher();
}); });
import projectSelect from '~/project_select'; import projectSelect from '~/project_select';
export default projectSelect; document.addEventListener('DOMContentLoaded', projectSelect);
...@@ -7,7 +7,7 @@ import ProjectsList from '~/projects_list'; ...@@ -7,7 +7,7 @@ import ProjectsList from '~/projects_list';
import ShortcutsNavigation from '~/shortcuts_navigation'; import ShortcutsNavigation from '~/shortcuts_navigation';
import initGroupsList from '../../../groups'; import initGroupsList from '../../../groups';
export default () => { document.addEventListener('DOMContentLoaded', () => {
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup'); const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
new ShortcutsNavigation(); new ShortcutsNavigation();
new NotificationsForm(); new NotificationsForm();
...@@ -19,4 +19,4 @@ export default () => { ...@@ -19,4 +19,4 @@ export default () => {
} }
initGroupsList(); initGroupsList();
}; });
import UsersSelect from '~/users_select'; import UsersSelect from '~/users_select';
import ShortcutsNavigation from '~/shortcuts_navigation'; import ShortcutsNavigation from '~/shortcuts_navigation';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new UsersSelect(); // eslint-disable-line no-new new UsersSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
}; });
...@@ -7,10 +7,10 @@ import initFilteredSearch from '~/pages/search/init_filtered_search'; ...@@ -7,10 +7,10 @@ import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants'; import { ISSUABLE_INDEX } from '~/pages/projects/constants';
export default () => { document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch(FILTERED_SEARCH.ISSUES); initFilteredSearch(FILTERED_SEARCH.ISSUES);
new IssuableIndex(ISSUABLE_INDEX.ISSUE); new IssuableIndex(ISSUABLE_INDEX.ISSUE);
new ShortcutsNavigation(); new ShortcutsNavigation();
new UsersSelect(); new UsersSelect();
}; });
/* eslint-disable no-new */ /* eslint-disable no-new */
import initIssuableSidebar from '~/init_issuable_sidebar'; import initIssuableSidebar from '~/init_issuable_sidebar';
import Issue from '~/issue'; import Issue from '~/issue';
import ShortcutsIssuable from '~/shortcuts_issuable'; import ShortcutsIssuable from '~/shortcuts_issuable';
import ZenMode from '~/zen_mode'; import ZenMode from '~/zen_mode';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new Issue(); new Issue();
new ShortcutsIssuable(); new ShortcutsIssuable();
new ZenMode(); new ZenMode();
initIssuableSidebar(); initIssuableSidebar();
}; });
...@@ -5,9 +5,9 @@ import initFilteredSearch from '~/pages/search/init_filtered_search'; ...@@ -5,9 +5,9 @@ import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants'; import { ISSUABLE_INDEX } from '~/pages/projects/constants';
export default () => { document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch(FILTERED_SEARCH.MERGE_REQUESTS); initFilteredSearch(FILTERED_SEARCH.MERGE_REQUESTS);
new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
new UsersSelect(); // eslint-disable-line no-new new UsersSelect(); // eslint-disable-line no-new
}; });
...@@ -8,7 +8,7 @@ import { ajaxGet } from '~/lib/utils/common_utils'; ...@@ -8,7 +8,7 @@ import { ajaxGet } from '~/lib/utils/common_utils';
import Star from '../../../star'; import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown'; import notificationsDropdown from '../../../notifications_dropdown';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new Star(); // eslint-disable-line no-new new Star(); // eslint-disable-line no-new
notificationsDropdown(); notificationsDropdown();
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
...@@ -24,4 +24,4 @@ export default () => { ...@@ -24,4 +24,4 @@ export default () => {
$('#tree-slider').waitForImages(() => { $('#tree-slider').waitForImages(() => {
ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath); ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath);
}); });
}; });
...@@ -2,10 +2,10 @@ import UsernameValidator from './username_validator'; ...@@ -2,10 +2,10 @@ import UsernameValidator from './username_validator';
import SigninTabsMemoizer from './signin_tabs_memoizer'; import SigninTabsMemoizer from './signin_tabs_memoizer';
import OAuthRememberMe from './oauth_remember_me'; import OAuthRememberMe from './oauth_remember_me';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new UsernameValidator(); // eslint-disable-line no-new new UsernameValidator(); // eslint-disable-line no-new
new SigninTabsMemoizer(); // eslint-disable-line no-new new SigninTabsMemoizer(); // eslint-disable-line no-new
new OAuthRememberMe({ // eslint-disable-line no-new new OAuthRememberMe({ // eslint-disable-line no-new
container: $('.omniauth-container'), container: $('.omniauth-container'),
}).bindEvents(); }).bindEvents();
}; });
...@@ -5,6 +5,24 @@ module WebpackHelper ...@@ -5,6 +5,24 @@ module WebpackHelper
javascript_include_tag(*gitlab_webpack_asset_paths(bundle, force_same_domain: force_same_domain)) javascript_include_tag(*gitlab_webpack_asset_paths(bundle, force_same_domain: force_same_domain))
end end
def webpack_controller_bundle_tags
bundles = []
segments = [*controller.controller_path.split('/'), controller.action_name].compact
until segments.empty?
begin
asset_paths = gitlab_webpack_asset_paths("pages.#{segments.join('.')}", extension: 'js')
bundles.unshift(*asset_paths)
rescue Webpack::Rails::Manifest::EntryPointMissingError
# no bundle exists for this path
end
segments.pop
end
javascript_include_tag(*bundles)
end
# override webpack-rails gem helper until changes can make it upstream # override webpack-rails gem helper until changes can make it upstream
def gitlab_webpack_asset_paths(source, extension: nil, force_same_domain: false) def gitlab_webpack_asset_paths(source, extension: nil, force_same_domain: false)
return "" unless source.present? return "" unless source.present?
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
- if content_for?(:page_specific_javascripts) - if content_for?(:page_specific_javascripts)
= yield :page_specific_javascripts = yield :page_specific_javascripts
= webpack_controller_bundle_tags
= yield :project_javascripts = yield :project_javascripts
= csrf_meta_tags = csrf_meta_tags
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
var crypto = require('crypto'); var crypto = require('crypto');
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
var glob = require('glob');
var webpack = require('webpack'); var webpack = require('webpack');
var StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin; var StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
var CopyWebpackPlugin = require('copy-webpack-plugin'); var CopyWebpackPlugin = require('copy-webpack-plugin');
...@@ -20,6 +21,26 @@ var DEV_SERVER_LIVERELOAD = process.env.DEV_SERVER_LIVERELOAD !== 'false'; ...@@ -20,6 +21,26 @@ var DEV_SERVER_LIVERELOAD = process.env.DEV_SERVER_LIVERELOAD !== 'false';
var WEBPACK_REPORT = process.env.WEBPACK_REPORT; var WEBPACK_REPORT = process.env.WEBPACK_REPORT;
var NO_COMPRESSION = process.env.NO_COMPRESSION; var NO_COMPRESSION = process.env.NO_COMPRESSION;
// generate automatic entry points
var autoEntries = {};
var pageEntries = glob.sync('pages/**/index.js', { cwd: path.join(ROOT_PATH, 'app/assets/javascripts') });
// filter out entries currently imported dynamically in dispatcher.js
var dispatcher = fs.readFileSync(path.join(ROOT_PATH, 'app/assets/javascripts/dispatcher.js')).toString();
var dispatcherChunks = dispatcher.match(/(?!import\('.\/)pages\/[^']+/g);
pageEntries.forEach(( path ) => {
let chunkPath = path.replace(/\/index\.js$/, '');
if (!dispatcherChunks.includes(chunkPath)) {
let chunkName = chunkPath.replace(/\//g, '.');
autoEntries[chunkName] = './' + path;
}
});
// report our auto-generated bundle count
var autoEntriesCount = Object.keys(autoEntries).length;
console.log(`${autoEntriesCount} entries from '/pages' automatically added to webpack output.`);
var config = { var config = {
// because sqljs requires fs. // because sqljs requires fs.
node: { node: {
...@@ -301,6 +322,8 @@ var config = { ...@@ -301,6 +322,8 @@ var config = {
} }
} }
config.entry = Object.assign({}, autoEntries, config.entry);
if (IS_PRODUCTION) { if (IS_PRODUCTION) {
config.devtool = 'source-map'; config.devtool = 'source-map';
config.plugins.push( config.plugins.push(
......
{ {
"private": true, "private": true,
"scripts": { "scripts": {
"dev-server": "nodemon --watch config/webpack.config.js -- ./node_modules/.bin/webpack-dev-server --config config/webpack.config.js", "dev-server": "nodemon -w 'config/webpack.config.js' -w 'app/assets/javascripts/dispatcher.js' -w 'app/assets/javascripts/pages/**/index.js' --exec 'webpack-dev-server --config config/webpack.config.js'",
"eslint": "eslint --max-warnings 0 --ext .js,.vue .", "eslint": "eslint --max-warnings 0 --ext .js,.vue .",
"eslint-fix": "eslint --max-warnings 0 --ext .js,.vue --fix .", "eslint-fix": "eslint --max-warnings 0 --ext .js,.vue --fix .",
"eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html .", "eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html .",
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
"exports-loader": "^0.6.4", "exports-loader": "^0.6.4",
"file-loader": "^0.11.1", "file-loader": "^0.11.1",
"fuzzaldrin-plus": "^0.5.0", "fuzzaldrin-plus": "^0.5.0",
"glob": "^7.1.2",
"imports-loader": "^0.7.1", "imports-loader": "^0.7.1",
"jed": "^1.1.1", "jed": "^1.1.1",
"jquery": "^2.2.4", "jquery": "^2.2.4",
......
...@@ -3322,7 +3322,7 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: ...@@ -3322,7 +3322,7 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
once "^1.3.0" once "^1.3.0"
path-is-absolute "^1.0.0" path-is-absolute "^1.0.0"
glob@^7.1.0, glob@~7.1.2: glob@^7.1.0, glob@^7.1.2, glob@~7.1.2:
version "7.1.2" version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies: dependencies:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment