Skip to content

Commit

Permalink
Refactor vite-configs to simplify sharing code, expose a config builder
Browse files Browse the repository at this point in the history
  • Loading branch information
nickgros committed Sep 18, 2024
1 parent 002be16 commit 684cb24
Show file tree
Hide file tree
Showing 15 changed files with 780 additions and 187 deletions.
23 changes: 14 additions & 9 deletions apps/SageAccountWeb/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { vitestConfig } from 'vite-config'
import { mergeConfig } from 'vitest/config'
import { ConfigBuilder } from 'vite-config'

export default mergeConfig(vitestConfig, {
test: {
include: ['src/**/*.test.[jt]s?(x)'],
setupFiles: ['src/tests/setupTests.ts'],
environment: 'jsdom', // introduced due to random "ReferenceError: window is not defined" during tests
},
})
const config = new ConfigBuilder()
.setIncludeReactConfig(true)
.setIncludeVitestConfig(true)
.setConfigOverrides({
test: {
include: ['src/**/*.test.[jt]s?(x)'],
setupFiles: ['src/tests/setupTests.ts'],
environment: 'jsdom', // introduced due to random "ReferenceError: window is not defined" during tests
},
})
.build()

export default config
23 changes: 14 additions & 9 deletions apps/synapse-oauth-signin/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { vitestConfig } from 'vite-config'
import { mergeConfig } from 'vitest/config'
import { ConfigBuilder } from 'vite-config'

export default mergeConfig(vitestConfig, {
test: {
include: ['src/test/**/*.test.[jt]s?(x)'],
setupFiles: ['src/test/setupTests.ts'],
environment: 'jsdom', // introduced due to random "ReferenceError: window is not defined" during tests
},
})
const config = new ConfigBuilder()
.setIncludeReactConfig(true)
.setIncludeVitestConfig(true)
.setConfigOverrides({
test: {
include: ['src/test/**/*.test.[jt]s?(x)'],
setupFiles: ['src/test/setupTests.ts'],
environment: 'jsdom', // introduced due to random "ReferenceError: window is not defined" during tests
},
})
.build()

export default config
46 changes: 16 additions & 30 deletions apps/synapse-portal-framework/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,18 @@
import { vitestConfig } from 'vite-config'
import { mergeConfig } from 'vitest/config'
import { ConfigBuilder } from 'vite-config'
import { resolve } from 'path'
export default mergeConfig(vitestConfig, {
build: {
outDir: 'dist',
lib: {
// Could also be a dictionary or array of multiple entry points
entry: resolve(__dirname, 'src/index.ts'),
name: 'SynapsePortalFramework',
// the proper extensions will be added
fileName: 'synapse-portal-framework',

const config = new ConfigBuilder()
.setIncludeReactConfig(true)
.setIncludeLibraryConfig(true)
.setBuildLibEntry(resolve(__dirname, 'src/index.ts'))
.setIncludeVitestConfig(true)
.setConfigOverrides({
test: {
include: ['src/**/*.test.[jt]s?(x)'],
setupFiles: ['src/tests/setupTests.ts'],
environment: 'jsdom',
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['react'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
react: 'React',
},
},
},
},
test: {
include: ['src/**/*.test.[jt]s?(x)'],
setupFiles: ['src/tests/setupTests.ts'],
environment: 'jsdom',
},
})
})
.build()

export default config
45 changes: 17 additions & 28 deletions packages/markdown-it-synapse-table/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,20 @@
import { vitestConfig } from 'vite-config'
import { mergeConfig } from 'vitest/config'
import { resolve } from 'path'
import { externalizeDeps } from 'vite-plugin-externalize-deps'
import dts from 'vite-plugin-dts'
import { ConfigBuilder } from 'vite-config'

