Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/blue-laws-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lg-charts/legend': minor
---

Updated `@lg-charts/legend` package build configuration to generate both non-minified and minified bundles. The default export is now the non-minified bundle, with the minified bundle provided as a production-specific export.
9 changes: 9 additions & 0 deletions .changeset/breezy-groups-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@lg-tools/build': minor
---

Added a new exported `modernDevProdConfig` Rollup configuration, designed for component packages.

This configuration generates both minified and non-minified bundles to support production and development environments respectively. Please update the `exports` field in your `package.json` to include a `browser.production` entry for both `import` and `require` that points to the minified bundle (`[bundle-name]-min.js`). This ensures that consumers’ build tools use the optimized, minified bundle in production automatically.

The charts/legend package is the initial adopter of this configuration and is a good example of how to use this new configuration.
14 changes: 12 additions & 2 deletions charts/legend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,18 @@
".": {
"types": "./dist/types/index.d.ts",
"types@<=5.0": "./dist/types/ts4.9/index.d.ts",
"import": "./dist/esm/index.js",
"require": "./dist/umd/index.js"
"import": {
"browser": {
"production": "./dist/esm/index-min.js"
},
"default": "./dist/esm/index.js"
Comment on lines +44 to +48
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember: is import.browser.production necessary? Or can we just have import.production?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried import.production first, but the build:production script of MMS did not pick it up. Seems like it's a necessary structure to have the bundler use it.

},
"require": {
"browser": {
"production": "./dist/umd/index-min.js"
},
"default": "./dist/umd/index.js"
}
Comment on lines +44 to +55
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For all my complaining about updating package.json files, I missed that this is necessary to get the dev builds. At least this is optional now though.

We should open a ticket to roll this out across the codebase

Copy link
Collaborator Author

@nima-taheri-mongodb nima-taheri-mongodb Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll create a ticket.
It's a quick job, except icon package that needs a bit of scripting.
I have good context, I can take that on and do it in a day. (not wise to say that ever 😂)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created two sub-tasks for the existing story.

  1. Experiment on a package | LG-5764
  2. Use the finalized approach on all packages | LG-5765

}
},
"typesVersions": {}
Expand Down
6 changes: 6 additions & 0 deletions charts/legend/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {
storiesConfig,
modernDevProdConfig,
} from '@lg-tools/build/config/rollup.config.mjs';

export default [storiesConfig, modernDevProdConfig];
19 changes: 13 additions & 6 deletions packages/icon/scripts/build/build-batch.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* eslint-disable no-console */
import { MergedRollupOptions, rollup } from 'rollup';
import { InputPluginOption, rollup, type RollupOptions } from 'rollup';

import { GENERATED_DIR } from './constants';

