From 599b36f51dc039bf2bc3d85aa59a8b29d5878314 Mon Sep 17 00:00:00 2001 From: Alex Prudhomme <78121423+alexprudhomme@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:48:10 -0400 Subject: [PATCH] fix(atomic-react): remove traces of npm imports (#4581) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://coveord.atlassian.net/browse/KIT-3659 ### This PR main goal is to fix the ESM output in the CDN by removing the traces of npm imports. This is achieved by two things. 1. Bundle all of atomic-react (both esm and cjs module) in rollup. Before esm was bundled with tsc and cjs with rollup. #### before 😆 ```mermaid graph TD; rollup-->CJS; tsc-->ESM; tsc-->types; ``` #### after 😆 ```mermaid graph TD; rollup-->CJS; rollup-->ESM; tsc-->types; ``` This is the current state of the dist folder. ``` dist/ ├── cjs/ │ ├── atomic-react.cjs │ ├── recommendation/ │ │ └── atomic-react.cjs │ └── commerce/ │ └── atomic-react.cjs ├── esm/ │ ├── atomic-react.mjs │ ├── recommendation/ │ │ └── atomic-react.mjs │ └── commerce/ │ └── atomic-react.mjs └── types/ ├── index.d.ts ├── recommendation.index.d.ts ├── commerce.index.d.ts └── components/ └── ... ``` 2. Add @coveo/atomic/loader to the list of cdn externalizations. https://github.com/coveo/ui-kit/pull/4581/files#r1812922022 3. Fix the ouptput in the CDN it now looks something like this for the proper files : image --- package-lock.json | 23 -- packages/atomic-react/package.json | 23 +- packages/atomic-react/project.json | 1 + packages/atomic-react/rollup.config.js | 167 +++++++++++++++ packages/atomic-react/rollup.config.mjs | 197 ------------------ packages/atomic-react/tsconfig.iife.json | 8 - packages/atomic-react/tsconfig.json | 16 +- ...{tsconfig.esm.json => tsconfig.types.json} | 4 +- 8 files changed, 181 insertions(+), 258 deletions(-) create mode 100644 packages/atomic-react/rollup.config.js delete mode 100644 packages/atomic-react/rollup.config.mjs delete mode 100644 packages/atomic-react/tsconfig.iife.json rename packages/atomic-react/{tsconfig.esm.json => tsconfig.types.json} (59%) diff --git a/package-lock.json b/package-lock.json index 9a5a0eb7715..2824742bb60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10889,27 +10889,6 @@ } } }, - "node_modules/@rollup/plugin-replace": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-5.0.5.tgz", - "integrity": "sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "magic-string": "^0.30.3" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, "node_modules/@rollup/plugin-terser": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", @@ -53848,9 +53827,7 @@ "@coveo/release": "1.0.0", "@coveo/rollup-plugin-replace-with-ast": "1.0.0", "@rollup/plugin-commonjs": "^25.0.0", - "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-replace": "^5.0.0", "@rollup/plugin-terser": "0.4.4", "@rollup/plugin-typescript": "^11.0.0", "@types/node": "20.14.12", diff --git a/packages/atomic-react/package.json b/packages/atomic-react/package.json index 07b567cf679..e6c78e7943d 100644 --- a/packages/atomic-react/package.json +++ b/packages/atomic-react/package.json @@ -14,17 +14,16 @@ "clean": "rimraf -rf dist", "build:fixLoaderImportPaths": "node ./scripts/fix-loader-import-paths.js", "build:fixGeneratedImportPaths": "fix-esm-import-path src/components/stencil-generated", - "build:bundles:esm": "tsc -p tsconfig.esm.json", - "build:bundles:iife-cjs": "rollup --config rollup.config.mjs --bundleConfigAsCjs", - "build:bundles": "concurrently \"npm run build:bundles:esm\" \"npm run build:bundles:iife-cjs\"", + "build:bundles": "rollup --config rollup.config.js", + "build:types": "tsc --project tsconfig.types.json", "publish:npm": "npm run-script -w=@coveo/release npm-publish", "publish:bump": "npm run-script -w=@coveo/release bump", "promote:npm:latest": "npm run-script -w=@coveo/release promote-npm-prod", "build:assets": "ncp ../atomic/dist/atomic/assets dist/assets && ncp ../atomic/dist/atomic/lang dist/lang " }, + "module": "./dist/esm/atomic-react.mjs", "main": "./dist/cjs/atomic-react.cjs", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", + "types": "./dist/types/index.d.ts", "files": [ "dist/", "recommendation/", @@ -37,9 +36,7 @@ "@coveo/release": "1.0.0", "@coveo/rollup-plugin-replace-with-ast": "1.0.0", "@rollup/plugin-commonjs": "^25.0.0", - "@rollup/plugin-json": "6.1.0", "@rollup/plugin-node-resolve": "^15.0.0", - "@rollup/plugin-replace": "^5.0.0", "@rollup/plugin-terser": "0.4.4", "@rollup/plugin-typescript": "^11.0.0", "@types/node": "20.14.12", @@ -62,18 +59,18 @@ }, "exports": { ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js", + "types": "./dist/types/index.d.ts", + "import": "./dist/esm/atomic-react.mjs", "require": "./dist/cjs/atomic-react.cjs" }, "./commerce": { - "types": "./dist/commerce.index.d.ts", - "import": "./dist/commerce.index.js", + "types": "./dist/types/commerce.index.d.ts", + "import": "./dist/esm/commerce/atomic-react.mjs", "require": "./dist/cjs/commerce/atomic-react.cjs" }, "./recommendation": { - "types": "./dist/recommendation.index.d.ts", - "import": "./dist/recommendation.index.js", + "types": "./dist/types/recommendation.index.d.ts", + "import": "./dist/esm/recommendation/atomic-react.mjs", "require": "./dist/cjs/recommendation/atomic-react.cjs" } } diff --git a/packages/atomic-react/project.json b/packages/atomic-react/project.json index 7c26443d165..12d21937f6f 100644 --- a/packages/atomic-react/project.json +++ b/packages/atomic-react/project.json @@ -11,6 +11,7 @@ "npm run build:fixLoaderImportPaths", "npm run build:fixGeneratedImportPaths", "npm run build:bundles", + "npm run build:types", "npm run build:assets" ], "parallel": false, diff --git a/packages/atomic-react/rollup.config.js b/packages/atomic-react/rollup.config.js new file mode 100644 index 00000000000..90ce545748a --- /dev/null +++ b/packages/atomic-react/rollup.config.js @@ -0,0 +1,167 @@ +import {nodeResolve} from '@rollup/plugin-node-resolve'; +import typescript from '@rollup/plugin-typescript'; +import {readFileSync} from 'fs'; +import {join, dirname} from 'path'; +import {defineConfig} from 'rollup'; +import nodePolyfills from 'rollup-plugin-polyfill-node'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const isCDN = process.env.DEPLOYMENT_ENVIRONMENT === 'CDN'; + +let headlessVersion; +let atomicVersion; + +if (isCDN) { + console.log('Building for CDN'); + + const headlessPackageJsonPath = join( + __dirname, + '../../packages/headless/package.json' + ); + const atomicPackageJsonPath = join( + __dirname, + '../../packages/atomic/package.json' + ); + + try { + const headlessPackageJson = JSON.parse( + readFileSync(headlessPackageJsonPath, 'utf8') + ); + headlessVersion = 'v' + headlessPackageJson.version; + console.log('Using headless version from package.json:', headlessVersion); + + const atomicPackageJson = JSON.parse( + readFileSync(atomicPackageJsonPath, 'utf8') + ); + atomicVersion = 'v' + atomicPackageJson.version; + console.log('Using atomic version from package.json:', atomicVersion); + } catch (error) { + console.error('Error reading headless package.json:', error); + throw new Error('Error reading headless package.json'); + } +} + +const packageMappings = { + '@coveo/headless/commerce': { + cdn: `/headless/${headlessVersion}/commerce/headless.esm.js`, + }, + '@coveo/headless/insight': { + cdn: `/headless/${headlessVersion}/insight/headless.esm.js`, + }, + '@coveo/headless/recommendation': { + cdn: `/headless/${headlessVersion}/recommendation/headless.esm.js`, + }, + '@coveo/headless/case-assist': { + cdn: `/headless/${headlessVersion}/case-assist/headless.esm.js`, + }, + '@coveo/headless': { + cdn: `/headless/${headlessVersion}/headless.esm.js`, + }, + '@coveo/atomic/loader': { + cdn: `/atomic/${atomicVersion}/loader/index.js`, + }, +}; + +const externalizeDependenciesPlugin = () => { + return { + name: 'externalize-dependencies', + resolveId: (source, _importer, _options) => { + const packageMapping = packageMappings[source]; + + if (packageMapping) { + console.log(`Package cdn import : ${packageMapping.cdn}`); + + return { + id: packageMapping.cdn, + external: 'absolute', + }; + } + + return null; + }, + }; +}; + +/** @type {import('rollup').ExternalOption} */ +const commonExternal = [ + 'react', + 'react-dom', + 'react-dom/client', + 'react-dom/server', + '@coveo/atomic/loader', + '@coveo/headless', + '@coveo/headless/recommendation', + '@coveo/headless/commerce', +]; + +/** @type {import('rollup').ExternalOption} */ +const cdnExternal = [ + 'react', + 'react-dom', + 'react-dom/client', + 'react-dom/server', +]; + +/** @returns {import('rollup').OutputOptions} */ +const outputCJS = ({useCase}) => ({ + file: `dist/cjs/${useCase}atomic-react.cjs`, + format: 'cjs', + sourcemap: true, +}); + +/** @returns {import('rollup').OutputOptions} */ +const outputESM = ({useCase}) => ({ + file: `dist/esm/${useCase}atomic-react.mjs`, + format: 'esm', + sourcemap: true, +}); + +/**@type {import('rollup').InputPluginOption} */ +const plugins = [ + nodePolyfills(), + typescript(), + nodeResolve(), + isCDN && externalizeDependenciesPlugin(), +]; + +export default defineConfig([ + { + input: 'src/index.ts', + output: [outputCJS({useCase: ''})], + external: isCDN ? cdnExternal : commonExternal, + plugins: plugins, + }, + { + input: 'src/index.ts', + output: [outputESM({useCase: ''})], + external: isCDN ? cdnExternal : commonExternal, + plugins: plugins, + }, + { + input: 'src/recommendation.index.ts', + output: [outputCJS({useCase: 'recommendation/'})], + external: isCDN ? cdnExternal : commonExternal, + plugins: plugins, + }, + { + input: 'src/recommendation.index.ts', + output: [outputESM({useCase: 'recommendation/'})], + external: isCDN ? cdnExternal : commonExternal, + plugins: plugins, + }, + { + input: 'src/commerce.index.ts', + output: [outputCJS({useCase: 'commerce/'})], + external: isCDN ? cdnExternal : commonExternal, + plugins: plugins, + }, + { + input: 'src/commerce.index.ts', + output: [outputESM({useCase: 'commerce/'})], + external: isCDN ? cdnExternal : commonExternal, + plugins: plugins, + }, +]); diff --git a/packages/atomic-react/rollup.config.mjs b/packages/atomic-react/rollup.config.mjs deleted file mode 100644 index cc4e9596f95..00000000000 --- a/packages/atomic-react/rollup.config.mjs +++ /dev/null @@ -1,197 +0,0 @@ -import replaceWithASTPlugin from '@coveo/rollup-plugin-replace-with-ast'; -import commonjs from '@rollup/plugin-commonjs'; -import json from '@rollup/plugin-json'; -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import replace from '@rollup/plugin-replace'; -// import terser from '@rollup/plugin-terser'; -import typescript from '@rollup/plugin-typescript'; -import {readFileSync} from 'fs'; -import {join, dirname} from 'path'; -import {defineConfig} from 'rollup'; -import nodePolyfills from 'rollup-plugin-polyfill-node'; -import {fileURLToPath} from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const isCDN = process.env.DEPLOYMENT_ENVIRONMENT === 'CDN'; - -let headlessVersion; - -if (isCDN) { - console.log('Building for CDN'); - - const headlessPackageJsonPath = join( - __dirname, - '../../packages/headless/package.json' - ); - - try { - const headlessPackageJson = JSON.parse( - readFileSync(headlessPackageJsonPath, 'utf8') - ); - headlessVersion = 'v' + headlessPackageJson.version; - console.log('Using headless version from package.json:', headlessVersion); - } catch (error) { - console.error('Error reading headless package.json:', error); - throw new Error('Error reading headless package.json'); - } -} - -function generateReplaceValues() { - return Object.entries(packageMappings).reduce((acc, [find, paths]) => { - acc[find] = paths.cdn; - return acc; - }, {}); -} - -const packageMappings = { - '@coveo/headless/commerce': { - cdn: `/headless/${headlessVersion}/commerce/headless.esm.js`, - }, - '@coveo/headless/insight': { - cdn: `/headless/${headlessVersion}/insight/headless.esm.js`, - }, - '@coveo/headless/recommendation': { - cdn: `/headless/${headlessVersion}/recommendation/headless.esm.js`, - }, - '@coveo/headless/case-assist': { - cdn: `/headless/${headlessVersion}/case-assist/headless.esm.js`, - }, - '@coveo/headless': { - cdn: `/headless/${headlessVersion}/headless.esm.js`, - }, -}; - -// /** @type {import("rollup").GlobalsOption} */ -// const globals = { -// react: 'React', -// 'react-dom': 'ReactDOM', -// 'react-dom/client': 'ReactDOM', -// 'react-dom/server': 'ReactDOMServer', -// '@coveo/atomic': 'CoveoAtomic', -// '@coveo/headless': 'CoveoHeadless', -// }; - -/** @type {import('rollup').ExternalOption} */ -const commonExternal = [ - 'react', - 'react-dom', - 'react-dom/client', - 'react-dom/server', - '@coveo/atomic', - '@coveo/headless', -]; - -// /** @returns {import('rollup').OutputOptions} */ -// const outputIIFE = ({minify}) => ({ -// file: `dist/iife/atomic-react${minify ? '.min' : ''}.js`, -// format: 'iife', -// name: 'CoveoAtomicReact', -// globals, -// plugins: minify ? [terser()] : [], -// }); - -/** @returns {import('rollup').OutputOptions} */ -const outputCJS = ({useCase}) => ({ - file: `dist/cjs/${useCase}atomic-react.cjs`, - format: 'cjs', -}); - -// /** @returns {import('rollup').OutputOptions} */ -// const outputIIFERecs = ({minify}) => ({ -// file: `dist/iife/atomic-react/recommendation${minify ? '.min' : ''}.js`, -// format: 'iife', -// name: 'CoveoAtomicReactRecommendation', -// globals, -// plugins: minify ? [terser()] : [], -// }); - -// /** @returns {import('rollup').OutputOptions} */ -// const outputIIFECommerce = ({minify}) => ({ -// file: `dist/iife/atomic-react/commerce${minify ? '.min' : ''}.js`, -// format: 'iife', -// name: 'CoveoAtomicReactCommerce', -// globals, -// plugins: minify ? [terser()] : [], -// }); - -const plugins = [ - isCDN && - replaceWithASTPlugin({ - replacements: generateReplaceValues(), - }), - json(), - nodePolyfills(), - typescript({tsconfig: 'tsconfig.iife.json'}), - commonjs(), - nodeResolve(), - replace({ - delimiters: ['', ''], - values: { - 'process.env.NODE_ENV': JSON.stringify('dev'), - 'util.TextEncoder();': 'TextEncoder();', - "import { defineCustomElements } from '@coveo/atomic/loader';": '', - 'defineCustomElements();': '', - }, - }), -]; - -const pluginsCJS = [ - json(), - nodePolyfills(), - typescript(), - commonjs(), - nodeResolve(), - replace({ - delimiters: ['', ''], - values: { - 'process.env.NODE_ENV': JSON.stringify('dev'), - 'util.TextEncoder();': 'TextEncoder();', - "import { defineCustomElements } from '@coveo/atomic/loader';": '', - 'defineCustomElements();': '', - }, - }), -]; - -export default defineConfig([ - // { - // input: 'src/index.ts', - // output: [outputIIFE({minify: true}), outputIIFE({minify: false})], - // external: commonExternal, - // plugins, - // }, - { - input: 'src/index.ts', - output: [outputCJS({useCase: ''})], - external: commonExternal, - plugins: pluginsCJS, - }, - // { - // input: 'src/recommendation.index.ts', - // output: [outputIIFERecs({minify: true}), outputIIFERecs({minify: false})], - // external: commonExternal, - // plugins, - // }, - { - input: 'src/recommendation.index.ts', - output: [outputCJS({useCase: 'recommendation/'})], - external: commonExternal, - plugins: pluginsCJS, - }, - // { - // input: 'src/commerce.index.ts', - // output: [ - // outputIIFECommerce({minify: true}), - // outputIIFECommerce({minify: false}), - // ], - // external: commonExternal, - // plugins, - // }, - { - input: 'src/commerce.index.ts', - output: [outputCJS({useCase: 'commerce/'})], - external: commonExternal, - plugins: pluginsCJS, - }, -]); diff --git a/packages/atomic-react/tsconfig.iife.json b/packages/atomic-react/tsconfig.iife.json deleted file mode 100644 index b3ebd30b24e..00000000000 --- a/packages/atomic-react/tsconfig.iife.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "declaration": true, - "module": "es2020", - "outDir": "dist/iife" - } -} diff --git a/packages/atomic-react/tsconfig.json b/packages/atomic-react/tsconfig.json index d715e10e72c..e25f19a5390 100644 --- a/packages/atomic-react/tsconfig.json +++ b/packages/atomic-react/tsconfig.json @@ -1,25 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "allowUnreachableCode": false, - "allowSyntheticDefaultImports": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "esModuleInterop": true, "lib": ["dom", "ES2023"], "moduleResolution": "Bundler", "module": "ES2022", - "noImplicitAny": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "removeComments": false, - "sourceMap": true, "jsx": "react", "target": "ES2022" }, - "include": ["src/**/*.ts", "src/**/*.tsx"], - "exclude": ["**/__tests__/**"], - "compileOnSave": false, - "buildOnSave": false + "include": ["src/**/*.ts", "src/**/*.tsx"] } diff --git a/packages/atomic-react/tsconfig.esm.json b/packages/atomic-react/tsconfig.types.json similarity index 59% rename from packages/atomic-react/tsconfig.esm.json rename to packages/atomic-react/tsconfig.types.json index 04ac54f50fd..1f68f1f2435 100644 --- a/packages/atomic-react/tsconfig.esm.json +++ b/packages/atomic-react/tsconfig.types.json @@ -2,7 +2,7 @@ "extends": "./tsconfig.json", "compilerOptions": { "declaration": true, - "module": "es2020", - "outDir": "dist" + "emitDeclarationOnly": true, + "outDir": "dist/types" } }