From 7f1bf27ad94daaef254a48fe51e98094d558fcf9 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 7 Apr 2026 14:43:54 +0000 Subject: [PATCH 1/2] Add ESM build output for better tree-shaking support Add a new ESM build target alongside existing UMD builds to enable modern bundlers (Vite, Rollup, esbuild, webpack 5) to effectively tree-shake the SDK. Changes: - Add webpack.esm.config.js for ES module bundle output - Add .babelrc.esm.js with modules: false to preserve ES imports/exports - Add "module" and "exports" fields to package.json for conditional module resolution - Add build:esm script and include it in prepublishOnly The ESM bundle is published as index.esm.js. Existing UMD builds (index.js for browser, index.node.js for Node) are unchanged. Closes #488 https://claude.ai/code/session_015bHPvFJoZHQomDKESZ9tfL --- .babelrc.esm.js | 23 ++++++++++++++ package.json | 15 ++++++++- webpack.esm.config.js | 73 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 .babelrc.esm.js create mode 100644 webpack.esm.config.js diff --git a/.babelrc.esm.js b/.babelrc.esm.js new file mode 100644 index 00000000..8c94d00e --- /dev/null +++ b/.babelrc.esm.js @@ -0,0 +1,23 @@ +module.exports = { + babelrc: false, + configFile: false, + presets: [ + ['@babel/preset-env', { modules: false }], + '@babel/preset-typescript' + ], + ignore: ['**/*.test.ts', '**/*.test.tsx', '**/*.spec.ts', '**/*.spec.ts'], + plugins: [ + '@babel/proposal-class-properties', + '@babel/proposal-object-rest-spread', + '@babel/plugin-proposal-optional-chaining', + ['@babel/transform-runtime', { regenerator: true }], + '@babel/plugin-transform-nullish-coalescing-operator', + [ + 'module-resolver', + { + root: ['.'], + extensions: ['.ts', '.tsx', '.js', '.jsx', '.es', '.es6', '.mjs'] + } + ] + ] +}; diff --git a/package.json b/package.json index f67df8fd..b07c7ea4 100644 --- a/package.json +++ b/package.json @@ -20,11 +20,23 @@ "typescript" ], "main": "./index.node.js", + "module": "./index.esm.js", "browser": "./index.js", "types": "./dist/index.d.ts", "unpkg": "./index.js", + "exports": { + ".": { + "import": "./index.esm.js", + "require": "./index.node.js", + "browser": "./index.js", + "types": "./dist/index.d.ts", + "default": "./index.node.js" + }, + "./package.json": "./package.json" + }, "files": [ "index.js", + "index.esm.js", "index.d.ts", "index.node.js", "dist/*", @@ -52,12 +64,13 @@ "start:all:react": "concurrently \"yarn start\" \"cd react-example && yarn start\" -n 'module,website' -k", "build": "ttsc && babel src --out-dir ./dist --extensions '.ts,.tsx' && webpack", "build:node": "yarn build --config webpack.node.config.js", + "build:esm": "webpack --config webpack.esm.config.js", "test": "jest --config jest.config.js --coverage", "format": "prettier --write \"src/**/*.{ts,tsx}\" \"src/**/*.{js}\" \"example/src/**/*.{ts,tsx}\" \"example/src/**/*.{js}\" \"react-example/src/**/*.{ts,tsx}\" \"react-example/src/**/*.{js}\" --no-error-on-unmatched-pattern", "lint": "eslint src --ignore-pattern '*.test.*' --ignore-pattern '*.spec.*' --ext '.ts,.tsx'", "typecheck": "ttsc --noEmit true --emitDeclarationOnly false", "check-deps": "madge --extensions js,ts --circular dist", - "prepublishOnly": "yarn lint && yarn typecheck && yarn format && yarn build && yarn build:node", + "prepublishOnly": "yarn lint && yarn typecheck && yarn format && yarn build && yarn build:node && yarn build:esm", "clean": "find . -name \"node_modules\" -exec rm -rf '{}' +" }, "devDependencies": { diff --git a/webpack.esm.config.js b/webpack.esm.config.js new file mode 100644 index 00000000..27e5df09 --- /dev/null +++ b/webpack.esm.config.js @@ -0,0 +1,73 @@ +const path = require('path'); +const env = require('dotenv').config({ path: './.env' }); +const webpack = require('webpack'); +const { version } = require('./package.json'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); + +function getParsedEnv() { + if (!env.error) { + return { + ...env.parsed, + VERSION: version, + IS_EU_ITERABLE_SERVICE: process.env.IS_EU_ITERABLE_SERVICE || false + }; + } + + return { + VERSION: version + }; +} + +module.exports = { + mode: 'production', + entry: './src/index.ts', + experiments: { + outputModule: true + }, + output: { + filename: './index.esm.js', + path: path.resolve(__dirname), + library: { + type: 'module' + } + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': JSON.stringify(getParsedEnv()) + }), + new MiniCssExtractPlugin({ + filename: 'dist/components/style.css' + }) + ], + module: { + rules: [ + { + test: /\.tsx?$/, + use: { + loader: 'babel-loader', + options: require('./.babelrc.esm.js') + }, + exclude: /node_modules/ + }, + { + test: /\.css$/, + use: [MiniCssExtractPlugin.loader, 'css-loader'] + }, + { + test: /\.(png|jpe?g|gif)$/i, + use: [ + { + loader: 'file-loader', + options: { + name: '[name].[ext]', + outputPath: 'dist/assets/' + } + } + ] + } + ] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js', '.css'] + } +}; From 34499c9d0fc06f64a1390ec0c1cdbe79e0b0f33b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 7 Apr 2026 14:45:01 +0000 Subject: [PATCH 2/2] Add index.esm.js to .gitignore The ESM build output should be ignored like the other build artifacts. https://claude.ai/code/session_015bHPvFJoZHQomDKESZ9tfL --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 33fde1a2..d33af4b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ node_modules dist /index.js +/index.esm.js /index.node.js .env coverage