diff --git a/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap b/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap index c6f479f6af860..80ac4eabd74b5 100644 --- a/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap +++ b/packages/vite/src/generators/configuration/__snapshots__/configuration.spec.ts.snap @@ -10,6 +10,7 @@ exports[`@nrwl/vite:configuration library mode should add config for building li import { join } from 'path'; export default defineConfig({ + cacheDir: '../node_modules/.vite/my-lib', @@ -67,6 +68,7 @@ exports[`@nrwl/vite:configuration library mode should set up non buildable libra import { join } from 'path'; export default defineConfig({ + cacheDir: '../../node_modules/.vite/react-lib-nonb-jest', @@ -190,7 +192,7 @@ import { defineConfig } from 'vite'; // Configuration for building your library. // See: https://vitejs.dev/guide/build.html#library-mode - build: { + cacheDir: '../../node_modules/.vite/react-lib-nonb-vitest',build: { lib: { // Could also be a dictionary or array of multiple entry points. entry: 'src/index.ts', @@ -382,6 +384,7 @@ exports[`@nrwl/vite:configuration transform React app to use Vite should create export default defineConfig({ + cacheDir: '../../node_modules/.vite/my-test-react-app', server:{ port: 4200, @@ -546,6 +549,7 @@ exports[`@nrwl/vite:configuration transform Web app to use Vite should create vi export default defineConfig({ + cacheDir: '../../node_modules/.vite/my-test-web-app', server:{ port: 4200, @@ -699,6 +703,7 @@ exports[`@nrwl/vite:configuration vitest should create a vitest configuration if export default defineConfig({ + cacheDir: '../../node_modules/.vite/my-test-react-app', server:{ port: 4200, diff --git a/packages/vite/src/generators/vitest/__snapshots__/vitest.spec.ts.snap b/packages/vite/src/generators/vitest/__snapshots__/vitest.spec.ts.snap index b498c4ef5ecfe..f974d110cf105 100644 --- a/packages/vite/src/generators/vitest/__snapshots__/vitest.spec.ts.snap +++ b/packages/vite/src/generators/vitest/__snapshots__/vitest.spec.ts.snap @@ -9,6 +9,7 @@ exports[`vitest generator insourceTests should add the insourceSource option in export default defineConfig({ + cacheDir: '../../node_modules/.vite/my-test-react-app', @@ -54,6 +55,7 @@ exports[`vitest generator vite.config should create correct vite.config.ts file export default defineConfig({ + cacheDir: '../../node_modules/.vite/my-test-react-app', @@ -97,6 +99,7 @@ exports[`vitest generator vite.config should create correct vite.config.ts file export default defineConfig({ + cacheDir: '../../node_modules/.vite/react-lib-nonb-jest', diff --git a/packages/vite/src/utils/__snapshots__/vite-config-edit-utils.spec.ts.snap b/packages/vite/src/utils/__snapshots__/vite-config-edit-utils.spec.ts.snap index af488af0c5b0e..918d06fd87eff 100644 --- a/packages/vite/src/utils/__snapshots__/vite-config-edit-utils.spec.ts.snap +++ b/packages/vite/src/utils/__snapshots__/vite-config-edit-utils.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ensureBuildOptionsInViteConfig should add build and test options if defineConfig is empty 1`] = ` +exports[`ensureViteConfigIsCorrect should add build and test options if defineConfig is empty 1`] = ` "import dts from 'vite-plugin-dts'; import { join } from 'path'; @@ -49,7 +49,7 @@ import { join } from 'path'; " `; -exports[`ensureBuildOptionsInViteConfig should add build option but not update test option if test already setup 1`] = ` +exports[`ensureViteConfigIsCorrect should add build option but not update test option if test already setup 1`] = ` "import dts from 'vite-plugin-dts'; import { join } from 'path'; import { defineConfig } from 'vite'; @@ -89,6 +89,7 @@ import { defineConfig } from 'vite'; ], test: { + ...{ globals: true, cache: { dir: '../../node_modules/.vitest', @@ -96,12 +97,14 @@ import { defineConfig } from 'vite'; environment: 'jsdom', include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], }, + ...{\\"globals\\":true,\\"cache\\":{\\"dir\\":\\"../node_modules/.vitest\\"},\\"environment\\":\\"jsdom\\",\\"include\\":[\\"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\\"]} + }, }); " `; -exports[`ensureBuildOptionsInViteConfig should add build options if build options don't exist 1`] = ` +exports[`ensureViteConfigIsCorrect should add build options if build options don't exist 1`] = ` "import dts from 'vite-plugin-dts'; import { join } from 'path'; import { defineConfig } from 'vite'; @@ -141,6 +144,7 @@ import { defineConfig } from 'vite'; ], test: { + ...{ globals: true, cache: { dir: '../../node_modules/.vitest', @@ -148,12 +152,14 @@ import { defineConfig } from 'vite'; environment: 'jsdom', include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], }, + ...{\\"globals\\":true,\\"cache\\":{\\"dir\\":\\"../node_modules/.vitest\\"},\\"environment\\":\\"jsdom\\",\\"include\\":[\\"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\\"]} + }, }); " `; -exports[`ensureBuildOptionsInViteConfig should add build options if defineConfig is not used 1`] = ` +exports[`ensureViteConfigIsCorrect should add build options if defineConfig is not used 1`] = ` "import dts from 'vite-plugin-dts'; import { join } from 'path'; import { defineConfig } from 'vite'; @@ -202,7 +208,7 @@ import { defineConfig } from 'vite'; " `; -exports[`ensureBuildOptionsInViteConfig should add build options if it is using conditional config - do nothing for test 1`] = ` +exports[`ensureViteConfigIsCorrect should add build options if it is using conditional config - do nothing for test 1`] = ` " /// import { defineConfig } from 'vite'; @@ -225,7 +231,7 @@ exports[`ensureBuildOptionsInViteConfig should add build options if it is using " `; -exports[`ensureBuildOptionsInViteConfig should add new build options if some build options already exist 1`] = ` +exports[`ensureViteConfigIsCorrect should add new build options if some build options already exist 1`] = ` "import dts from 'vite-plugin-dts'; import { join } from 'path'; import { defineConfig } from 'vite'; @@ -248,6 +254,7 @@ import { defineConfig } from 'vite'; ], test: { + ...{ globals: true, cache: { dir: '../../node_modules/.vitest', @@ -255,6 +262,8 @@ import { defineConfig } from 'vite'; environment: 'jsdom', include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], }, + ...{\\"globals\\":true,\\"cache\\":{\\"dir\\":\\"../node_modules/.vitest\\"},\\"environment\\":\\"jsdom\\",\\"include\\":[\\"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\\"]} + }, build: { ...{ @@ -267,17 +276,18 @@ import { defineConfig } from 'vite'; " `; -exports[`ensureBuildOptionsInViteConfig should not do anything if cannot understand syntax of vite config 1`] = `"console.log('Unknown syntax')"`; +exports[`ensureViteConfigIsCorrect should not do anything if cannot understand syntax of vite config 1`] = `"console.log('Unknown syntax')"`; -exports[`ensureBuildOptionsInViteConfig should not do anything if project has everything setup already 1`] = ` -" - /// - import { defineConfig } from 'vite'; +exports[`ensureViteConfigIsCorrect should not do anything if project has everything setup already 1`] = ` +"import dts from 'vite-plugin-dts'; +import { join } from 'path'; +import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import viteTsConfigPaths from 'vite-tsconfig-paths'; export default defineConfig({ plugins: [ + ...[ dts({ tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'), // Faster builds by skipping tests. Set this to false to enable type checking. @@ -288,10 +298,17 @@ exports[`ensureBuildOptionsInViteConfig should not do anything if project has ev root: '../../../', }), ], + dts({ + tsConfigFilePath: join(__dirname, 'tsconfig.lib.json'), + // Faster builds by skipping tests. Set this to false to enable type checking. + skipDiagnostics: true, + }), + ], // Configuration for building your library. // See: https://vitejs.dev/guide/build.html#library-mode build: { + ...{ lib: { // Could also be a dictionary or array of multiple entry points. entry: 'src/index.ts', @@ -306,8 +323,11 @@ exports[`ensureBuildOptionsInViteConfig should not do anything if project has ev external: ['react', 'react-dom', 'react/jsx-runtime'], }, }, + ...{\\"lib\\":{\\"entry\\":\\"src/index.ts\\",\\"name\\":\\"my-app\\",\\"fileName\\":\\"index\\",\\"formats\\":[\\"es\\",\\"cjs\\"]},\\"rollupOptions\\":{\\"external\\":[\\"'react', 'react-dom', 'react/jsx-runtime'\\"]}} + }, test: { + ...{ globals: true, cache: { dir: '../../../node_modules/.vitest', @@ -315,11 +335,13 @@ exports[`ensureBuildOptionsInViteConfig should not do anything if project has ev environment: 'jsdom', include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], }, + ...{\\"globals\\":true,\\"cache\\":{\\"dir\\":\\"../node_modules/.vitest\\"},\\"environment\\":\\"jsdom\\",\\"include\\":[\\"src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}\\"]} + }, }); " `; -exports[`ensureBuildOptionsInViteConfig should update both test and build options - keep existing settings 1`] = ` +exports[`ensureViteConfigIsCorrect should update both test and build options - keep existing settings 1`] = ` "import dts from 'vite-plugin-dts'; import { join } from 'path'; import { defineConfig } from 'vite'; diff --git a/packages/vite/src/utils/generator-utils.ts b/packages/vite/src/utils/generator-utils.ts index 21f626f281379..c8e4a4bc8041d 100644 --- a/packages/vite/src/utils/generator-utils.ts +++ b/packages/vite/src/utils/generator-utils.ts @@ -14,7 +14,7 @@ import { ViteDevServerExecutorOptions } from '../executors/dev-server/schema'; import { VitePreviewServerExecutorOptions } from '../executors/preview-server/schema'; import { VitestExecutorOptions } from '../executors/test/schema'; import { Schema } from '../generators/configuration/schema'; -import { ensureBuildOptionsInViteConfig } from './vite-config-edit-utils'; +import { ensureViteConfigIsCorrect } from './vite-config-edit-utils'; export type Target = 'build' | 'serve' | 'test' | 'preview'; export type TargetFlags = Partial>; @@ -550,6 +550,10 @@ export function createOrEditViteConfig( // ], // },`; + const cacheDir = `cacheDir: '${offsetFromRoot( + projectConfig.root + )}node_modules/.vite/${options.project}',`; + if (tree.exists(viteConfigPath)) { handleViteConfigFileExists( tree, @@ -560,6 +564,7 @@ export function createOrEditViteConfig( dtsImportLine, pluginOption, testOption, + cacheDir, offsetFromRoot(projectConfig.root), projectAlreadyHasViteTargets ); @@ -574,6 +579,7 @@ export function createOrEditViteConfig( ${dtsImportLine} export default defineConfig({ + ${cacheDir} ${devServerOption} ${previewServerOption} ${pluginOption} @@ -725,6 +731,7 @@ function handleViteConfigFileExists( dtsImportLine: string, pluginOption: string, testOption: string, + cacheDir: string, offsetFromRoot: string, projectAlreadyHasViteTargets?: TargetFlags ) { @@ -757,7 +764,7 @@ function handleViteConfigFileExists( include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], }; - const changed = ensureBuildOptionsInViteConfig( + const changed = ensureViteConfigIsCorrect( tree, viteConfigPath, buildOption, @@ -767,6 +774,7 @@ function handleViteConfigFileExists( pluginOption, testOption, testOptionObject, + cacheDir, projectAlreadyHasViteTargets ); diff --git a/packages/vite/src/utils/vite-config-edit-utils.spec.ts b/packages/vite/src/utils/vite-config-edit-utils.spec.ts index 69aefaadc2707..f30247af9fe88 100644 --- a/packages/vite/src/utils/vite-config-edit-utils.spec.ts +++ b/packages/vite/src/utils/vite-config-edit-utils.spec.ts @@ -18,9 +18,9 @@ import { testOption, testOptionObject, } from './test-files/test-vite-configs'; -import { ensureBuildOptionsInViteConfig } from './vite-config-edit-utils'; +import { ensureViteConfigIsCorrect } from './vite-config-edit-utils'; -describe('ensureBuildOptionsInViteConfig', () => { +describe('ensureViteConfigIsCorrect', () => { let tree: Tree; beforeEach(() => { @@ -29,7 +29,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it("should add build options if build options don't exist", () => { tree.write('apps/my-app/vite.config.ts', noBuildOptions); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, @@ -53,7 +53,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it('should add new build options if some build options already exist', () => { tree.write('apps/my-app/vite.config.ts', someBuildOptions); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, @@ -77,7 +77,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it('should add build and test options if defineConfig is empty', () => { tree.write('apps/my-app/vite.config.ts', noContentDefineConfig); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, @@ -101,7 +101,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it('should add build options if it is using conditional config - do nothing for test', () => { tree.write('apps/my-app/vite.config.ts', conditionalConfig); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, @@ -125,7 +125,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it('should add build options if defineConfig is not used', () => { tree.write('apps/my-app/vite.config.ts', configNoDefineConfig); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, @@ -149,7 +149,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it('should not do anything if cannot understand syntax of vite config', () => { tree.write('apps/my-app/vite.config.ts', `console.log('Unknown syntax')`); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, @@ -167,7 +167,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it('should not do anything if project has everything setup already', () => { tree.write('apps/my-app/vite.config.ts', hasEverything); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, @@ -185,7 +185,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it('should add build option but not update test option if test already setup', () => { tree.write('apps/my-app/vite.config.ts', noBuildOptionsHasTestOption); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, @@ -203,7 +203,7 @@ describe('ensureBuildOptionsInViteConfig', () => { it('should update both test and build options - keep existing settings', () => { tree.write('apps/my-app/vite.config.ts', someBuildOptionsSomeTestOption); - ensureBuildOptionsInViteConfig( + ensureViteConfigIsCorrect( tree, 'apps/my-app/vite.config.ts', buildOption, diff --git a/packages/vite/src/utils/vite-config-edit-utils.ts b/packages/vite/src/utils/vite-config-edit-utils.ts index c007289a5475c..0d38b3e33c093 100644 --- a/packages/vite/src/utils/vite-config-edit-utils.ts +++ b/packages/vite/src/utils/vite-config-edit-utils.ts @@ -4,7 +4,7 @@ import ts = require('typescript'); import { tsquery } from '@phenomnomnominal/tsquery'; import { TargetFlags } from './generator-utils'; -export function ensureBuildOptionsInViteConfig( +export function ensureViteConfigIsCorrect( tree: Tree, path: string, buildConfigString: string, @@ -14,6 +14,7 @@ export function ensureBuildOptionsInViteConfig( pluginOption: string, testConfigString: string, testConfigObject: {}, + cacheDir: string, projectAlreadyHasViteTargets?: TargetFlags ): boolean { const fileContent = tree.read(path, 'utf-8'); @@ -45,6 +46,12 @@ export function ensureBuildOptionsInViteConfig( ); } + if (cacheDir?.length) { + updatedContent = handleCacheDirNode( + updatedContent ?? fileContent, + cacheDir + ); + } if (updatedContent) { tree.write(path, updatedContent); return true; @@ -97,7 +104,7 @@ function handleBuildOrTestNode( ); } else { // no test config in conditional config - return undefined; + return updatedFileContent; } } else { const propertyAssignments = tsquery.query( @@ -144,7 +151,7 @@ function handleBuildOrTestNode( }, ]); } catch { - return undefined; + return updatedFileContent; } } } @@ -229,11 +236,13 @@ function transformConditionalConfig( if (serveExists && elseKeywordExists) { // build options live inside the else block - return transformCurrentBuildObject( - returnStatements?.length - 1, - returnStatements, - appFileContent, - buildConfigObject + return ( + transformCurrentBuildObject( + returnStatements?.length - 1, + returnStatements, + appFileContent, + buildConfigObject + ) ?? appFileContent ); } else { // no build options exist yet @@ -256,11 +265,13 @@ function transformConditionalConfig( // it will be the return statement which lives // at the buildExistsExpressionIndex - return transformCurrentBuildObject( - buildExistsExpressionIndex, - returnStatements, - appFileContent, - buildConfigObject + return ( + transformCurrentBuildObject( + buildExistsExpressionIndex, + returnStatements, + appFileContent, + buildConfigObject + ) ?? appFileContent ); } } @@ -367,5 +378,78 @@ function handlePluginNode( } return appFileContent; } - return undefined; + return appFileContent; +} + +function handleCacheDirNode(appFileContent: string, cacheDir: string): string { + const file = tsquery.ast(appFileContent); + const cacheDirNode = tsquery.query( + file, + 'PropertyAssignment:has(Identifier[name="cacheDir"])' + ); + + if (!cacheDirNode?.length || cacheDirNode?.length === 0) { + // cacheDir node does not exist yet + // So make one from scratch + + const foundDefineConfig = tsquery.query( + file, + 'CallExpression:has(Identifier[name="defineConfig"])' + ); + + if (foundDefineConfig.length) { + const conditionalConfig = tsquery.query( + foundDefineConfig[0], + 'ArrowFunction' + ); + + if (conditionalConfig.length) { + // We are NOT transforming the conditional config + // with cacheDir + } else { + const propertyAssignments = tsquery.query( + foundDefineConfig[0], + 'PropertyAssignment' + ); + + if (propertyAssignments.length) { + appFileContent = applyChangesToString(appFileContent, [ + { + type: ChangeType.Insert, + index: propertyAssignments[0].getStart(), + text: cacheDir, + }, + ]); + } else { + appFileContent = applyChangesToString(appFileContent, [ + { + type: ChangeType.Insert, + index: foundDefineConfig[0].getStart() + 14, + text: cacheDir, + }, + ]); + } + } + } else { + // cacheDir option does not exist and defineConfig is not used + // could also potentially be invalid syntax, so try-catch + try { + const defaultExport = tsquery.query(file, 'ExportAssignment'); + const found = tsquery?.query( + defaultExport?.[0], + 'ObjectLiteralExpression' + ); + const startOfObject = found?.[0].getStart(); + appFileContent = applyChangesToString(appFileContent, [ + { + type: ChangeType.Insert, + index: startOfObject + 1, + text: cacheDir, + }, + ]); + } catch {} + } + } + + return appFileContent; }