async function getBatchBuildOptions(
batch: Array<string>,
): Promise<Array<MergedRollupOptions>> {
): Promise<Array<RollupOptions>> {
const { constructUMDGlobalName } = await import(
'@lg-tools/build/config/utils/constructUMDGlobalName.mjs'
);
Expand All @@ -21,11 +21,11 @@ async function getBatchBuildOptions(
{
...esmConfig,
input: batch.map(icon => `${GENERATED_DIR}/${icon}.tsx`),
output: [esmConfig.output],
output: esmConfig.output,
plugins: [
// Ensure @emotion packages are externalized (not bundled into icons)
nodeExternals({ deps: true, include: [/@emotion/] }),
...esmConfig.plugins,
...(esmConfig.plugins as Array<InputPluginOption>),
],
},
// UMD builds need a single input file
Expand All @@ -43,7 +43,7 @@ async function getBatchBuildOptions(
plugins: [
// Ensure @emotion packages are externalized (not bundled into icons)
nodeExternals({ deps: true, include: [/@emotion/] }),
...umdConfig.plugins,
...(umdConfig.plugins as Array<InputPluginOption>),
],
};
}),
Expand All @@ -64,7 +64,14 @@ export async function buildBatch(
for (const config of rollupConfigs) {
const bundle = await rollup(config);

await Promise.all(config.output.map(bundle.write));
if (config.output) {
const outputs = Array.isArray(config.output)
? config.output
: [config.output];

await Promise.all(outputs.map(bundle.write));
}

await bundle.close();
}
} catch (e) {
Expand Down
1 change: 1 addition & 0 deletions packages/icon/scripts/build/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ async function buildIcons(options: BuildIconOptions): Promise<void> {

new Command()
.description('Split icon files into batches for bundling in parallel')
.option('-f, --force', 'Force build all icons', false)
.option('-v, --verbose', 'Enable verbose output', false)
.action(buildIcons)
.parse();
161 changes: 108 additions & 53 deletions tools/build/config/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getUMDGlobals } from './utils/getUMDGlobals.mjs';
import { defaultsDeep } from 'lodash-es';

const extensions = ['.ts', '.tsx'];
const testUtilsFilename = 'src/testing/index.ts';
const testBundleGlob = 'src/testing/index.ts';
const storyGlob = 'src/*.stor{y,ies}.tsx';

const babelConfigPath = fileURLToPath(
Expand All @@ -33,43 +33,57 @@ const moduleFormatToDirectory = {
umd: 'dist/umd',
};

const doTestUtilsExist = glob.sync(testUtilsFilename).length > 0;
/**
* @param {{ format: import('rollup').OutputOptions['format'], useTerser?: boolean, outputFile?: string, outputName?: string, outputDir?: string }} options
* @returns {import('rollup').OutputOptions}
*/
const createOutput = ({
format,
useTerser = false,
outputFile = undefined,
outputName = '[name].js',
outputDir = moduleFormatToDirectory[format],
}) => {
return {
dir: outputDir,
file: outputFile,
name,
format,
sourcemap: true,
globals: format === 'umd' ? getUMDGlobals() : {},
validate: true,
interop: 'compat', // https://rollupjs.org/configuration-options/#output-interop
entryFileNames: outputName,
plugins: useTerser ? [terser()] : [],
};
};

/**
*
* @param {'esm' | 'umd'} format
* @param {*} overrides
* @returns
* @param {import('rollup').RollupOptions['output']} output
* @param {Partial<import('rollup').RollupOptions>} [overrides]
* @returns {import('rollup').RollupOptions}
*/
const createConfigForFormat = (format, overrides) => {
const createConfigForFormat = (output, overrides = {}) => {
/** @type {import('@rollup/plugin-babel').RollupBabelInputPluginOptions} */
const babelOptions = {
babelrc: false,
babelHelpers: 'bundled',
extensions,
configFile: babelConfigPath,
sourceMaps: true,
envName: 'production',
};

/** @type {import('rollup').RollupOptions} */
const formatConfig = {
input: ['src/index.ts'],
output: {
dir: moduleFormatToDirectory[format],
name,
format,
sourcemap: true,
globals: format === 'umd' ? getUMDGlobals() : {},
validate: true,
interop: 'compat', // https://rollupjs.org/configuration-options/#output-interop
},
output,
plugins: [
nodePolyfills(),
nodeExternals({ deps: true }),
nodeResolve({ extensions }),

babel({
babelrc: false,
babelHelpers: 'bundled',
extensions,
configFile: babelConfigPath,
sourceMaps: 'inline',
envName: 'production',
}),

babel(babelOptions),
svgr(),

terser(),
],
external,
strictDeprecations: true,
Expand All @@ -83,44 +97,85 @@ const createConfigForFormat = (format, overrides) => {
return finalConfig;
};

const esmConfig = createConfigForFormat('esm');
const umdConfig = createConfigForFormat('umd');
// 1. Create the default esm/umd bundles configs
const esmConfig = createConfigForFormat(
createOutput({ format: 'esm', useTerser: true }),
);
const umdConfig = createConfigForFormat(
createOutput({ format: 'umd', useTerser: true }),
);

const defaultConfig = [esmConfig, umdConfig];

// Add additional entry point to UMD build for test-utils if they exist
doTestUtilsExist &&
// 1.1. Create the modern dev/prod bundle configs
const modernDevProdConfig = createConfigForFormat([
createOutput({ format: 'esm' }),
createOutput({ format: 'umd' }),
createOutput({
format: 'esm',
useTerser: true,
outputName: '[name]-min.js',
}),
createOutput({
format: 'umd',
useTerser: true,
outputName: '[name]-min.js',
}),
]);

// 2. Create testing bundles (if applicable)
const testingBundleEntryPoints = glob.sync(testBundleGlob);

if (testingBundleEntryPoints.length > 0) {
defaultConfig.push(
createConfigForFormat('esm', {
input: testUtilsFilename,
output: {
dir: `${moduleFormatToDirectory['esm']}/testing`,
createConfigForFormat(
createOutput({
format: 'esm',
useTerser: true,
outputDir: `${moduleFormatToDirectory['esm']}/testing`,
}),
{
input: testingBundleEntryPoints,
},
}),
createConfigForFormat('umd', {
input: testUtilsFilename,
output: {
dir: `${moduleFormatToDirectory['umd']}/testing`,
),
createConfigForFormat(
createOutput({
format: 'umd',
useTerser: true,
outputDir: `${moduleFormatToDirectory['umd']}/testing`,
}),
{
input: testingBundleEntryPoints,
},
}),
),
);
}

// 3. Create stories bundles (if applicable)

const storiesEntryPoints = glob.sync(storyGlob);

// FIXME: Figure out a way to get rid of this.
// Creates a super-hacky `stories` bundle
const storiesExist = glob.sync(storyGlob).length > 0;
const storiesConfig = {
...esmConfig,
input: glob.sync(storyGlob)[0],
output: {
format: 'esm',
file: 'stories.js',
const storiesConfig = createConfigForFormat(
{
...createOutput({
format: 'esm',
useTerser: true,
outputDir: null,
outputFile: 'stories.js',
}),
sourcemap: false,
globals: esmConfig.output.globals,
},
};
{
input: storiesEntryPoints[0],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a no change, we're ignoring all stories except the first one. doesn't feel right 😁 where do we use this?

},
);

storiesExist && defaultConfig.push(storiesConfig);
if (storiesEntryPoints.length > 0) {
defaultConfig.push(storiesConfig);
}

export { esmConfig, storiesConfig, umdConfig };
export { modernDevProdConfig, esmConfig, storiesConfig, umdConfig };

export default defaultConfig;
Loading