diff options
-rw-r--r-- | build.gradle | 1 | ||||
-rw-r--r-- | server/sonar-web/build.gradle | 3 | ||||
-rw-r--r-- | server/sonar-web/package.json | 2 | ||||
-rw-r--r-- | server/sonar-web/scripts/analyze.js | 5 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/app/components/PageTracker.tsx | 3 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/app/components/__tests__/PageTracker-test.tsx | 8 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/app/components/extensions/Extension.tsx | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/app/index.ts | 2 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/helpers/__tests__/extensions-test.ts | 42 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/helpers/__tests__/extensionsHandler-test.ts | 49 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/helpers/extensions.ts | 37 | ||||
-rw-r--r-- | server/sonar-web/src/main/js/helpers/extensionsHandler.ts | 49 | ||||
-rw-r--r-- | server/sonar-web/yarn.lock | 8 |
13 files changed, 135 insertions, 76 deletions
diff --git a/build.gradle b/build.gradle index 7d94be836e3..c43c36b641a 100644 --- a/build.gradle +++ b/build.gradle @@ -62,6 +62,7 @@ allprojects { ext { release = project.hasProperty('release') && project.getProperty('release') + ci = project.hasProperty('ci') && project.getProperty('ci') official = project.hasProperty('official') && project.getProperty('official') } diff --git a/server/sonar-web/build.gradle b/server/sonar-web/build.gradle index 17ceecbd5dc..7e99f19ef1d 100644 --- a/server/sonar-web/build.gradle +++ b/server/sonar-web/build.gradle @@ -27,6 +27,7 @@ yarn_run { inputs.property('official', official) inputs.property('release', release) + inputs.property('ci', ci) ['config', 'public', 'scripts', 'src', '../sonar-docs/src'].each { inputs.dir(it).withPathSensitivity(PathSensitivity.RELATIVE) @@ -36,7 +37,7 @@ yarn_run { } outputs.dir(webappDir) outputs.cacheIf { true } - args = [release ? 'build-release' : 'build'] + args = [release || ci ? 'build-release' : 'build'] } build.dependsOn(yarn_run) diff --git a/server/sonar-web/package.json b/server/sonar-web/package.json index cca4351ea04..4139065226d 100644 --- a/server/sonar-web/package.json +++ b/server/sonar-web/package.json @@ -125,7 +125,7 @@ "ts-loader": "5.3.3", "typescript": "3.3.3333", "webpack": "4.29.6", - "webpack-bundle-analyzer": "3.1.0", + "webpack-bundle-analyzer": "3.3.2", "webpack-dev-server": "3.2.1" }, "scripts": { diff --git a/server/sonar-web/scripts/analyze.js b/server/sonar-web/scripts/analyze.js index c41bedde127..b0c21ea1954 100644 --- a/server/sonar-web/scripts/analyze.js +++ b/server/sonar-web/scripts/analyze.js @@ -24,10 +24,11 @@ const webpack = require('webpack'); const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const getConfigs = require('../config/webpack.config'); -const configs = getConfigs({ production: true }); +const configs = getConfigs({ production: true, release: true }); const config = configs.find(config => config.name === 'modern'); +const analyzerPort = process.env.PORT || 8888; -config.plugins.push(new BundleAnalyzerPlugin()); +config.plugins.push(new BundleAnalyzerPlugin({ analyzerPort })); webpack(config, err => { if (err) { diff --git a/server/sonar-web/src/main/js/app/components/PageTracker.tsx b/server/sonar-web/src/main/js/app/components/PageTracker.tsx index 0af0e6bec16..0ce7f93111b 100644 --- a/server/sonar-web/src/main/js/app/components/PageTracker.tsx +++ b/server/sonar-web/src/main/js/app/components/PageTracker.tsx @@ -22,7 +22,8 @@ import { connect } from 'react-redux'; import Helmet from 'react-helmet'; import { Location, withRouter } from '../../components/hoc/withRouter'; import { gtm } from '../../helpers/analytics'; -import { installScript, getWebAnalyticsPageHandlerFromCache } from '../../helpers/extensions'; +import { installScript } from '../../helpers/extensions'; +import { getWebAnalyticsPageHandlerFromCache } from '../../helpers/extensionsHandler'; import { getInstance } from '../../helpers/system'; import { getGlobalSettingValue, Store, getAppState } from '../../store/rootReducer'; diff --git a/server/sonar-web/src/main/js/app/components/__tests__/PageTracker-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/PageTracker-test.tsx index 59f6fe13655..36d40db9a93 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/PageTracker-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/PageTracker-test.tsx @@ -23,10 +23,14 @@ import { shallow } from 'enzyme'; import { PageTracker } from '../PageTracker'; import { gtm } from '../../../helpers/analytics'; import { mockLocation } from '../../../helpers/testMocks'; -import { installScript, getWebAnalyticsPageHandlerFromCache } from '../../../helpers/extensions'; +import { installScript } from '../../../helpers/extensions'; +import { getWebAnalyticsPageHandlerFromCache } from '../../../helpers/extensionsHandler'; jest.mock('../../../helpers/extensions', () => ({ - installScript: jest.fn().mockResolvedValue({}), + installScript: jest.fn().mockResolvedValue({}) +})); + +jest.mock('../../../helpers/extensionsHandler', () => ({ getWebAnalyticsPageHandlerFromCache: jest.fn().mockReturnValue(undefined) })); diff --git a/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx b/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx index 2e66aa797d3..c0eb4175997 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx +++ b/server/sonar-web/src/main/js/app/components/extensions/Extension.tsx @@ -22,11 +22,11 @@ import Helmet from 'react-helmet'; import { injectIntl, InjectedIntlProps } from 'react-intl'; import { connect } from 'react-redux'; import getStore from '../../utils/getStore'; +import { Location, Router, withRouter } from '../../../components/hoc/withRouter'; import { getExtensionStart } from '../../../helpers/extensions'; import { addGlobalErrorMessage } from '../../../store/globalMessages'; import { translate } from '../../../helpers/l10n'; import { Store, getCurrentUser } from '../../../store/rootReducer'; -import { Location, Router, withRouter } from '../../../components/hoc/withRouter'; interface Props extends InjectedIntlProps { currentUser: T.CurrentUser; diff --git a/server/sonar-web/src/main/js/app/index.ts b/server/sonar-web/src/main/js/app/index.ts index 8fd4bc68a9d..fd3639bcc05 100644 --- a/server/sonar-web/src/main/js/app/index.ts +++ b/server/sonar-web/src/main/js/app/index.ts @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { installGlobal, DEFAULT_LANGUAGE, requestMessages } from '../helpers/l10n'; -import { installExtensionsHandler, installWebAnalyticsHandler } from '../helpers/extensions'; +import { installExtensionsHandler, installWebAnalyticsHandler } from '../helpers/extensionsHandler'; import { request, parseJSON } from '../helpers/request'; import { getSystemStatus } from '../helpers/system'; import './styles/sonar.css'; diff --git a/server/sonar-web/src/main/js/helpers/__tests__/extensions-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/extensions-test.ts index 72ece2f775b..182fa0e54d6 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/extensions-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/extensions-test.ts @@ -17,14 +17,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { - getExtensionFromCache, - getWebAnalyticsPageHandlerFromCache, - getExtensionStart, - installExtensionsHandler, - installScript, - installWebAnalyticsHandler -} from '../extensions'; +import { getExtensionStart, installScript } from '../extensions'; +import { installExtensionsHandler } from '../extensionsHandler'; import exposeLibraries from '../../app/components/extensions/exposeLibraries'; jest.mock('../../app/components/extensions/exposeLibraries', () => ({ @@ -35,30 +29,6 @@ beforeEach(() => { jest.clearAllMocks(); }); -describe('installExtensionsHandler & extensions.getExtensionFromCache', () => { - it('should register the global "registerExtension" function and retrieve extension', () => { - expect((window as any).registerExtension).toBeUndefined(); - installExtensionsHandler(); - expect((window as any).registerExtension).toEqual(expect.any(Function)); - - const start = jest.fn(); - (window as any).registerExtension('foo', start); - expect(getExtensionFromCache('foo')).toBe(start); - }); -}); - -describe('setWebAnalyticsPageChangeHandler & getWebAnalyticsPageHandlerFromCache', () => { - it('should register the global "setWebAnalyticsPageChangeHandler" function and retrieve analytics extension', () => { - expect((window as any).setWebAnalyticsPageChangeHandler).toBeUndefined(); - installWebAnalyticsHandler(); - expect((window as any).setWebAnalyticsPageChangeHandler).toEqual(expect.any(Function)); - - const pageChange = jest.fn(); - (window as any).setWebAnalyticsPageChangeHandler(pageChange); - expect(getWebAnalyticsPageHandlerFromCache()).toBe(pageChange); - }); -}); - describe('installScript', () => { it('should add the given script in the dom', () => { installScript('custom_script.js'); @@ -67,17 +37,19 @@ describe('installScript', () => { }); describe('getExtensionStart', () => { - it('should install the extension in the to dom', () => { + it('should install the extension in the to dom', async () => { const start = jest.fn(); const scriptTag = document.createElement('script'); document.createElement = jest.fn().mockReturnValue(scriptTag); installExtensionsHandler(); const result = getExtensionStart('bar'); - (window as any).registerExtension('bar', start); - (scriptTag.onload as Function)(); + await new Promise(setImmediate); expect(exposeLibraries).toBeCalled(); + + (window as any).registerExtension('bar', start); + (scriptTag.onload as Function)(); return expect(result).resolves.toBe(start); }); diff --git a/server/sonar-web/src/main/js/helpers/__tests__/extensionsHandler-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/extensionsHandler-test.ts new file mode 100644 index 00000000000..a2a23379e32 --- /dev/null +++ b/server/sonar-web/src/main/js/helpers/__tests__/extensionsHandler-test.ts @@ -0,0 +1,49 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { + getExtensionFromCache, + getWebAnalyticsPageHandlerFromCache, + installExtensionsHandler, + installWebAnalyticsHandler +} from '../extensionsHandler'; + +describe('installExtensionsHandler & extensions.getExtensionFromCache', () => { + it('should register the global "registerExtension" function and retrieve extension', () => { + expect((window as any).registerExtension).toBeUndefined(); + installExtensionsHandler(); + expect((window as any).registerExtension).toEqual(expect.any(Function)); + + const start = jest.fn(); + (window as any).registerExtension('foo', start); + expect(getExtensionFromCache('foo')).toBe(start); + }); +}); + +describe('setWebAnalyticsPageChangeHandler & getWebAnalyticsPageHandlerFromCache', () => { + it('should register the global "setWebAnalyticsPageChangeHandler" function and retrieve analytics extension', () => { + expect((window as any).setWebAnalyticsPageChangeHandler).toBeUndefined(); + installWebAnalyticsHandler(); + expect((window as any).setWebAnalyticsPageChangeHandler).toEqual(expect.any(Function)); + + const pageChange = jest.fn(); + (window as any).setWebAnalyticsPageChangeHandler(pageChange); + expect(getWebAnalyticsPageHandlerFromCache()).toBe(pageChange); + }); +}); diff --git a/server/sonar-web/src/main/js/helpers/extensions.ts b/server/sonar-web/src/main/js/helpers/extensions.ts index 66a56cf3ed0..6d40d843625 100644 --- a/server/sonar-web/src/main/js/helpers/extensions.ts +++ b/server/sonar-web/src/main/js/helpers/extensions.ts @@ -18,34 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { getBaseUrl } from './urls'; -import exposeLibraries from '../app/components/extensions/exposeLibraries'; +import { getExtensionFromCache } from './extensionsHandler'; -const WEB_ANALYTICS_EXTENSION = 'sq-web-analytics'; -const extensions: T.Dict<Function> = {}; - -function registerExtension(key: string, start: Function) { - extensions[key] = start; -} - -function setWebAnalyticsPageChangeHandler(pageHandler: (pathname: string) => void) { - registerExtension(WEB_ANALYTICS_EXTENSION, pageHandler); -} - -export function installExtensionsHandler() { - (window as any).registerExtension = registerExtension; -} - -export function installWebAnalyticsHandler() { - (window as any).setWebAnalyticsPageChangeHandler = setWebAnalyticsPageChangeHandler; -} - -export function getExtensionFromCache(key: string): Function | undefined { - return extensions[key]; -} - -export function getWebAnalyticsPageHandlerFromCache(): Function | undefined { - return extensions[WEB_ANALYTICS_EXTENSION]; -} +let librariesExposed = false; export function installScript(url: string, target: 'body' | 'head' = 'body'): Promise<any> { return new Promise(resolve => { @@ -62,7 +37,13 @@ export async function getExtensionStart(key: string) { return Promise.resolve(fromCache); } - exposeLibraries(); + if (!librariesExposed) { + // Async import allows to reduce initial vendor bundle size + const exposeLibraries = (await import('../app/components/extensions/exposeLibraries')).default; + exposeLibraries(); + librariesExposed = true; + } + await installScript(`/static/${key}.js`); const start = getExtensionFromCache(key); diff --git a/server/sonar-web/src/main/js/helpers/extensionsHandler.ts b/server/sonar-web/src/main/js/helpers/extensionsHandler.ts new file mode 100644 index 00000000000..e414b2fdbbd --- /dev/null +++ b/server/sonar-web/src/main/js/helpers/extensionsHandler.ts @@ -0,0 +1,49 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// Do not import dependencies in this helper, to keep initial bundle load as small as possible + +const WEB_ANALYTICS_EXTENSION = 'sq-web-analytics'; + +const extensions: T.Dict<Function> = {}; + +function registerExtension(key: string, start: Function) { + extensions[key] = start; +} + +function setWebAnalyticsPageChangeHandler(pageHandler: (pathname: string) => void) { + registerExtension(WEB_ANALYTICS_EXTENSION, pageHandler); +} + +export function installExtensionsHandler() { + (window as any).registerExtension = registerExtension; +} + +export function installWebAnalyticsHandler() { + (window as any).setWebAnalyticsPageChangeHandler = setWebAnalyticsPageChangeHandler; +} + +export function getExtensionFromCache(key: string): Function | undefined { + return extensions[key]; +} + +export function getWebAnalyticsPageHandlerFromCache(): Function | undefined { + return extensions[WEB_ANALYTICS_EXTENSION]; +} diff --git a/server/sonar-web/yarn.lock b/server/sonar-web/yarn.lock index fbb636f62db..f3cd22159f4 100644 --- a/server/sonar-web/yarn.lock +++ b/server/sonar-web/yarn.lock @@ -10247,10 +10247,10 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-bundle-analyzer@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.1.0.tgz#2f19cbb87bb6d4f3cb4e59cb67c837bd9436e89d" - integrity sha512-nyDyWEs7C6DZlgvu1pR1zzJfIWSiGPbtaByZr8q+Fd2xp70FuM/8ngCJzj3Er1TYRLSFmp1F1OInbEm4DZH8NA== +webpack-bundle-analyzer@3.3.2: + version "3.3.2" + resolved "https://repox.jfrog.io/repox/api/npm/npm/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz#3da733a900f515914e729fcebcd4c40dde71fc6f" + integrity sha1-PaczqQD1FZFOcp/OvNTEDd5x/G8= dependencies: acorn "^6.0.7" acorn-walk "^6.1.1" |