@@ -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') | |||
} | |||
@@ -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) | |||
@@ -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": { |
@@ -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) { |
@@ -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'; | |||
@@ -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) | |||
})); | |||
@@ -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; |
@@ -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'; |
@@ -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); | |||
}); | |||
@@ -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); | |||
}); | |||
}); |
@@ -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); |
@@ -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]; | |||
} |
@@ -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" |