export default mergeConfig(vitestConfig, {
build: {
sourcemap: true,
emptyOutDir: true,
outDir: './dist',
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'markdownitSynapseTable',
fileName: 'index',
formats: ['es', 'cjs', 'umd'],
export default new ConfigBuilder()
.setIncludeLibraryConfig(true)
.setBuildLibEntry(resolve(__dirname, 'src/index.ts'))
.setIncludeVitestConfig(true)
.setConfigOverrides({
build: {
lib: {
name: 'markdownitSynapseTable',
formats: ['es', 'cjs', 'umd'],
},
},
},
test: {
globals: true,
include: ['test/**/*.test.[jt]s?(x)'],
},
plugins: [
// Do not bundle any dependencies; the consumer's bundler will resolve and link them.
externalizeDeps(),
// Generate a single type definition file for distribution.
dts({
rollupTypes: true,
}),
],
})
test: {
globals: true,
include: ['test/**/*.test.[jt]s?(x)'],
},
})
.build()
39 changes: 14 additions & 25 deletions packages/synapse-react-client/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,20 @@
import { resolve } from 'path'
import { mergeConfig } from 'vite'
import viteConfig from 'vite-config'
import { externalizeDeps } from 'vite-plugin-externalize-deps'
import dts from 'vite-plugin-dts'
import { ConfigBuilder } from 'vite-config'

/**
* Vite config to generate the ESM & CJS bundles for Synapse React Client.
*/
export default mergeConfig(viteConfig, {
root: '.',
build: {
sourcemap: true,
emptyOutDir: false,
outDir: './dist',
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'SRC',
fileName: 'index',
formats: ['es', 'cjs'],
const config = new ConfigBuilder()
.setIncludeReactConfig(true)
.setIncludeLibraryConfig(true)
.setBuildLibEntry(resolve(__dirname, 'src/index.ts'))
.setConfigOverrides({
root: '.',
build: {
// Do not clean the output directory before building, since we build ESM/CJS and UMD separately.
emptyOutDir: false,
},
},
plugins: [
// Do not bundle any dependencies; the consumer's bundler will resolve and link them.
externalizeDeps(),
// Generate a single type definition file for distribution.
dts({
rollupTypes: true,
}),
],
})
})
.build()

export default config
55 changes: 29 additions & 26 deletions packages/synapse-react-client/vite.config.umd.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { resolve } from 'path'
import { mergeConfig } from 'vite'
import viteConfig from 'vite-config'
import { ConfigBuilder } from 'vite-config'
import { version } from './package.json'

