Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dev-packages/node-core-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"scripts": {
"build": "run-s build:transpile build:types",
"build:dev": "yarn build",
"build:transpile": "rollup -c rollup.npm.config.mjs",
"build:transpile": "rolldown -c rollup.npm.config.mjs",
"build:types": "tsc -p tsconfig.types.json",
"clean": "rimraf -g **/node_modules && run-p clean:script",
"clean:script": "node scripts/clean.js",
Expand Down
2 changes: 1 addition & 1 deletion dev-packages/node-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"scripts": {
"build": "run-s build:transpile build:types",
"build:dev": "yarn build",
"build:transpile": "rollup -c rollup.npm.config.mjs",
"build:transpile": "rolldown -c rollup.npm.config.mjs",
"build:types": "tsc -p tsconfig.types.json",
"clean": "rimraf -g suites/**/node_modules suites/**/tmp_* && run-p clean:script",
"clean:script": "node scripts/clean.js",
Expand Down
39 changes: 15 additions & 24 deletions dev-packages/rollup-utils/bundleHelpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,46 @@
*/

import { builtinModules } from 'module';

import path from 'node:path';
import fs from 'node:fs';
import deepMerge from 'deepmerge';

import {
makeBrowserBuildPlugin,
makeCleanupPlugin,
makeCommonJSPlugin,
makeIsDebugBuildPlugin,
makeLicensePlugin,
makeNodeResolvePlugin,
makeRrwebBuildPlugin,
makeSetSDKSourcePlugin,
makeSucrasePlugin,
makeBannerOptions,
makeTerserPlugin,
} from './plugins/index.mjs';
import { mergePlugins } from './utils.mjs';
import { makeProductionReplacePlugin } from './plugins/npmPlugins.mjs';

const BUNDLE_VARIANTS = ['.js', '.min.js', '.debug.min.js'];

const packageDotJSON = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), './package.json'), { encoding: 'utf8' }));

export function makeBaseBundleConfig(options) {
const { bundleType, entrypoints, licenseTitle, outputFileBase, packageSpecificConfig, sucrase } = options;
const { bundleType, entrypoints, licenseTitle, outputFileBase, packageSpecificConfig } = options;

const nodeResolvePlugin = makeNodeResolvePlugin();
const sucrasePlugin = makeSucrasePlugin({}, sucrase);
const cleanupPlugin = makeCleanupPlugin();
const markAsBrowserBuildPlugin = makeBrowserBuildPlugin(true);
const licensePlugin = makeLicensePlugin(licenseTitle);
const banner = makeBannerOptions(licenseTitle, packageDotJSON.version);
const rrwebBuildPlugin = makeRrwebBuildPlugin({
excludeIframe: false,
excludeShadowDom: false,
});
const productionReplacePlugin = makeProductionReplacePlugin();

// The `commonjs` plugin is the `esModuleInterop` of the bundling world. When used with `transformMixedEsModules`, it
// will include all dependencies, imported or required, in the final bundle. (Without it, CJS modules aren't included
// at all, and without `transformMixedEsModules`, they're only included if they're imported, not if they're required.)
const commonJSPlugin = makeCommonJSPlugin({ transformMixedEsModules: true });

// used by `@sentry/browser`
const standAloneBundleConfig = {
output: {
banner,
format: 'iife',
name: 'Sentry',
intro: () => {
return 'exports = window.Sentry || {};';
},
},
context: 'window',
plugins: [rrwebBuildPlugin, markAsBrowserBuildPlugin, licensePlugin],
plugins: [rrwebBuildPlugin, markAsBrowserBuildPlugin],
};

// used by `@sentry/wasm` & pluggable integrations from core/browser (bundles which need to be combined with a stand-alone SDK bundle)
Expand All @@ -63,7 +53,7 @@ export function makeBaseBundleConfig(options) {
format: 'cjs',

// code to add before the CJS wrapper
banner: '(function (__window) {',
banner: `${banner}\n(function (__window) {`,

// code to add just inside the CJS wrapper, before any of the wrapped code
intro: 'var exports = {};',
Expand All @@ -86,14 +76,15 @@ export function makeBaseBundleConfig(options) {
// code to add after the CJS wrapper
footer: '}(window));',
},
plugins: [rrwebBuildPlugin, markAsBrowserBuildPlugin, licensePlugin],
plugins: [rrwebBuildPlugin, markAsBrowserBuildPlugin],
};

const workerBundleConfig = {
output: {
banner,
format: 'esm',
},
plugins: [commonJSPlugin, makeTerserPlugin(), licensePlugin],
plugins: [makeTerserPlugin()],
// Don't bundle any of Node's core modules
external: builtinModules,
};
Expand All @@ -102,7 +93,7 @@ export function makeBaseBundleConfig(options) {
output: {
format: 'esm',
},
plugins: [commonJSPlugin, makeIsDebugBuildPlugin(true), makeTerserPlugin()],
plugins: [makeIsDebugBuildPlugin(true), makeTerserPlugin()],
// Don't bundle any of Node's core modules
external: builtinModules,
};
Expand All @@ -118,7 +109,6 @@ export function makeBaseBundleConfig(options) {
strict: false,
esModule: false,
},
plugins: [productionReplacePlugin, sucrasePlugin, nodeResolvePlugin, cleanupPlugin],
treeshake: 'smallest',
};

