diff --git a/package.json b/package.json index 2cffb8bc4c94..adbd9f45c26d 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@types/sinon": "^7.0.11", "chai": "^4.1.2", "codecov": "^3.6.5", + "deepmerge": "^4.2.2", "eslint": "7.32.0", "jest": "^24.9.0", "karma-browserstack-launcher": "^1.5.1", diff --git a/packages/tracing/rollup.config.js b/packages/tracing/rollup.config.js index 2b9d0ca3e2aa..2b5f4fbc13ee 100644 --- a/packages/tracing/rollup.config.js +++ b/packages/tracing/rollup.config.js @@ -1,53 +1,29 @@ -import { - baseBundleConfig, - makeLicensePlugin, - markAsBrowserBuild, - nodeResolvePlugin, - terserPlugin, - typescriptPluginES5, -} from '../../rollup.config'; +import { makeBaseBundleConfig, makeLicensePlugin, terserPlugin } from '../../rollup.config'; const licensePlugin = makeLicensePlugin('@sentry/tracing & @sentry/browser'); -const plugins = [ - typescriptPluginES5, - // replace `__SENTRY_BROWSER_BUNDLE__` with `true` to enable treeshaking of non-browser code - markAsBrowserBuild, - nodeResolvePlugin, - licensePlugin, -]; - -const bundleConfig = { - ...baseBundleConfig, - input: 'src/index.ts', - output: { - ...baseBundleConfig.output, - format: 'iife', - name: 'Sentry', - }, - context: 'window', - plugins, -}; +const baseBundleConfig = makeBaseBundleConfig({ + input: 'src/index.bundle.ts', + isAddOn: false, + outputFileBase: 'build/bundle.tracing', +}); export default [ // ES5 Browser Tracing Bundle { - ...bundleConfig, - input: 'src/index.bundle.ts', + ...baseBundleConfig, output: { - ...bundleConfig.output, - file: 'build/bundle.tracing.js', + ...baseBundleConfig.output, + file: `${baseBundleConfig.output.file}.js`, }, - plugins: bundleConfig.plugins, + plugins: [...baseBundleConfig.plugins, licensePlugin], }, { - ...bundleConfig, - input: 'src/index.bundle.ts', + ...baseBundleConfig, output: { - ...bundleConfig.output, - file: 'build/bundle.tracing.min.js', + ...baseBundleConfig.output, + file: `${baseBundleConfig.output.file}.min.js`, }, - // Uglify has to be at the end of compilation, BUT before the license banner - plugins: bundleConfig.plugins.slice(0, -1).concat(terserPlugin).concat(bundleConfig.plugins.slice(-1)), + plugins: [...baseBundleConfig.plugins, terserPlugin, licensePlugin], }, ]; diff --git a/packages/vue/rollup.config.js b/packages/vue/rollup.config.js index 66bf22bd6169..9092aa12634f 100644 --- a/packages/vue/rollup.config.js +++ b/packages/vue/rollup.config.js @@ -1,53 +1,28 @@ -import { - baseBundleConfig, - makeLicensePlugin, - markAsBrowserBuild, - nodeResolvePlugin, - terserPlugin, - typescriptPluginES5, -} from '../../rollup.config'; +import { makeBaseBundleConfig, makeLicensePlugin, terserPlugin } from '../../rollup.config'; const licensePlugin = makeLicensePlugin(); -const plugins = [ - typescriptPluginES5, - // replace `__SENTRY_BROWSER_BUNDLE__` with `true` to enable treeshaking of non-browser code - markAsBrowserBuild, - nodeResolvePlugin, - licensePlugin, -]; - -const bundleConfig = { - ...baseBundleConfig, - input: 'src/index.ts', - output: { - ...baseBundleConfig.output, - format: 'iife', - name: 'Sentry', - }, - context: 'window', - plugins, -}; +const baseBundleConfig = makeBaseBundleConfig({ + input: 'src/index.bundle.ts', + isAddOn: false, + outputFileBase: 'build/bundle.vue', +}); export default [ - // ES5 Browser Tracing Bundle { - ...bundleConfig, - input: 'src/index.bundle.ts', + ...baseBundleConfig, output: { - ...bundleConfig.output, - file: 'build/bundle.vue.js', + ...baseBundleConfig.output, + file: `${baseBundleConfig.output.file}.js`, }, - plugins: bundleConfig.plugins, + plugins: [...baseBundleConfig.plugins, licensePlugin], }, { - ...bundleConfig, - input: 'src/index.bundle.ts', + ...baseBundleConfig, output: { - ...bundleConfig.output, - file: 'build/bundle.vue.min.js', + ...baseBundleConfig.output, + file: `${baseBundleConfig.output.file}.min.js`, }, - // Uglify has to be at the end of compilation, BUT before the license banner - plugins: bundleConfig.plugins.slice(0, -1).concat(terserPlugin).concat(bundleConfig.plugins.slice(-1)), + plugins: [...baseBundleConfig.plugins, terserPlugin, licensePlugin], }, ]; diff --git a/packages/wasm/rollup.config.js b/packages/wasm/rollup.config.js index 60b09d39972d..3fe988090b83 100644 --- a/packages/wasm/rollup.config.js +++ b/packages/wasm/rollup.config.js @@ -1,38 +1,28 @@ -import { - addOnBundleConfig, - baseBundleConfig, - markAsBrowserBuild, - nodeResolvePlugin, - terserPlugin, - typescriptPluginES5, -} from '../../rollup.config'; +import { makeBaseBundleConfig, terserPlugin } from '../../rollup.config'; -const plugins = [ - typescriptPluginES5, - // replace `__SENTRY_BROWSER_BUNDLE__` with `true` to enable treeshaking of non-browser code - markAsBrowserBuild, - nodeResolvePlugin, -]; +const baseBundleConfig = makeBaseBundleConfig({ + input: 'src/index.ts', + isAddOn: true, + outputFileBase: 'build/wasm', +}); function loadAllIntegrations() { const builds = []; [ { extension: '.js', - plugins, + plugins: baseBundleConfig.plugins, }, { extension: '.min.js', - plugins: [...plugins, terserPlugin], + plugins: [...baseBundleConfig.plugins, terserPlugin], }, ].forEach(build => { builds.push({ ...baseBundleConfig, - input: `src/index.ts`, output: { ...baseBundleConfig.output, - ...addOnBundleConfig.output, - file: `build/wasm${build.extension}`, + file: `${baseBundleConfig.output.file}${build.extension}`, }, plugins: build.plugins, }); diff --git a/rollup.config.js b/rollup.config.js index 9c49aded1c39..3c684bf391e6 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,7 +1,14 @@ /** - * Shared config used by individual packages' Rollup configs + * Shared config used by individual packages' Rollup configs. Items here come in three flavors: + * - stand-alone: used by `@sentry/browser`, `@sentry/tracing`, and `@sentry/vue` (bundles which are a full SDK in + * and of themselves) + * - add-on: used by `@sentry/integrations` and `@sentry/wasm` (bundles which need to be combined with a stand-alone + * SDK bundle) + * - shared: used by both types of bundles + * */ +import deepMerge from 'deepmerge'; import license from 'rollup-plugin-license'; import resolve from '@rollup/plugin-node-resolve'; import replace from '@rollup/plugin-replace'; @@ -115,3 +122,61 @@ export const addOnBundleConfig = { footer: '}(window));', }, }; + +export function makeBaseBundleConfig(options) { + const { input, isAddOn, outputFileBase } = options; + + const standAloneBundleConfig = { + output: { + format: 'iife', + name: 'Sentry', + }, + context: 'window', + }; + + const addOnBundleConfig = { + // These output settings are designed to mimic an IIFE. We don't use Rollup's `iife` format because we don't want to + // attach this code to a new global variable, but rather inject it into the existing SDK's `Integrations` object. + output: { + format: 'cjs', + + // code to add before the CJS wrapper + banner: '(function (__window) {', + + // code to add just inside the CJS wrapper, before any of the wrapped code + intro: 'var exports = {};', + + // code to add after all of the wrapped code, but still inside the CJS wrapper + outro: () => + [ + '', + " // Add this module's exports to the global `Sentry.Integrations`", + ' __window.Sentry = __window.Sentry || {};', + ' __window.Sentry.Integrations = __window.Sentry.Integrations || {};', + ' for (var key in exports) {', + ' if (Object.prototype.hasOwnProperty.call(exports, key)) {', + ' __window.Sentry.Integrations[key] = exports[key];', + ' }', + ' }', + ].join('\n'), + + // code to add after the CJS wrapper + footer: '}(window));', + }, + }; + + const sharedBundleConfig = { + input, + output: { + // a file extension will be added to this base value when we specify either a minified or non-minified build + file: outputFileBase, + sourcemap: true, + strict: false, + esModule: false, + }, + plugins: [typescriptPluginES5, markAsBrowserBuild, nodeResolvePlugin], + treeshake: 'smallest', + }; + + return deepMerge(sharedBundleConfig, isAddOn ? addOnBundleConfig : standAloneBundleConfig); +}