// The set of dependencies that will NOT be included in our UMD bundle. The dependency will be loaded from the global object matching the dependency key's value in this object.
Expand Down Expand Up @@ -35,32 +34,36 @@ const globalExternals = {
* A Vite configuration to create a UMD bundle for Synapse React Client. This bundle is primarily used to include Synapse
* React Client code in the Synapse Web Client, which does not use a JavaScript bundler that could bundle the ES module.
*/
const config = mergeConfig(viteConfig, {
root: '.',
build: {
sourcemap: true,
emptyOutDir: false,
outDir: './dist/umd',
minify: true,
lib: {
entry: resolve(__dirname, 'src/umd.index.ts'),
name: 'SRC',
fileName: () => 'synapse-react-client.production.min.js',
formats: ['umd'],
},
rollupOptions: {
external: Object.keys(globalExternals),
output: {
globals: globalExternals,
banner: `/*! SRC v${version} */`,
assetFileNames: assetInfo => {
if (assetInfo.name === 'style.css')
return 'synapse-react-client.production.min.css'
return assetInfo.name
const config = new ConfigBuilder()
.setIncludeReactConfig(true)
// For our UMD bundle, we don't want to generate types or externalize all dependencies, so don't include the default library config.
.setConfigOverrides({
root: '.',
build: {
sourcemap: true,
emptyOutDir: false,
outDir: './dist/umd',
minify: true,
lib: {
entry: resolve(__dirname, 'src/umd.index.ts'),
name: 'SRC',
fileName: () => 'synapse-react-client.production.min.js',
formats: ['umd'],
},
rollupOptions: {
external: Object.keys(globalExternals),
output: {
globals: globalExternals,
banner: `/*! SRC v${version} */`,
assetFileNames: (assetInfo: { name: string }) => {
if (assetInfo.name === 'style.css')
return 'synapse-react-client.production.min.css'
return assetInfo.name
},
},
},
},
},
})
})
.build()

export default config
1 change: 1 addition & 0 deletions packages/synapse-types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"prepublishOnly": "pnpm install && pnpm nx run @sage-bionetworks/synapse-types:build"
},
"devDependencies": {
"@types/node": "^20.14.10",
"rimraf": "^5.0.5",
"tsup": "^8.0.2",
"typescript": "5.5.2"
Expand Down
2 changes: 2 additions & 0 deletions packages/vite-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"svgo": "^3.2.0",
"typescript": "5.5.2",
"vite": "^5.4.3",
"vite-plugin-dts": "^4.2.1",
"vite-plugin-externalize-deps": "^0.8.0",
"vite-plugin-html": "^3.2.2",
"vite-plugin-node-polyfills": "0.17.0",
"vite-plugin-svgr": "^4.2.0",
Expand Down
77 changes: 77 additions & 0 deletions packages/vite-config/src/ConfigBuilder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { getPluginConfig, PluginConfigOptions } from './pluginConfig.js'
import viteConfig from './vite-config.js'
import { mergeConfig } from 'vitest/config'
import viteLibraryConfig from './vite-library-config.js'
import vitestConfig from './vitest-config.js'

export class ConfigBuilder {
private includeReactConfig = false
private includeLibraryConfig = false
private buildLibEntry: string | string[] | undefined = undefined
private includeVitestConfig = false
private pluginConfigOptions: PluginConfigOptions = {}
private configOverrides: Record<string, any> | null = null

setIncludeReactConfig(includeReactConfig: boolean): ConfigBuilder {
this.includeReactConfig = includeReactConfig
return this
}

setIncludeVitestConfig(includeVitestConfig: boolean): ConfigBuilder {
this.includeVitestConfig = includeVitestConfig
return this
}

setBuildLibEntry(buildLibEntry: string | string[]): ConfigBuilder {
this.buildLibEntry = buildLibEntry
return this
}

setIncludeLibraryConfig(includeLibraryConfig: boolean): ConfigBuilder {
this.includeLibraryConfig = includeLibraryConfig
return this
}

setPluginConfigOptions(
pluginConfigOptions: PluginConfigOptions,
): ConfigBuilder {
this.pluginConfigOptions = pluginConfigOptions
return this
}

setConfigOverrides(configOverrides: Record<string, any>): ConfigBuilder {
this.configOverrides = configOverrides
return this
}

build() {
let config = viteConfig
if (this.includeLibraryConfig) {
if (!this.buildLibEntry) {
throw new Error(
'buildLibEntry must be provided when includeLibraryConfig is true',
)
}
config = mergeConfig(config, viteLibraryConfig)
config = mergeConfig(config, {
build: { lib: { entry: this.buildLibEntry } },
})
}
if (this.includeVitestConfig) {
config = mergeConfig(config, vitestConfig)
}
if (this.pluginConfigOptions) {
config = mergeConfig(config, {
plugins: getPluginConfig({
includeReactPlugins: this.includeReactConfig,
includeLibraryPlugins: this.includeLibraryConfig,
}),
})
}
if (this.configOverrides) {
config = mergeConfig(config, this.configOverrides)
}

return config
}
}
10 changes: 9 additions & 1 deletion packages/vite-config/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import viteConfig from './vite-config.js'
import vitestConfig from './vitest-config.js'
import portalsViteConfig from './portals-vite-config.js'
import viteLibraryConfig from './vite-library-config.js'
import { ConfigBuilder } from './ConfigBuilder.js'

export { viteConfig, vitestConfig, portalsViteConfig }
export {
viteConfig,
vitestConfig,
portalsViteConfig,
viteLibraryConfig,
ConfigBuilder,
}

export default viteConfig
Loading

0 comments on commit 684cb24

Please sign in to comment.