Expand Down Expand Up @@ -180,6 +170,7 @@ export function makeBundleConfigVariants(baseConfig, options = {}) {
if (!BUNDLE_VARIANTS.includes(variant)) {
throw new Error(`Unknown bundle variant requested: ${variant}`);
}

return deepMerge(baseConfig, variantSpecificConfigMap[variant], {
// Merge the plugin arrays and make sure the end result is in the correct order. Everything else can use the
// default merge strategy.
Expand Down
5 changes: 1 addition & 4 deletions dev-packages/rollup-utils/index.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
// TODO Is this necessary?
import * as plugins from './plugins/index.mjs';
export { plugins };

export * from './plugins/index.mjs';
export * from './bundleHelpers.mjs';
export * from './npmHelpers.mjs';
export { insertAt } from './utils.mjs';
29 changes: 7 additions & 22 deletions dev-packages/rollup-utils/npmHelpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,12 @@ import * as fs from 'fs';
import { builtinModules } from 'module';
import * as path from 'path';
import { fileURLToPath } from 'url';

import deepMerge from 'deepmerge';

import { defineConfig } from 'rollup';
import { defineConfig } from 'rolldown';
import {
makeCleanupPlugin,
makeDebugBuildStatementReplacePlugin,
makeNodeResolvePlugin,
makeProductionReplacePlugin,
makeRrwebBuildPlugin,
makeSucrasePlugin,
} from './plugins/index.mjs';
import { makePackageNodeEsm } from './plugins/make-esm-plugin.mjs';
import { mergePlugins } from './utils.mjs';
Expand All @@ -34,20 +29,16 @@ export function makeBaseNPMConfig(options = {}) {
entrypoints = ['src/index.ts'],
hasBundles = false,
packageSpecificConfig = {},
sucrase = {},
bundledBuiltins = [],
} = options;

const nodeResolvePlugin = makeNodeResolvePlugin();
const sucrasePlugin = makeSucrasePlugin({}, sucrase);
const debugBuildStatementReplacePlugin = makeDebugBuildStatementReplacePlugin();
const cleanupPlugin = makeCleanupPlugin();
const rrwebBuildPlugin = makeRrwebBuildPlugin({
excludeShadowDom: undefined,
excludeIframe: undefined,
});

const defaultBaseConfig = {
const defaultBaseConfig = defineConfig({
input: entrypoints,

output: {
Expand All @@ -62,14 +53,14 @@ export function makeBaseNPMConfig(options = {}) {
// output individual files rather than one big bundle
preserveModules: true,

// output files relative to the src directory
preserveModulesRoot: 'src',

// Allow wrappers or helper functions generated by rollup to use any ES2015 features
generatedCode: {
preset: 'es2015',
},

// don't add `"use strict"` to the top of cjs files
strict: false,

// do TS-3.8-style exports
// exports.dogs = are.great
// rather than TS-3.9-style exports
Expand All @@ -78,12 +69,6 @@ export function makeBaseNPMConfig(options = {}) {
// get: () => are.great,
// });
externalLiveBindings: false,

// Don't call `Object.freeze` on the results of `import * as someModule from '...'`
// (We don't need it, so why waste the bytes?)
freeze: false,

interop: 'esModule',
},

treeshake: {
Expand All @@ -97,7 +82,7 @@ export function makeBaseNPMConfig(options = {}) {
},
},

plugins: [nodeResolvePlugin, sucrasePlugin, debugBuildStatementReplacePlugin, rrwebBuildPlugin, cleanupPlugin],
plugins: [debugBuildStatementReplacePlugin, rrwebBuildPlugin],

// don't include imported modules from outside the package in the final output
external: [
Expand All @@ -106,7 +91,7 @@ export function makeBaseNPMConfig(options = {}) {
...Object.keys(packageDotJSON.peerDependencies || {}),
...Object.keys(packageDotJSON.optionalDependencies || {}),
],
};
});

return deepMerge(defaultBaseConfig, packageSpecificConfig, {
// Plugins have to be in the correct order or everything breaks, so when merging we have to manually re-order them
Expand Down
77 changes: 31 additions & 46 deletions dev-packages/rollup-utils/plugins/bundlePlugins.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,64 +10,56 @@

import * as childProcess from 'child_process';

import commonjs from '@rollup/plugin-commonjs';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import { replacePlugin } from 'rolldown/plugins';
import terser from '@rollup/plugin-terser';
import license from 'rollup-plugin-license';

/**
* Create a plugin to add an identification banner to the top of stand-alone bundles.
*
* @param title The title to use for the SDK, if not the package name
* @param version The version of the SDK
* @returns An instance of the `rollup-plugin-license` plugin
*/
export function makeLicensePlugin(title) {
export function makeBannerOptions(title, version) {
const commitHash = childProcess.execSync('git rev-parse --short HEAD', { encoding: 'utf-8' }).trim();

const plugin = license({
banner: {
content: `/*! <%= data.title %> <%= pkg.version %> (${commitHash}) | https://github.com/getsentry/sentry-javascript */`,
data: { title },
},
});

// give it a nicer name for later, when we'll need to sort the plugins
plugin.name = 'license';

return plugin;
return `/*! ${title} ${version} (${commitHash}) | https://github.com/getsentry/sentry-javascript */`;
}

/**
* Create a plugin to set the value of the `__SENTRY_DEBUG__` magic string.
*
* @param includeDebugging Whether or not the resulting build should include log statements
* @returns An instance of the `@rollup/plugin-replace` plugin to do the replacement of the magic string with `true` or
* @returns An instance of the `rolldown.replacePlugin` plugin to do the replacement of the magic string with `true` or
* 'false`
*/
export function makeIsDebugBuildPlugin(includeDebugging) {
return replace({
// TODO `preventAssignment` will default to true in version 5.x of the replace plugin, at which point we can get rid
// of this. (It actually makes no difference in this case whether it's true or false, since we never assign to
// `__SENTRY_DEBUG__`, but if we don't give it a value, it will spam with warnings.)
preventAssignment: true,
values: {
return replacePlugin(
{
// Flags in current package
__DEBUG_BUILD__: includeDebugging,
__DEBUG_BUILD__: JSON.stringify(includeDebugging),
// Flags in built monorepo dependencies, from which the bundle pulls
__SENTRY_DEBUG__: includeDebugging,
__SENTRY_DEBUG__: JSON.stringify(includeDebugging),
},
});
{
// TODO `preventAssignment` will default to true in version 5.x of the replace plugin, at which point we can get rid
// of this. (It actually makes no difference in this case whether it's true or false, since we never assign to
// `__SENTRY_DEBUG__`, but if we don't give it a value, it will spam with warnings.)
preventAssignment: true,
},
);
}

export function makeSetSDKSourcePlugin(sdkSource) {
return replace({
preventAssignment: false,
delimiters: ['', ''],
values: {
return replacePlugin(
{
'/* __SENTRY_SDK_SOURCE__ */': `return ${JSON.stringify(sdkSource)};`,
},
});
{
preventAssignment: false,
delimiters: ['', ''],
},
);
}

/**
Expand All @@ -77,13 +69,15 @@ export function makeSetSDKSourcePlugin(sdkSource) {
* @returns An instance of the `replace` plugin to do the replacement of the magic string with `true` or 'false`
*/
export function makeBrowserBuildPlugin(isBrowserBuild) {
return replace({
// TODO This will be the default in the next version of the `replace` plugin
preventAssignment: true,
values: {
__SENTRY_BROWSER_BUNDLE__: isBrowserBuild,
return replacePlugin(
{
__SENTRY_BROWSER_BUNDLE__: JSON.stringify(!!isBrowserBuild),
},
});
{
// TODO This will be the default in the next version of the `replace` plugin
preventAssignment: true,
},
);
}

// `terser` options reference: https://github.com/terser/terser#api-reference
Expand Down Expand Up @@ -146,12 +140,3 @@ export function makeTerserPlugin() {
},
});
}

// We don't pass these plugins any options which need to be calculated or changed by us, so no need to wrap them in
// another factory function, as they are themselves already factory functions.

export function makeNodeResolvePlugin() {
return nodeResolve();
}

export { commonjs as makeCommonJSPlugin };
7 changes: 4 additions & 3 deletions dev-packages/rollup-utils/plugins/make-esm-plugin.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from 'node:fs';
import path from 'node:path';

/**
* Outputs a package.json file with {type: module} in the root of the output directory so that Node
Expand All @@ -11,9 +12,9 @@ export function makePackageNodeEsm() {
// We need to keep the `sideEffects` value from the original package.json,
// as e.g. webpack seems to depend on this
// without this, tree shaking does not work as expected
const packageJSONPath = (await this.resolve('package.json')).id;

const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8'));
const packageJSON = JSON.parse(
fs.readFileSync(path.resolve(process.cwd(), './package.json'), { encoding: 'utf8' }),
);
const sideEffects = packageJSON.sideEffects;
// For module federation we need to keep the version of the package
const version = packageJSON.version;
Expand Down
Loading
Loading