fix(vite): adjust config generation (#20367)
This commit is contained in:
parent
b9b75a79fc
commit
2c88282e8a
@ -26,11 +26,6 @@
|
|||||||
"description": "Skip type-checking via TypeScript. Skipping type-checking speeds up the build but type errors are not caught.",
|
"description": "Skip type-checking via TypeScript. Skipping type-checking speeds up the build but type errors are not caught.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"base": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Base public path when served in development or production.",
|
|
||||||
"alias": "baseHref"
|
|
||||||
},
|
|
||||||
"configFile": {
|
"configFile": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of the Vite.js configuration file.",
|
"description": "The name of the Vite.js configuration file.",
|
||||||
@ -59,49 +54,6 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
"emptyOutDir": {
|
|
||||||
"description": "When set to false, outputPath will not be emptied during the build process.",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"sourcemap": {
|
|
||||||
"description": "Output sourcemaps. Use 'hidden' for use with error reporting tools without generating sourcemap comment.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"target": {
|
|
||||||
"description": "Browser compatibility target for the final bundle. For more info: https://vitejs.dev/config/build-options.html#build-target",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"minify": {
|
|
||||||
"description": "Output sourcemaps. Use 'hidden' for use with error reporting tools without generating sourcemap comment.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"manifest": {
|
|
||||||
"description": "Output sourcemaps. Use 'hidden' for use with error reporting tools without generating sourcemap comment.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"ssrManifest": {
|
|
||||||
"description": "When set to true, the build will also generate an SSR manifest for determining style links and asset preload directives in production. When the value is a string, it will be used as the manifest file name.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"ssr": {
|
|
||||||
"description": "Produce SSR-oriented build. The value can be a string to directly specify the SSR entry, or true, which requires specifying the SSR entry via rollupOptions.input.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"logLevel": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Adjust console output verbosity.",
|
|
||||||
"enum": ["info", "warn", "error", "silent"]
|
|
||||||
},
|
|
||||||
"mode": { "type": "string", "description": "Mode to run the build in." },
|
|
||||||
"force": {
|
|
||||||
"description": "Force the optimizer to ignore the cache and re-bundle",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"cssCodeSplit": {
|
|
||||||
"description": "Enable/disable CSS code splitting. When enabled, CSS imported in async chunks will be inlined into the async chunk itself and inserted when the chunk is loaded.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"watch": {
|
"watch": {
|
||||||
"description": "Enable re-building when files change.",
|
"description": "Enable re-building when files change.",
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "object" }],
|
"oneOf": [{ "type": "boolean" }, { "type": "object" }],
|
||||||
|
|||||||
@ -27,45 +27,6 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Path to the proxy configuration file.",
|
"description": "Path to the proxy configuration file.",
|
||||||
"x-completion-type": "file"
|
"x-completion-type": "file"
|
||||||
},
|
|
||||||
"port": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "Port to listen on.",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"host": {
|
|
||||||
"description": "Specify which IP addresses the server should listen on.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "object" }],
|
|
||||||
"description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https"
|
|
||||||
},
|
|
||||||
"hmr": {
|
|
||||||
"description": "Enable hot module replacement. For more options, use the 'hmr' option in the Vite configuration file.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"open": {
|
|
||||||
"description": "Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"cors": {
|
|
||||||
"description": "Configure CORS for the dev server.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"logLevel": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Adjust console output verbosity.",
|
|
||||||
"enum": ["info", "warn", "error", "silent"]
|
|
||||||
},
|
|
||||||
"mode": { "type": "string", "description": "Mode to run the server in." },
|
|
||||||
"clearScreen": {
|
|
||||||
"description": "Set to false to prevent Vite from clearing the terminal screen when logging certain messages.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"force": {
|
|
||||||
"description": "Force the optimizer to ignore the cache and re-bundle",
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {},
|
"definitions": {},
|
||||||
|
|||||||
@ -22,29 +22,6 @@
|
|||||||
"description": "Path to the proxy configuration file.",
|
"description": "Path to the proxy configuration file.",
|
||||||
"x-completion-type": "file"
|
"x-completion-type": "file"
|
||||||
},
|
},
|
||||||
"port": { "type": "number", "description": "Port to listen on." },
|
|
||||||
"host": {
|
|
||||||
"description": "Specify which IP addresses the server should listen on.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "object" }],
|
|
||||||
"description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https"
|
|
||||||
},
|
|
||||||
"open": {
|
|
||||||
"description": "Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname.",
|
|
||||||
"oneOf": [{ "type": "boolean" }, { "type": "string" }]
|
|
||||||
},
|
|
||||||
"logLevel": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Adjust console output verbosity.",
|
|
||||||
"enum": ["info", "warn", "error", "silent"]
|
|
||||||
},
|
|
||||||
"mode": { "type": "string", "description": "Mode to run the server in." },
|
|
||||||
"clearScreen": {
|
|
||||||
"description": "Set to false to prevent Vite from clearing the terminal screen when logging certain messages.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"staticFilePath": {
|
"staticFilePath": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Path where the build artifacts are located. If not provided then it will be infered from the buildTarget executor options as outputPath",
|
"description": "Path where the build artifacts are located. If not provided then it will be infered from the buildTarget executor options as outputPath",
|
||||||
|
|||||||
@ -9,50 +9,12 @@
|
|||||||
"description": "Test using Vitest.",
|
"description": "Test using Vitest.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"config": {
|
"configFile": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The path to the local vitest config",
|
"description": "The path to the local vitest config",
|
||||||
"x-completion-type": "file",
|
"x-completion-type": "file",
|
||||||
"x-completion-glob": "@(vitest|vite).config@(.js|.ts)"
|
"x-completion-glob": "@(vitest|vite).config@(.js|.ts)",
|
||||||
},
|
"aliases": ["config"]
|
||||||
"passWithNoTests": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true,
|
|
||||||
"description": "Pass the test even if no tests are found"
|
|
||||||
},
|
|
||||||
"testNamePattern": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Run tests with full names matching the pattern"
|
|
||||||
},
|
|
||||||
"mode": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["test", "benchmark", "typecheck"],
|
|
||||||
"default": "test",
|
|
||||||
"description": "The mode that vitest will run on",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"watch": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"description": "Enable watch mode"
|
|
||||||
},
|
|
||||||
"reporters": {
|
|
||||||
"type": "array",
|
|
||||||
"items": { "type": "string" },
|
|
||||||
"description": "An array of reporters to pass to vitest"
|
|
||||||
},
|
|
||||||
"update": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"alias": "u",
|
|
||||||
"description": "Update snapshots",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"coverage": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"description": "Enable coverage report",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
},
|
||||||
"reportsDirectory": {
|
"reportsDirectory": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -62,6 +24,10 @@
|
|||||||
"aliases": ["testFile"],
|
"aliases": ["testFile"],
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "type": "string" }
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"watch": {
|
||||||
|
"description": "Watch files for changes and rerun tests related to changed files.",
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [],
|
"required": [],
|
||||||
|
|||||||
@ -38,7 +38,7 @@ describe('Nuxt Plugin', () => {
|
|||||||
it('should test application', async () => {
|
it('should test application', async () => {
|
||||||
const result = runCLI(`test ${app}`);
|
const result = runCLI(`test ${app}`);
|
||||||
expect(result).toContain(`Successfully ran target test for project ${app}`);
|
expect(result).toContain(`Successfully ran target test for project ${app}`);
|
||||||
});
|
}, 150_000);
|
||||||
|
|
||||||
it('should lint application', async () => {
|
it('should lint application', async () => {
|
||||||
const result = runCLI(`lint ${app}`);
|
const result = runCLI(`lint ${app}`);
|
||||||
|
|||||||
@ -6,10 +6,8 @@ import {
|
|||||||
exists,
|
exists,
|
||||||
fileExists,
|
fileExists,
|
||||||
getPackageManagerCommand,
|
getPackageManagerCommand,
|
||||||
killPorts,
|
|
||||||
listFiles,
|
listFiles,
|
||||||
newProject,
|
newProject,
|
||||||
promisifiedTreeKill,
|
|
||||||
readFile,
|
readFile,
|
||||||
readJson,
|
readJson,
|
||||||
removeFile,
|
removeFile,
|
||||||
@ -17,7 +15,6 @@ import {
|
|||||||
runCLI,
|
runCLI,
|
||||||
runCommand,
|
runCommand,
|
||||||
runCLIAsync,
|
runCLIAsync,
|
||||||
runCommandUntil,
|
|
||||||
tmpProjPath,
|
tmpProjPath,
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
@ -32,87 +29,11 @@ describe('Vite Plugin', () => {
|
|||||||
let proj: string;
|
let proj: string;
|
||||||
|
|
||||||
describe('Vite on React apps', () => {
|
describe('Vite on React apps', () => {
|
||||||
describe('convert React webpack app to vite using the vite:configuration generator', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
proj = newProject();
|
|
||||||
runCLI(`generate @nx/react:app ${myApp} --bundler=webpack`);
|
|
||||||
runCLI(`generate @nx/vite:configuration ${myApp}`);
|
|
||||||
});
|
|
||||||
afterEach(() => cleanupProject());
|
|
||||||
|
|
||||||
it('should serve application in dev mode with custom options', async () => {
|
|
||||||
const port = 4212;
|
|
||||||
const p = await runCommandUntil(
|
|
||||||
`run ${myApp}:serve --port=${port} --https=true`,
|
|
||||||
(output) => {
|
|
||||||
return (
|
|
||||||
output.includes('Local:') &&
|
|
||||||
output.includes(`:${port}`) &&
|
|
||||||
output.includes('https')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
await promisifiedTreeKill(p.pid, 'SIGKILL');
|
|
||||||
await killPorts(port);
|
|
||||||
} catch (e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}, 200_000);
|
|
||||||
|
|
||||||
it('should test application', async () => {
|
|
||||||
const result = await runCLIAsync(`test ${myApp}`);
|
|
||||||
expect(result.combinedOutput).toContain(
|
|
||||||
`Successfully ran target test for project ${myApp}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('set up new React app with --bundler=vite option', () => {
|
describe('set up new React app with --bundler=vite option', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
proj = newProject();
|
proj = newProject();
|
||||||
runCLI(`generate @nx/react:app ${myApp} --bundler=vite`);
|
runCLI(`generate @nx/react:app ${myApp} --bundler=vite`);
|
||||||
createFile(`apps/${myApp}/public/hello.md`, `# Hello World`);
|
createFile(`apps/${myApp}/public/hello.md`, `# Hello World`);
|
||||||
updateFile(
|
|
||||||
`apps/${myApp}/src/environments/environment.prod.ts`,
|
|
||||||
`export const environment = {
|
|
||||||
production: true,
|
|
||||||
myTestVar: 'MyProductionValue',
|
|
||||||
};`
|
|
||||||
);
|
|
||||||
updateFile(
|
|
||||||
`apps/${myApp}/src/environments/environment.ts`,
|
|
||||||
`export const environment = {
|
|
||||||
production: false,
|
|
||||||
myTestVar: 'MyDevelopmentValue',
|
|
||||||
};`
|
|
||||||
);
|
|
||||||
|
|
||||||
updateFile(
|
|
||||||
`apps/${myApp}/src/app/app.tsx`,
|
|
||||||
`
|
|
||||||
import { environment } from './../environments/environment';
|
|
||||||
export function App() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h1>{environment.myTestVar}</h1>
|
|
||||||
<p>Welcome ${myApp}!</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default App;
|
|
||||||
`
|
|
||||||
);
|
|
||||||
|
|
||||||
updateJson(join('apps', myApp, 'project.json'), (config) => {
|
|
||||||
config.targets.build.options.fileReplacements = [
|
|
||||||
{
|
|
||||||
replace: `apps/${myApp}/src/environments/environment.ts`,
|
|
||||||
with: `apps/${myApp}/src/environments/environment.prod.ts`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
afterEach(() => cleanupProject());
|
afterEach(() => cleanupProject());
|
||||||
it('should build application', async () => {
|
it('should build application', async () => {
|
||||||
@ -120,14 +41,6 @@ describe('Vite Plugin', () => {
|
|||||||
expect(readFile(`dist/apps/${myApp}/favicon.ico`)).toBeDefined();
|
expect(readFile(`dist/apps/${myApp}/favicon.ico`)).toBeDefined();
|
||||||
expect(readFile(`dist/apps/${myApp}/hello.md`)).toBeDefined();
|
expect(readFile(`dist/apps/${myApp}/hello.md`)).toBeDefined();
|
||||||
expect(readFile(`dist/apps/${myApp}/index.html`)).toBeDefined();
|
expect(readFile(`dist/apps/${myApp}/index.html`)).toBeDefined();
|
||||||
const fileArray = listFiles(`dist/apps/${myApp}/assets`);
|
|
||||||
const mainBundle = fileArray.find((file) => file.endsWith('.js'));
|
|
||||||
expect(readFile(`dist/apps/${myApp}/assets/${mainBundle}`)).toContain(
|
|
||||||
'MyProductionValue'
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
readFile(`dist/apps/${myApp}/assets/${mainBundle}`)
|
|
||||||
).not.toContain('MyDevelopmentValue');
|
|
||||||
rmDist();
|
rmDist();
|
||||||
}, 200_000);
|
}, 200_000);
|
||||||
});
|
});
|
||||||
@ -202,48 +115,7 @@ describe('Vite Plugin', () => {
|
|||||||
}, 200_000);
|
}, 200_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('convert @nx/web webpack app to vite using the vite:configuration generator', () => {
|
100_000;
|
||||||
beforeEach(() => {
|
|
||||||
proj = newProject();
|
|
||||||
runCLI(`generate @nx/web:app ${myApp} --bundler=webpack`);
|
|
||||||
runCLI(`generate @nx/vite:configuration ${myApp}`);
|
|
||||||
});
|
|
||||||
afterEach(() => cleanupProject());
|
|
||||||
it('should build application', async () => {
|
|
||||||
runCLI(`build ${myApp}`);
|
|
||||||
expect(readFile(`dist/apps/${myApp}/index.html`)).toBeDefined();
|
|
||||||
const fileArray = listFiles(`dist/apps/${myApp}/assets`);
|
|
||||||
const mainBundle = fileArray.find((file) => file.endsWith('.js'));
|
|
||||||
expect(
|
|
||||||
readFile(`dist/apps/${myApp}/assets/${mainBundle}`)
|
|
||||||
).toBeDefined();
|
|
||||||
rmDist();
|
|
||||||
}, 200_000);
|
|
||||||
|
|
||||||
it('should serve application in dev mode with custom port', async () => {
|
|
||||||
const port = 4212;
|
|
||||||
const p = await runCommandUntil(
|
|
||||||
`run ${myApp}:serve --port=${port}`,
|
|
||||||
(output) => {
|
|
||||||
return output.includes('Local:') && output.includes(`:${port}`);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
await promisifiedTreeKill(p.pid, 'SIGKILL');
|
|
||||||
await killPorts(port);
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}, 200_000);
|
|
||||||
|
|
||||||
it('should test application', async () => {
|
|
||||||
const result = await runCLIAsync(`test ${myApp}`);
|
|
||||||
expect(result.combinedOutput).toContain(
|
|
||||||
`Successfully ran target test for project ${myApp}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
100_000;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('incremental building', () => {
|
describe('incremental building', () => {
|
||||||
@ -363,6 +235,8 @@ export default App;
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/libs/${lib}',
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
@ -371,14 +245,18 @@ export default App;
|
|||||||
react(),
|
react(),
|
||||||
nxViteTsPaths()
|
nxViteTsPaths()
|
||||||
],
|
],
|
||||||
|
build: {
|
||||||
|
outDir: '../../dist/libs/${lib}',
|
||||||
|
},
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
cache: {
|
cache: {
|
||||||
dir: './node_modules/.vitest',
|
dir: '../../node_modules/.vitest',
|
||||||
},
|
},
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
coverage: {
|
coverage: {
|
||||||
|
reportsDirectory: '../../coverage/libs/${lib}',
|
||||||
provider: "v8",
|
provider: "v8",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
lines: 100,
|
lines: 100,
|
||||||
@ -531,7 +409,7 @@ export default defineConfig({
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: './node_modules/.vite/root-app',
|
cacheDir: '../../node_modules/.vite/root-app',
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
|
|||||||
@ -61,8 +61,8 @@ describe('Web Components Applications with bundler set as vite', () => {
|
|||||||
`dist/apps/${appName}/_should_remove.txt`,
|
`dist/apps/${appName}/_should_remove.txt`,
|
||||||
`dist/apps/_should_not_remove.txt`
|
`dist/apps/_should_not_remove.txt`
|
||||||
);
|
);
|
||||||
runCLI(`build ${appName}`);
|
runCLI(`build ${appName} --emptyOutDir`);
|
||||||
runCLI(`build ${libName}`);
|
runCLI(`build ${libName} --emptyOutDir`);
|
||||||
checkFilesDoNotExist(
|
checkFilesDoNotExist(
|
||||||
`dist/apps/${appName}/_should_remove.txt`,
|
`dist/apps/${appName}/_should_remove.txt`,
|
||||||
`dist/libs/${libName}/_should_remove.txt`
|
`dist/libs/${libName}/_should_remove.txt`
|
||||||
|
|||||||
@ -129,8 +129,12 @@ export default defineVitestConfig({
|
|||||||
cache: {
|
cache: {
|
||||||
dir: '../node_modules/.vitest',
|
dir: '../node_modules/.vitest',
|
||||||
},
|
},
|
||||||
include: ['my-app/src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
|
||||||
environment: 'nuxt',
|
environment: 'nuxt',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/app5176218',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
|
|||||||
@ -54,12 +54,16 @@ export function addVitest(
|
|||||||
export default defineVitestConfig({
|
export default defineVitestConfig({
|
||||||
plugins: [nxViteTsPaths()],
|
plugins: [nxViteTsPaths()],
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
cache: {
|
cache: {
|
||||||
dir: '${projectOffsetFromRoot}node_modules/.vitest',
|
dir: '${projectOffsetFromRoot}node_modules/.vitest',
|
||||||
},
|
},
|
||||||
include: ['${projectRoot}/src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
environment: 'nuxt',
|
||||||
environment: 'nuxt',
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '${projectOffsetFromRoot}coverage/app5176218',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
`
|
`
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import react from '@vitejs/plugin-react';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths()],
|
plugins: [react(), nxViteTsPaths()],
|
||||||
@ -20,6 +21,7 @@ export default defineConfig({
|
|||||||
cache: { dir: '../node_modules/.vitest' },
|
cache: { dir: '../node_modules/.vitest' },
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
coverage: { reportsDirectory: '../coverage/my-lib', provider: 'v8' },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
@ -34,6 +36,7 @@ import * as path from 'path';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
@ -54,6 +57,7 @@ export default defineConfig({
|
|||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
|
outDir: '../dist/my-lib',
|
||||||
lib: {
|
lib: {
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
@ -76,6 +80,11 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/my-lib',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
|
|||||||
@ -40,6 +40,11 @@
|
|||||||
"version": "17.1.0-beta.2",
|
"version": "17.1.0-beta.2",
|
||||||
"description": "Move target defaults",
|
"description": "Move target defaults",
|
||||||
"implementation": "./src/migrations/update-17-1-0/move-target-defaults"
|
"implementation": "./src/migrations/update-17-1-0/move-target-defaults"
|
||||||
|
},
|
||||||
|
"update-vite-config": {
|
||||||
|
"version": "17.2.0-beta.10",
|
||||||
|
"description": "Update vite config.",
|
||||||
|
"implementation": "./src/migrations/update-17-2-0/update-vite-config"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packageJsonUpdates": {
|
"packageJsonUpdates": {
|
||||||
|
|||||||
@ -53,6 +53,7 @@
|
|||||||
"./src/executors/*/schema.json": "./src/executors/*/schema.json",
|
"./src/executors/*/schema.json": "./src/executors/*/schema.json",
|
||||||
"./src/executors/*.impl": "./src/executors/*.impl.js",
|
"./src/executors/*.impl": "./src/executors/*.impl.js",
|
||||||
"./src/executors/*/compat": "./src/executors/*/compat.js",
|
"./src/executors/*/compat": "./src/executors/*/compat.js",
|
||||||
"./plugins/nx-tsconfig-paths.plugin": "./plugins/nx-tsconfig-paths.plugin.js"
|
"./plugins/nx-tsconfig-paths.plugin": "./plugins/nx-tsconfig-paths.plugin.js",
|
||||||
|
"./plugins/rollup-replace-files.plugin": "./plugins/rollup-replace-files.plugin.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,19 @@
|
|||||||
/**
|
/**
|
||||||
* @function replaceFiles
|
* @function replaceFiles
|
||||||
* @param {FileReplacement[]} replacements
|
* @param {FileReplacement[]} replacements
|
||||||
* @return {({name: "rollup-plugin-replace-files", enforce: "pre", Promise<resolveId>})}
|
* @return {({name: "rollup-plugin-replace-files", enforce: "pre" | "post" | undefined, Promise<resolveId>})}
|
||||||
*/
|
*/
|
||||||
export default function replaceFiles(replacements: FileReplacement[]) {
|
export default function replaceFiles(replacements: FileReplacement[]): {
|
||||||
|
name: string;
|
||||||
|
enforce: 'pre' | 'post' | undefined;
|
||||||
|
resolveId(
|
||||||
|
source: any,
|
||||||
|
importer: any,
|
||||||
|
options: any
|
||||||
|
): Promise<{
|
||||||
|
id: string;
|
||||||
|
}>;
|
||||||
|
} {
|
||||||
if (!replacements?.length) {
|
if (!replacements?.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
detectPackageManager,
|
detectPackageManager,
|
||||||
ExecutorContext,
|
ExecutorContext,
|
||||||
|
joinPathFragments,
|
||||||
logger,
|
logger,
|
||||||
|
offsetFromRoot,
|
||||||
stripIndents,
|
stripIndents,
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
getProjectTsConfigPath,
|
getProjectTsConfigPath,
|
||||||
getViteBuildOptions,
|
normalizeViteConfigFilePath,
|
||||||
getViteSharedConfig,
|
|
||||||
} from '../../utils/options-utils';
|
} from '../../utils/options-utils';
|
||||||
import { ViteBuildExecutorOptions } from './schema';
|
import { ViteBuildExecutorOptions } from './schema';
|
||||||
import {
|
import {
|
||||||
@ -18,33 +19,63 @@ import {
|
|||||||
getLockFileName,
|
getLockFileName,
|
||||||
} from '@nx/js';
|
} from '@nx/js';
|
||||||
import { existsSync, writeFileSync } from 'fs';
|
import { existsSync, writeFileSync } from 'fs';
|
||||||
import { resolve } from 'path';
|
import { relative, resolve } from 'path';
|
||||||
import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable';
|
import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable';
|
||||||
import {
|
import {
|
||||||
createBuildableTsConfig,
|
createBuildableTsConfig,
|
||||||
validateTypes,
|
validateTypes,
|
||||||
} from '../../utils/executor-utils';
|
} from '../../utils/executor-utils';
|
||||||
|
import { BuildOptions } from 'vite';
|
||||||
|
|
||||||
export async function* viteBuildExecutor(
|
export async function* viteBuildExecutor(
|
||||||
options: ViteBuildExecutorOptions,
|
options: Record<string, any> & ViteBuildExecutorOptions,
|
||||||
context: ExecutorContext
|
context: ExecutorContext
|
||||||
) {
|
) {
|
||||||
// Allows ESM to be required in CJS modules. Vite will be published as ESM in the future.
|
// Allows ESM to be required in CJS modules. Vite will be published as ESM in the future.
|
||||||
const { mergeConfig, build } = await (Function(
|
const { mergeConfig, build, loadConfigFromFile } = await (Function(
|
||||||
'return import("vite")'
|
'return import("vite")'
|
||||||
)() as Promise<typeof import('vite')>);
|
)() as Promise<typeof import('vite')>);
|
||||||
|
|
||||||
const projectRoot =
|
const projectRoot =
|
||||||
context.projectsConfigurations.projects[context.projectName].root;
|
context.projectsConfigurations.projects[context.projectName].root;
|
||||||
|
|
||||||
createBuildableTsConfig(projectRoot, options, context);
|
createBuildableTsConfig(projectRoot, options, context);
|
||||||
|
|
||||||
const normalizedOptions = normalizeOptions(options);
|
const viteConfigPath = normalizeViteConfigFilePath(
|
||||||
|
context.root,
|
||||||
|
projectRoot,
|
||||||
|
options.configFile
|
||||||
|
);
|
||||||
|
const root =
|
||||||
|
projectRoot === '.'
|
||||||
|
? process.cwd()
|
||||||
|
: relative(context.cwd, joinPathFragments(context.root, projectRoot));
|
||||||
|
|
||||||
|
const { buildOptions, otherOptions } = await getExtraArgs(options);
|
||||||
|
|
||||||
|
const resolved = await loadConfigFromFile(
|
||||||
|
{
|
||||||
|
mode: otherOptions?.mode ?? 'production',
|
||||||
|
command: 'build',
|
||||||
|
},
|
||||||
|
viteConfigPath
|
||||||
|
);
|
||||||
|
|
||||||
|
const outDir =
|
||||||
|
joinPathFragments(offsetFromRoot(projectRoot), options.outputPath) ??
|
||||||
|
resolved?.config?.build?.outDir;
|
||||||
|
|
||||||
const buildConfig = mergeConfig(
|
const buildConfig = mergeConfig(
|
||||||
getViteSharedConfig(normalizedOptions, false, context),
|
|
||||||
{
|
{
|
||||||
build: getViteBuildOptions(normalizedOptions, context),
|
// This should not be needed as it's going to be set in vite.config.ts
|
||||||
|
// but leaving it here in case someone did not migrate correctly
|
||||||
|
root: resolved.config.root ?? root,
|
||||||
|
configFile: viteConfigPath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
build: {
|
||||||
|
outDir,
|
||||||
|
...buildOptions,
|
||||||
|
},
|
||||||
|
...otherOptions,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -60,7 +91,14 @@ export async function* viteBuildExecutor(
|
|||||||
|
|
||||||
const libraryPackageJson = resolve(projectRoot, 'package.json');
|
const libraryPackageJson = resolve(projectRoot, 'package.json');
|
||||||
const rootPackageJson = resolve(context.root, 'package.json');
|
const rootPackageJson = resolve(context.root, 'package.json');
|
||||||
const distPackageJson = resolve(normalizedOptions.outputPath, 'package.json');
|
|
||||||
|
// Here, we want the outdir relative to the workspace root.
|
||||||
|
// So, we calculate the relative path from the workspace root to the outdir.
|
||||||
|
const outDirRelativeToWorkspaceRoot = outDir.replaceAll('../', '');
|
||||||
|
const distPackageJson = resolve(
|
||||||
|
outDirRelativeToWorkspaceRoot,
|
||||||
|
'package.json'
|
||||||
|
);
|
||||||
|
|
||||||
// Generate a package.json if option has been set.
|
// Generate a package.json if option has been set.
|
||||||
if (options.generatePackageJson) {
|
if (options.generatePackageJson) {
|
||||||
@ -83,7 +121,10 @@ export async function* viteBuildExecutor(
|
|||||||
|
|
||||||
builtPackageJson.type = 'module';
|
builtPackageJson.type = 'module';
|
||||||
|
|
||||||
writeJsonFile(`${options.outputPath}/package.json`, builtPackageJson);
|
writeJsonFile(
|
||||||
|
`${outDirRelativeToWorkspaceRoot}/package.json`,
|
||||||
|
builtPackageJson
|
||||||
|
);
|
||||||
const packageManager = detectPackageManager(context.root);
|
const packageManager = detectPackageManager(context.root);
|
||||||
|
|
||||||
const lockFile = createLockFile(
|
const lockFile = createLockFile(
|
||||||
@ -92,7 +133,7 @@ export async function* viteBuildExecutor(
|
|||||||
packageManager
|
packageManager
|
||||||
);
|
);
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
`${options.outputPath}/${getLockFileName(packageManager)}`,
|
`${outDirRelativeToWorkspaceRoot}/${getLockFileName(packageManager)}`,
|
||||||
lockFile,
|
lockFile,
|
||||||
{
|
{
|
||||||
encoding: 'utf-8',
|
encoding: 'utf-8',
|
||||||
@ -107,7 +148,7 @@ export async function* viteBuildExecutor(
|
|||||||
) {
|
) {
|
||||||
await copyAssets(
|
await copyAssets(
|
||||||
{
|
{
|
||||||
outputPath: normalizedOptions.outputPath,
|
outputPath: outDirRelativeToWorkspaceRoot,
|
||||||
assets: [
|
assets: [
|
||||||
{
|
{
|
||||||
input: projectRoot,
|
input: projectRoot,
|
||||||
@ -142,22 +183,66 @@ export async function* viteBuildExecutor(
|
|||||||
} else {
|
} else {
|
||||||
const output = watcherOrOutput?.['output'] || watcherOrOutput?.[0]?.output;
|
const output = watcherOrOutput?.['output'] || watcherOrOutput?.[0]?.output;
|
||||||
const fileName = output?.[0]?.fileName || 'main.cjs';
|
const fileName = output?.[0]?.fileName || 'main.cjs';
|
||||||
const outfile = resolve(normalizedOptions.outputPath, fileName);
|
const outfile = resolve(outDirRelativeToWorkspaceRoot, fileName);
|
||||||
yield { success: true, outfile };
|
yield { success: true, outfile };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeOptions(options: ViteBuildExecutorOptions) {
|
async function getExtraArgs(options: ViteBuildExecutorOptions): Promise<{
|
||||||
const normalizedOptions = { ...options };
|
buildOptions: BuildOptions;
|
||||||
|
otherOptions: Record<string, any>;
|
||||||
// coerce watch to null or {} to match with Vite's watch config
|
}> {
|
||||||
if (options.watch === false) {
|
// support passing extra args to vite cli
|
||||||
normalizedOptions.watch = null;
|
const schema = await import('./schema.json');
|
||||||
} else if (options.watch === true) {
|
const extraArgs = {};
|
||||||
normalizedOptions.watch = {};
|
for (const key of Object.keys(options)) {
|
||||||
|
if (!schema.properties[key]) {
|
||||||
|
extraArgs[key] = options[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalizedOptions;
|
const buildOptions = {} as BuildOptions;
|
||||||
|
const buildSchemaKeys = [
|
||||||
|
'target',
|
||||||
|
'polyfillModulePreload',
|
||||||
|
'modulePreload',
|
||||||
|
'outDir',
|
||||||
|
'assetsDir',
|
||||||
|
'assetsInlineLimit',
|
||||||
|
'cssCodeSplit',
|
||||||
|
'cssTarget',
|
||||||
|
'cssMinify',
|
||||||
|
'sourcemap',
|
||||||
|
'minify',
|
||||||
|
'terserOptions',
|
||||||
|
'rollupOptions',
|
||||||
|
'commonjsOptions',
|
||||||
|
'dynamicImportVarsOptions',
|
||||||
|
'write',
|
||||||
|
'emptyOutDir',
|
||||||
|
'copyPublicDir',
|
||||||
|
'manifest',
|
||||||
|
'lib',
|
||||||
|
'ssr',
|
||||||
|
'ssrManifest',
|
||||||
|
'ssrEmitAssets',
|
||||||
|
'reportCompressedSize',
|
||||||
|
'chunkSizeWarningLimit',
|
||||||
|
'watch',
|
||||||
|
];
|
||||||
|
const otherOptions = {};
|
||||||
|
for (const key of Object.keys(extraArgs)) {
|
||||||
|
if (buildSchemaKeys.includes(key)) {
|
||||||
|
buildOptions[key] = extraArgs[key];
|
||||||
|
} else {
|
||||||
|
otherOptions[key] = extraArgs[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
buildOptions,
|
||||||
|
otherOptions,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default viteBuildExecutor;
|
export default viteBuildExecutor;
|
||||||
|
|||||||
18
packages/vite/src/executors/build/schema.d.ts
vendored
18
packages/vite/src/executors/build/schema.d.ts
vendored
@ -1,23 +1,11 @@
|
|||||||
import type { FileReplacement } from '../../plugins/rollup-replace-files.plugin';
|
import type { FileReplacement } from '../../plugins/rollup-replace-files.plugin';
|
||||||
export interface ViteBuildExecutorOptions {
|
export interface ViteBuildExecutorOptions {
|
||||||
outputPath: string;
|
outputPath?: string;
|
||||||
emptyOutDir?: boolean;
|
skipTypeCheck?: boolean;
|
||||||
base?: string;
|
|
||||||
configFile?: string;
|
configFile?: string;
|
||||||
fileReplacements?: FileReplacement[];
|
fileReplacements?: FileReplacement[];
|
||||||
force?: boolean;
|
watch?: boolean;
|
||||||
sourcemap?: boolean | 'inline' | 'hidden';
|
|
||||||
minify?: boolean | 'esbuild' | 'terser';
|
|
||||||
manifest?: boolean | string;
|
|
||||||
ssrManifest?: boolean | string;
|
|
||||||
logLevel?: 'info' | 'warn' | 'error' | 'silent';
|
|
||||||
mode?: string;
|
|
||||||
ssr?: boolean | string;
|
|
||||||
watch?: object | boolean;
|
|
||||||
target?: string | string[];
|
|
||||||
generatePackageJson?: boolean;
|
generatePackageJson?: boolean;
|
||||||
includeDevDependenciesInPackageJson?: boolean;
|
includeDevDependenciesInPackageJson?: boolean;
|
||||||
cssCodeSplit?: boolean;
|
|
||||||
buildLibsFromSource?: boolean;
|
buildLibsFromSource?: boolean;
|
||||||
skipTypeCheck?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,11 +28,6 @@
|
|||||||
"description": "Skip type-checking via TypeScript. Skipping type-checking speeds up the build but type errors are not caught.",
|
"description": "Skip type-checking via TypeScript. Skipping type-checking speeds up the build but type errors are not caught.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
"base": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Base public path when served in development or production.",
|
|
||||||
"alias": "baseHref"
|
|
||||||
},
|
|
||||||
"configFile": {
|
"configFile": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of the Vite.js configuration file.",
|
"description": "The name of the Vite.js configuration file.",
|
||||||
@ -61,87 +56,6 @@
|
|||||||
},
|
},
|
||||||
"default": []
|
"default": []
|
||||||
},
|
},
|
||||||
"emptyOutDir": {
|
|
||||||
"description": "When set to false, outputPath will not be emptied during the build process.",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true
|
|
||||||
},
|
|
||||||
"sourcemap": {
|
|
||||||
"description": "Output sourcemaps. Use 'hidden' for use with error reporting tools without generating sourcemap comment.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"target": {
|
|
||||||
"description": "Browser compatibility target for the final bundle. For more info: https://vitejs.dev/config/build-options.html#build-target",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"minify": {
|
|
||||||
"description": "Output sourcemaps. Use 'hidden' for use with error reporting tools without generating sourcemap comment.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"manifest": {
|
|
||||||
"description": "Output sourcemaps. Use 'hidden' for use with error reporting tools without generating sourcemap comment.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"ssrManifest": {
|
|
||||||
"description": "When set to true, the build will also generate an SSR manifest for determining style links and asset preload directives in production. When the value is a string, it will be used as the manifest file name.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"ssr": {
|
|
||||||
"description": "Produce SSR-oriented build. The value can be a string to directly specify the SSR entry, or true, which requires specifying the SSR entry via rollupOptions.input.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"logLevel": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Adjust console output verbosity.",
|
|
||||||
"enum": ["info", "warn", "error", "silent"]
|
|
||||||
},
|
|
||||||
"mode": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Mode to run the build in."
|
|
||||||
},
|
|
||||||
"force": {
|
|
||||||
"description": "Force the optimizer to ignore the cache and re-bundle",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"cssCodeSplit": {
|
|
||||||
"description": "Enable/disable CSS code splitting. When enabled, CSS imported in async chunks will be inlined into the async chunk itself and inserted when the chunk is loaded.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"watch": {
|
"watch": {
|
||||||
"description": "Enable re-building when files change.",
|
"description": "Enable re-building when files change.",
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
|
|||||||
@ -1,16 +1,20 @@
|
|||||||
import { ExecutorContext } from '@nx/devkit';
|
import { ExecutorContext, joinPathFragments } from '@nx/devkit';
|
||||||
import type { InlineConfig, ViteDevServer } from 'vite';
|
import {
|
||||||
|
loadConfigFromFile,
|
||||||
|
type InlineConfig,
|
||||||
|
type ViteDevServer,
|
||||||
|
} from 'vite';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getNxTargetOptions,
|
getNxTargetOptions,
|
||||||
getViteBuildOptions,
|
|
||||||
getViteServerOptions,
|
getViteServerOptions,
|
||||||
getViteSharedConfig,
|
normalizeViteConfigFilePath,
|
||||||
} from '../../utils/options-utils';
|
} from '../../utils/options-utils';
|
||||||
|
|
||||||
import { ViteDevServerExecutorOptions } from './schema';
|
import { ViteDevServerExecutorOptions } from './schema';
|
||||||
import { ViteBuildExecutorOptions } from '../build/schema';
|
import { ViteBuildExecutorOptions } from '../build/schema';
|
||||||
import { createBuildableTsConfig } from '../../utils/executor-utils';
|
import { createBuildableTsConfig } from '../../utils/executor-utils';
|
||||||
|
import { relative } from 'path';
|
||||||
|
|
||||||
export async function* viteDevServerExecutor(
|
export async function* viteDevServerExecutor(
|
||||||
options: ViteDevServerExecutorOptions,
|
options: ViteDevServerExecutorOptions,
|
||||||
@ -23,7 +27,10 @@ export async function* viteDevServerExecutor(
|
|||||||
|
|
||||||
const projectRoot =
|
const projectRoot =
|
||||||
context.projectsConfigurations.projects[context.projectName].root;
|
context.projectsConfigurations.projects[context.projectName].root;
|
||||||
|
const root =
|
||||||
|
projectRoot === '.'
|
||||||
|
? process.cwd()
|
||||||
|
: relative(context.cwd, joinPathFragments(context.root, projectRoot));
|
||||||
createBuildableTsConfig(projectRoot, options, context);
|
createBuildableTsConfig(projectRoot, options, context);
|
||||||
|
|
||||||
// Retrieve the option for the configured buildTarget.
|
// Retrieve the option for the configured buildTarget.
|
||||||
@ -31,20 +38,33 @@ export async function* viteDevServerExecutor(
|
|||||||
options.buildTarget,
|
options.buildTarget,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
const viteConfigPath = normalizeViteConfigFilePath(
|
||||||
// Merge the options from the build and dev-serve targets.
|
context.root,
|
||||||
// The latter takes precedence.
|
projectRoot,
|
||||||
const mergedOptions = {
|
buildTargetOptions.configFile
|
||||||
...buildTargetOptions,
|
);
|
||||||
...options,
|
const extraArgs = await getExtraArgs(options);
|
||||||
};
|
const resolved = await loadConfigFromFile(
|
||||||
|
|
||||||
// Add the server specific configuration.
|
|
||||||
const serverConfig: InlineConfig = mergeConfig(
|
|
||||||
getViteSharedConfig(mergedOptions, options.clearScreen, context),
|
|
||||||
{
|
{
|
||||||
build: getViteBuildOptions(mergedOptions, context),
|
mode: extraArgs?.mode ?? 'production',
|
||||||
server: await getViteServerOptions(mergedOptions, context),
|
command: 'build',
|
||||||
|
},
|
||||||
|
viteConfigPath
|
||||||
|
);
|
||||||
|
|
||||||
|
const serverConfig: InlineConfig = mergeConfig(
|
||||||
|
{
|
||||||
|
// This should not be needed as it's going to be set in vite.config.ts
|
||||||
|
// but leaving it here in case someone did not migrate correctly
|
||||||
|
root: resolved.config.root ?? root,
|
||||||
|
configFile: viteConfigPath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
server: {
|
||||||
|
...(await getViteServerOptions(options, context)),
|
||||||
|
...extraArgs,
|
||||||
|
},
|
||||||
|
...extraArgs,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -90,3 +110,18 @@ async function runViteDevServer(server: ViteDevServer): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default viteDevServerExecutor;
|
export default viteDevServerExecutor;
|
||||||
|
|
||||||
|
async function getExtraArgs(
|
||||||
|
options: ViteDevServerExecutorOptions
|
||||||
|
): Promise<InlineConfig> {
|
||||||
|
// support passing extra args to vite cli
|
||||||
|
const schema = await import('./schema.json');
|
||||||
|
const extraArgs = {};
|
||||||
|
for (const key of Object.keys(options)) {
|
||||||
|
if (!schema.properties[key]) {
|
||||||
|
extraArgs[key] = options[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extraArgs as InlineConfig;
|
||||||
|
}
|
||||||
|
|||||||
@ -2,14 +2,4 @@ export interface ViteDevServerExecutorOptions {
|
|||||||
buildTarget: string;
|
buildTarget: string;
|
||||||
buildLibsFromSource?: boolean;
|
buildLibsFromSource?: boolean;
|
||||||
proxyConfig?: string;
|
proxyConfig?: string;
|
||||||
port?: number;
|
|
||||||
host?: string | boolean;
|
|
||||||
https?: boolean | Json;
|
|
||||||
hmr?: boolean;
|
|
||||||
open?: string | boolean;
|
|
||||||
cors?: boolean;
|
|
||||||
logLevel?: 'info' | 'warn' | 'error' | 'silent';
|
|
||||||
mode?: string;
|
|
||||||
clearScreen?: boolean;
|
|
||||||
force?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,69 +30,6 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Path to the proxy configuration file.",
|
"description": "Path to the proxy configuration file.",
|
||||||
"x-completion-type": "file"
|
"x-completion-type": "file"
|
||||||
},
|
|
||||||
"port": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "Port to listen on.",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"host": {
|
|
||||||
"description": "Specify which IP addresses the server should listen on.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https"
|
|
||||||
},
|
|
||||||
"hmr": {
|
|
||||||
"description": "Enable hot module replacement. For more options, use the 'hmr' option in the Vite configuration file.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"open": {
|
|
||||||
"description": "Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"cors": {
|
|
||||||
"description": "Configure CORS for the dev server.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"logLevel": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Adjust console output verbosity.",
|
|
||||||
"enum": ["info", "warn", "error", "silent"]
|
|
||||||
},
|
|
||||||
"mode": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Mode to run the server in."
|
|
||||||
},
|
|
||||||
"clearScreen": {
|
|
||||||
"description": "Set to false to prevent Vite from clearing the terminal screen when logging certain messages.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"force": {
|
|
||||||
"description": "Force the optimizer to ignore the cache and re-bundle",
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {},
|
"definitions": {},
|
||||||
|
|||||||
@ -1,27 +1,30 @@
|
|||||||
import { ExecutorContext, parseTargetString, runExecutor } from '@nx/devkit';
|
import {
|
||||||
|
ExecutorContext,
|
||||||
|
joinPathFragments,
|
||||||
|
offsetFromRoot,
|
||||||
|
parseTargetString,
|
||||||
|
runExecutor,
|
||||||
|
} from '@nx/devkit';
|
||||||
import type { InlineConfig, PreviewServer } from 'vite';
|
import type { InlineConfig, PreviewServer } from 'vite';
|
||||||
import {
|
import {
|
||||||
getNxTargetOptions,
|
getNxTargetOptions,
|
||||||
getViteBuildOptions,
|
|
||||||
getVitePreviewOptions,
|
getVitePreviewOptions,
|
||||||
getViteSharedConfig,
|
normalizeViteConfigFilePath,
|
||||||
} from '../../utils/options-utils';
|
} from '../../utils/options-utils';
|
||||||
import { ViteBuildExecutorOptions } from '../build/schema';
|
import { ViteBuildExecutorOptions } from '../build/schema';
|
||||||
import { VitePreviewServerExecutorOptions } from './schema';
|
import { VitePreviewServerExecutorOptions } from './schema';
|
||||||
|
import { relative } from 'path';
|
||||||
interface CustomBuildTargetOptions {
|
|
||||||
outputPath: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function* vitePreviewServerExecutor(
|
export async function* vitePreviewServerExecutor(
|
||||||
options: VitePreviewServerExecutorOptions,
|
options: VitePreviewServerExecutorOptions,
|
||||||
context: ExecutorContext
|
context: ExecutorContext
|
||||||
) {
|
) {
|
||||||
// Allows ESM to be required in CJS modules. Vite will be published as ESM in the future.
|
// Allows ESM to be required in CJS modules. Vite will be published as ESM in the future.
|
||||||
const { mergeConfig, preview } = await (Function(
|
const { mergeConfig, preview, loadConfigFromFile } = await (Function(
|
||||||
'return import("vite")'
|
'return import("vite")'
|
||||||
)() as Promise<typeof import('vite')>);
|
)() as Promise<typeof import('vite')>);
|
||||||
|
const projectRoot =
|
||||||
|
context.projectsConfigurations.projects[context.projectName].root;
|
||||||
const target = parseTargetString(options.buildTarget, context);
|
const target = parseTargetString(options.buildTarget, context);
|
||||||
const targetConfiguration =
|
const targetConfiguration =
|
||||||
context.projectsConfigurations.projects[target.project]?.targets[
|
context.projectsConfigurations.projects[target.project]?.targets[
|
||||||
@ -36,35 +39,63 @@ export async function* vitePreviewServerExecutor(
|
|||||||
targetConfiguration.executor !== '@nrwl/vite:build';
|
targetConfiguration.executor !== '@nrwl/vite:build';
|
||||||
|
|
||||||
// Retrieve the option for the configured buildTarget.
|
// Retrieve the option for the configured buildTarget.
|
||||||
const buildTargetOptions:
|
const buildTargetOptions: ViteBuildExecutorOptions = getNxTargetOptions(
|
||||||
| ViteBuildExecutorOptions
|
|
||||||
| CustomBuildTargetOptions = getNxTargetOptions(
|
|
||||||
options.buildTarget,
|
options.buildTarget,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
const viteConfigPath = normalizeViteConfigFilePath(
|
||||||
|
context.root,
|
||||||
|
projectRoot,
|
||||||
|
buildTargetOptions.configFile
|
||||||
|
);
|
||||||
|
const extraArgs = await getExtraArgs(options);
|
||||||
|
const resolved = await loadConfigFromFile(
|
||||||
|
{
|
||||||
|
mode: extraArgs?.mode ?? 'production',
|
||||||
|
command: 'build',
|
||||||
|
},
|
||||||
|
viteConfigPath
|
||||||
|
);
|
||||||
|
|
||||||
const outputPath = options.staticFilePath ?? buildTargetOptions.outputPath;
|
const outDir =
|
||||||
|
options.staticFilePath ??
|
||||||
|
joinPathFragments(
|
||||||
|
offsetFromRoot(projectRoot),
|
||||||
|
buildTargetOptions.outputPath
|
||||||
|
) ??
|
||||||
|
resolved?.config?.build?.outDir;
|
||||||
|
|
||||||
if (!outputPath) {
|
if (!outDir) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not infer the "outputPath". It should either be a property of the "${options.buildTarget}" buildTarget or provided explicitly as a "staticFilePath" option.`
|
`Could not infer the "outputPath" or "outDir". It should be set in your vite.config.ts, or as a property of the "${options.buildTarget}" buildTarget or provided explicitly as a "staticFilePath" option.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const root =
|
||||||
|
projectRoot === '.'
|
||||||
|
? process.cwd()
|
||||||
|
: relative(context.cwd, joinPathFragments(context.root, projectRoot));
|
||||||
|
|
||||||
// Merge the options from the build and preview-serve targets.
|
// Merge the options from the build and preview-serve targets.
|
||||||
// The latter takes precedence.
|
// The latter takes precedence.
|
||||||
const mergedOptions = {
|
const mergedOptions = {
|
||||||
...{ watch: {} },
|
...{ watch: {} },
|
||||||
|
build: {
|
||||||
|
outDir,
|
||||||
|
},
|
||||||
...(isCustomBuildTarget ? {} : buildTargetOptions),
|
...(isCustomBuildTarget ? {} : buildTargetOptions),
|
||||||
...options,
|
...extraArgs,
|
||||||
outputPath,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retrieve the server configuration.
|
// Retrieve the server configuration.
|
||||||
const serverConfig: InlineConfig = mergeConfig(
|
const serverConfig: InlineConfig = mergeConfig(
|
||||||
getViteSharedConfig(mergedOptions, options.clearScreen, context),
|
|
||||||
{
|
{
|
||||||
build: getViteBuildOptions(mergedOptions, context),
|
// This should not be needed as it's going to be set in vite.config.ts
|
||||||
|
// but leaving it here in case someone did not migrate correctly
|
||||||
|
root: resolved.config.root ?? root,
|
||||||
|
configFile: viteConfigPath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...mergedOptions,
|
||||||
preview: getVitePreviewOptions(mergedOptions, context),
|
preview: getVitePreviewOptions(mergedOptions, context),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -146,3 +177,18 @@ function closeServer(server?: PreviewServer): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default vitePreviewServerExecutor;
|
export default vitePreviewServerExecutor;
|
||||||
|
|
||||||
|
async function getExtraArgs(
|
||||||
|
options: VitePreviewServerExecutorOptions
|
||||||
|
): Promise<InlineConfig> {
|
||||||
|
// support passing extra args to vite cli
|
||||||
|
const schema = await import('./schema.json');
|
||||||
|
const extraArgs = {};
|
||||||
|
for (const key of Object.keys(options)) {
|
||||||
|
if (!schema.properties[key]) {
|
||||||
|
extraArgs[key] = options[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extraArgs as InlineConfig;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,12 +1,5 @@
|
|||||||
export interface VitePreviewServerExecutorOptions {
|
export interface VitePreviewServerExecutorOptions {
|
||||||
buildTarget: string;
|
buildTarget: string;
|
||||||
proxyConfig?: string;
|
proxyConfig?: string;
|
||||||
port?: number;
|
|
||||||
host?: string | boolean;
|
|
||||||
https?: boolean | Json;
|
|
||||||
open?: string | boolean;
|
|
||||||
logLevel?: 'info' | 'warn' | 'error' | 'silent';
|
|
||||||
mode?: string;
|
|
||||||
clearScreen?: boolean;
|
|
||||||
staticFilePath?: string;
|
staticFilePath?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,56 +25,6 @@
|
|||||||
"description": "Path to the proxy configuration file.",
|
"description": "Path to the proxy configuration file.",
|
||||||
"x-completion-type": "file"
|
"x-completion-type": "file"
|
||||||
},
|
},
|
||||||
"port": {
|
|
||||||
"type": "number",
|
|
||||||
"description": "Port to listen on."
|
|
||||||
},
|
|
||||||
"host": {
|
|
||||||
"description": "Specify which IP addresses the server should listen on.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"https": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Serve using HTTPS. https://vitejs.dev/config/server-options.html#server-https"
|
|
||||||
},
|
|
||||||
"open": {
|
|
||||||
"description": "Automatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname.",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"logLevel": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Adjust console output verbosity.",
|
|
||||||
"enum": ["info", "warn", "error", "silent"]
|
|
||||||
},
|
|
||||||
"mode": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Mode to run the server in."
|
|
||||||
},
|
|
||||||
"clearScreen": {
|
|
||||||
"description": "Set to false to prevent Vite from clearing the terminal screen when logging certain messages.",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"staticFilePath": {
|
"staticFilePath": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Path where the build artifacts are located. If not provided then it will be infered from the buildTarget executor options as outputPath",
|
"description": "Path where the build artifacts are located. If not provided then it will be infered from the buildTarget executor options as outputPath",
|
||||||
|
|||||||
36
packages/vite/src/executors/test/lib/nx-reporter.ts
Normal file
36
packages/vite/src/executors/test/lib/nx-reporter.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import type { File, Reporter } from 'vitest';
|
||||||
|
|
||||||
|
export class NxReporter implements Reporter {
|
||||||
|
deferred: {
|
||||||
|
promise: Promise<boolean>;
|
||||||
|
resolve: (val: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(private watch: boolean) {
|
||||||
|
this.setupDeferred();
|
||||||
|
}
|
||||||
|
|
||||||
|
async *[Symbol.asyncIterator]() {
|
||||||
|
do {
|
||||||
|
const hasErrors = await this.deferred.promise;
|
||||||
|
yield { hasErrors };
|
||||||
|
this.setupDeferred();
|
||||||
|
} while (this.watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupDeferred() {
|
||||||
|
let resolve: (val: boolean) => void;
|
||||||
|
this.deferred = {
|
||||||
|
promise: new Promise((res) => {
|
||||||
|
resolve = res;
|
||||||
|
}),
|
||||||
|
resolve,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onFinished(files: File[], errors?: unknown[]) {
|
||||||
|
const hasErrors =
|
||||||
|
files.some((f) => f.result?.state === 'fail') || errors?.length > 0;
|
||||||
|
this.deferred.resolve(hasErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
88
packages/vite/src/executors/test/lib/utils.ts
Normal file
88
packages/vite/src/executors/test/lib/utils.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import {
|
||||||
|
ExecutorContext,
|
||||||
|
joinPathFragments,
|
||||||
|
logger,
|
||||||
|
stripIndents,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { VitestExecutorOptions } from '../schema';
|
||||||
|
import { normalizeViteConfigFilePath } from '../../../utils/options-utils';
|
||||||
|
import { relative } from 'path';
|
||||||
|
import { NxReporter } from './nx-reporter';
|
||||||
|
|
||||||
|
export async function getOptions(
|
||||||
|
options: VitestExecutorOptions,
|
||||||
|
context: ExecutorContext,
|
||||||
|
projectRoot: string,
|
||||||
|
extraArgs: Record<string, any>
|
||||||
|
) {
|
||||||
|
// Allows ESM to be required in CJS modules. Vite will be published as ESM in the future.
|
||||||
|
const { loadConfigFromFile, mergeConfig } = await (Function(
|
||||||
|
'return import("vite")'
|
||||||
|
)() as Promise<typeof import('vite')>);
|
||||||
|
|
||||||
|
const viteConfigPath = normalizeViteConfigFilePath(
|
||||||
|
context.root,
|
||||||
|
projectRoot,
|
||||||
|
options.configFile
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!viteConfigPath) {
|
||||||
|
throw new Error(
|
||||||
|
stripIndents`
|
||||||
|
Unable to load test config from config file ${viteConfigPath}.
|
||||||
|
|
||||||
|
Please make sure that vitest is configured correctly,
|
||||||
|
or use the @nx/vite:vitest generator to configure it for you.
|
||||||
|
You can read more here: https://nx.dev/nx-api/vite/generators/vitest
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolved = await loadConfigFromFile(
|
||||||
|
{
|
||||||
|
mode: extraArgs?.mode ?? 'production',
|
||||||
|
command: 'serve',
|
||||||
|
},
|
||||||
|
viteConfigPath
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!viteConfigPath || !resolved?.config?.['test']) {
|
||||||
|
logger.warn(stripIndents`Unable to load test config from config file ${
|
||||||
|
resolved?.path ?? viteConfigPath
|
||||||
|
}
|
||||||
|
Some settings may not be applied as expected.
|
||||||
|
You can manually set the config in the project, ${
|
||||||
|
context.projectName
|
||||||
|
}, configuration.
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
const root =
|
||||||
|
projectRoot === '.'
|
||||||
|
? process.cwd()
|
||||||
|
: relative(context.cwd, joinPathFragments(context.root, projectRoot));
|
||||||
|
|
||||||
|
const settings = {
|
||||||
|
...extraArgs,
|
||||||
|
// This should not be needed as it's going to be set in vite.config.ts
|
||||||
|
// but leaving it here in case someone did not migrate correctly
|
||||||
|
root: resolved.config.root ?? root,
|
||||||
|
configFile: viteConfigPath,
|
||||||
|
};
|
||||||
|
|
||||||
|
return mergeConfig(resolved?.config?.['test'] ?? {}, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getExtraArgs(
|
||||||
|
options: VitestExecutorOptions
|
||||||
|
): Promise<Record<string, any>> {
|
||||||
|
// support passing extra args to vite cli
|
||||||
|
const schema = await import('../schema.json');
|
||||||
|
const extraArgs: Record<string, any> = {};
|
||||||
|
for (const key of Object.keys(options)) {
|
||||||
|
if (!schema.properties[key]) {
|
||||||
|
extraArgs[key] = options[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return extraArgs;
|
||||||
|
}
|
||||||
10
packages/vite/src/executors/test/schema.d.ts
vendored
10
packages/vite/src/executors/test/schema.d.ts
vendored
@ -1,12 +1,6 @@
|
|||||||
export interface VitestExecutorOptions {
|
export interface VitestExecutorOptions {
|
||||||
config?: string;
|
configFile?: string;
|
||||||
passWithNoTests?: boolean;
|
|
||||||
testNamePattern?: string;
|
|
||||||
mode?: 'test' | 'benchmark' | 'typecheck';
|
|
||||||
reporters?: string[];
|
|
||||||
watch?: boolean;
|
|
||||||
update?: boolean;
|
|
||||||
reportsDirectory?: string;
|
reportsDirectory?: string;
|
||||||
coverage?: boolean;
|
|
||||||
testFiles?: string[];
|
testFiles?: string[];
|
||||||
|
watch?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,52 +6,12 @@
|
|||||||
"description": "Test using Vitest.",
|
"description": "Test using Vitest.",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"config": {
|
"configFile": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The path to the local vitest config",
|
"description": "The path to the local vitest config",
|
||||||
"x-completion-type": "file",
|
"x-completion-type": "file",
|
||||||
"x-completion-glob": "@(vitest|vite).config@(.js|.ts)"
|
"x-completion-glob": "@(vitest|vite).config@(.js|.ts)",
|
||||||
},
|
"aliases": ["config"]
|
||||||
"passWithNoTests": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true,
|
|
||||||
"description": "Pass the test even if no tests are found"
|
|
||||||
},
|
|
||||||
"testNamePattern": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Run tests with full names matching the pattern"
|
|
||||||
},
|
|
||||||
"mode": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": ["test", "benchmark", "typecheck"],
|
|
||||||
"default": "test",
|
|
||||||
"description": "The mode that vitest will run on",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"watch": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"description": "Enable watch mode"
|
|
||||||
},
|
|
||||||
"reporters": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"description": "An array of reporters to pass to vitest"
|
|
||||||
},
|
|
||||||
"update": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"alias": "u",
|
|
||||||
"description": "Update snapshots",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"coverage": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"description": "Enable coverage report",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
},
|
||||||
"reportsDirectory": {
|
"reportsDirectory": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -61,6 +21,10 @@
|
|||||||
"aliases": ["testFile"],
|
"aliases": ["testFile"],
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": { "type": "string" }
|
"items": { "type": "string" }
|
||||||
|
},
|
||||||
|
"watch": {
|
||||||
|
"description": "Watch files for changes and rerun tests related to changed files.",
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [],
|
"required": [],
|
||||||
|
|||||||
@ -1,51 +1,9 @@
|
|||||||
import {
|
import { ExecutorContext, workspaceRoot } from '@nx/devkit';
|
||||||
ExecutorContext,
|
|
||||||
joinPathFragments,
|
|
||||||
logger,
|
|
||||||
readJsonFile,
|
|
||||||
stripIndents,
|
|
||||||
workspaceRoot,
|
|
||||||
} from '@nx/devkit';
|
|
||||||
import type { CoverageOptions, File, Reporter } from 'vitest';
|
|
||||||
import { VitestExecutorOptions } from './schema';
|
import { VitestExecutorOptions } from './schema';
|
||||||
import { join, relative, resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
import { existsSync } from 'fs';
|
|
||||||
import { registerTsConfigPaths } from '@nx/js/src/internal';
|
import { registerTsConfigPaths } from '@nx/js/src/internal';
|
||||||
|
import { NxReporter } from './lib/nx-reporter';
|
||||||
class NxReporter implements Reporter {
|
import { getExtraArgs, getOptions } from './lib/utils';
|
||||||
deferred: {
|
|
||||||
promise: Promise<boolean>;
|
|
||||||
resolve: (val: boolean) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(private watch: boolean) {
|
|
||||||
this.setupDeferred();
|
|
||||||
}
|
|
||||||
|
|
||||||
async *[Symbol.asyncIterator]() {
|
|
||||||
do {
|
|
||||||
const hasErrors = await this.deferred.promise;
|
|
||||||
yield { hasErrors };
|
|
||||||
this.setupDeferred();
|
|
||||||
} while (this.watch);
|
|
||||||
}
|
|
||||||
|
|
||||||
private setupDeferred() {
|
|
||||||
let resolve: (val: boolean) => void;
|
|
||||||
this.deferred = {
|
|
||||||
promise: new Promise((res) => {
|
|
||||||
resolve = res;
|
|
||||||
}),
|
|
||||||
resolve,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onFinished(files: File[], errors?: unknown[]) {
|
|
||||||
const hasErrors =
|
|
||||||
files.some((f) => f.result?.state === 'fail') || errors?.length > 0;
|
|
||||||
this.deferred.resolve(hasErrors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function* vitestExecutor(
|
export async function* vitestExecutor(
|
||||||
options: VitestExecutorOptions,
|
options: VitestExecutorOptions,
|
||||||
@ -53,18 +11,32 @@ export async function* vitestExecutor(
|
|||||||
) {
|
) {
|
||||||
const projectRoot =
|
const projectRoot =
|
||||||
context.projectsConfigurations.projects[context.projectName].root;
|
context.projectsConfigurations.projects[context.projectName].root;
|
||||||
|
|
||||||
registerTsConfigPaths(resolve(workspaceRoot, projectRoot, 'tsconfig.json'));
|
registerTsConfigPaths(resolve(workspaceRoot, projectRoot, 'tsconfig.json'));
|
||||||
|
|
||||||
const { startVitest } = await (Function(
|
const { startVitest } = await (Function(
|
||||||
'return import("vitest/node")'
|
'return import("vitest/node")'
|
||||||
)() as Promise<typeof import('vitest/node')>);
|
)() as Promise<typeof import('vitest/node')>);
|
||||||
|
|
||||||
const nxReporter = new NxReporter(options.watch);
|
const extraArgs = await getExtraArgs(options);
|
||||||
const settings = await getSettings(options, context, projectRoot);
|
const resolvedOptions =
|
||||||
settings.reporters.push(nxReporter);
|
(await getOptions(options, context, projectRoot, extraArgs)) ?? {};
|
||||||
|
|
||||||
|
const nxReporter = new NxReporter(resolvedOptions['watch']);
|
||||||
|
if (resolvedOptions['reporters'] === undefined) {
|
||||||
|
resolvedOptions['reporters'] = [];
|
||||||
|
} else if (typeof resolvedOptions['reporters'] === 'string') {
|
||||||
|
resolvedOptions['reporters'] = [resolvedOptions['reporters']];
|
||||||
|
}
|
||||||
|
resolvedOptions['reporters'].push(nxReporter);
|
||||||
|
|
||||||
const cliFilters = options.testFiles ?? [];
|
const cliFilters = options.testFiles ?? [];
|
||||||
|
|
||||||
const ctx = await startVitest(options.mode, cliFilters, settings);
|
const ctx = await startVitest(
|
||||||
|
resolvedOptions['mode'] ?? 'test',
|
||||||
|
cliFilters,
|
||||||
|
resolvedOptions
|
||||||
|
);
|
||||||
|
|
||||||
let hasErrors = false;
|
let hasErrors = false;
|
||||||
|
|
||||||
@ -77,7 +49,7 @@ export async function* vitestExecutor(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.watch) {
|
if (resolvedOptions['watch'] === true) {
|
||||||
process.on('SIGINT', processExit);
|
process.on('SIGINT', processExit);
|
||||||
process.on('SIGTERM', processExit);
|
process.on('SIGTERM', processExit);
|
||||||
process.on('exit', processExit);
|
process.on('exit', processExit);
|
||||||
@ -94,111 +66,4 @@ export async function* vitestExecutor(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSettings(
|
|
||||||
options: VitestExecutorOptions,
|
|
||||||
context: ExecutorContext,
|
|
||||||
projectRoot: string
|
|
||||||
) {
|
|
||||||
// Allows ESM to be required in CJS modules. Vite will be published as ESM in the future.
|
|
||||||
const { loadConfigFromFile } = await (Function(
|
|
||||||
'return import("vite")'
|
|
||||||
)() as Promise<typeof import('vite')>);
|
|
||||||
|
|
||||||
const packageJsonPath = join(workspaceRoot, 'package.json');
|
|
||||||
const packageJson = existsSync(packageJsonPath)
|
|
||||||
? readJsonFile(packageJsonPath)
|
|
||||||
: undefined;
|
|
||||||
let provider: 'v8' | 'istanbul' | 'custom';
|
|
||||||
if (
|
|
||||||
packageJson?.dependencies?.['@vitest/coverage-istanbul'] ||
|
|
||||||
packageJson?.devDependencies?.['@vitest/coverage-istanbul']
|
|
||||||
) {
|
|
||||||
provider = 'istanbul';
|
|
||||||
} else {
|
|
||||||
provider = 'v8';
|
|
||||||
}
|
|
||||||
const offset = relative(workspaceRoot, context.cwd);
|
|
||||||
// if reportsDirectory is not provided vitest will remove all files in the project root
|
|
||||||
// when coverage is enabled in the vite.config.ts
|
|
||||||
const coverage: CoverageOptions = options.reportsDirectory
|
|
||||||
? {
|
|
||||||
enabled: options.coverage,
|
|
||||||
reportsDirectory: options.reportsDirectory,
|
|
||||||
provider,
|
|
||||||
}
|
|
||||||
: ({} as CoverageOptions);
|
|
||||||
|
|
||||||
const viteConfigPath = options.config
|
|
||||||
? options.config // config is expected to be from the workspace root
|
|
||||||
: findViteConfig(joinPathFragments(context.root, projectRoot));
|
|
||||||
|
|
||||||
if (!viteConfigPath) {
|
|
||||||
throw new Error(
|
|
||||||
stripIndents`
|
|
||||||
Unable to load test config from config file ${viteConfigPath}.
|
|
||||||
|
|
||||||
Please make sure that vitest is configured correctly,
|
|
||||||
or use the @nx/vite:vitest generator to configure it for you.
|
|
||||||
You can read more here: https://nx.dev/nx-api/vite/generators/vitest
|
|
||||||
`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolvedProjectRoot = resolve(workspaceRoot, projectRoot);
|
|
||||||
const resolvedViteConfigPath = resolve(
|
|
||||||
workspaceRoot,
|
|
||||||
projectRoot,
|
|
||||||
relative(resolvedProjectRoot, viteConfigPath)
|
|
||||||
);
|
|
||||||
|
|
||||||
const resolved = await loadConfigFromFile(
|
|
||||||
{
|
|
||||||
mode: options.mode,
|
|
||||||
command: 'serve',
|
|
||||||
},
|
|
||||||
resolvedViteConfigPath,
|
|
||||||
resolvedProjectRoot
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!viteConfigPath || !resolved?.config?.['test']) {
|
|
||||||
logger.warn(stripIndents`Unable to load test config from config file ${
|
|
||||||
resolved?.path ?? viteConfigPath
|
|
||||||
}
|
|
||||||
Some settings may not be applied as expected.
|
|
||||||
You can manually set the config in the project, ${
|
|
||||||
context.projectName
|
|
||||||
}, configuration.
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const settings = {
|
|
||||||
...options,
|
|
||||||
// when running nx from the project root, the root will get appended to the cwd.
|
|
||||||
// creating an invalid path and no tests will be found.
|
|
||||||
// instead if we are not at the root, let the cwd be root.
|
|
||||||
root: offset === '' ? resolvedProjectRoot : workspaceRoot,
|
|
||||||
config: resolvedViteConfigPath,
|
|
||||||
reporters: [
|
|
||||||
...(options.reporters ?? []),
|
|
||||||
...((resolved?.config?.['test']?.reporters as string[]) ?? []),
|
|
||||||
'default',
|
|
||||||
] as (string | Reporter)[],
|
|
||||||
coverage: { ...coverage, ...resolved?.config?.['test']?.coverage },
|
|
||||||
};
|
|
||||||
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findViteConfig(projectRootFullPath: string): string {
|
|
||||||
const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts'];
|
|
||||||
|
|
||||||
for (const ext of allowsExt) {
|
|
||||||
if (
|
|
||||||
existsSync(joinPathFragments(projectRootFullPath, `vite.config.${ext}`))
|
|
||||||
) {
|
|
||||||
return joinPathFragments(projectRootFullPath, `vite.config.${ext}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default vitestExecutor;
|
export default vitestExecutor;
|
||||||
|
|||||||
@ -9,7 +9,8 @@ import * as path from 'path';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: '../../node_modules/.vite/react-lib-nonb-jest',
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
@ -29,6 +30,7 @@ export default defineConfig({
|
|||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
|
outDir: '../../dist/libs/react-lib-nonb-jest',
|
||||||
lib: {
|
lib: {
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
@ -56,7 +58,8 @@ import * as path from 'path';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: '../../node_modules/.vite/react-lib-nonb-jest',
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
@ -76,6 +79,7 @@ export default defineConfig({
|
|||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
|
outDir: '../../dist/libs/react-lib-nonb-jest',
|
||||||
lib: {
|
lib: {
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
@ -98,6 +102,11 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
@ -143,8 +152,9 @@ import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
cacheDir: '../../node_modules/.vite/react-lib-nonb-vitest',
|
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-vitest',
|
||||||
build: {
|
build: {
|
||||||
|
outDir: '../../dist/libs/react-lib-nonb-vitest',
|
||||||
lib: {
|
lib: {
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
@ -174,6 +184,10 @@ export default defineConfig({
|
|||||||
cache: { dir: '../../node_modules/.vitest' },
|
cache: { dir: '../../node_modules/.vitest' },
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../../coverage/libs/react-lib-nonb-vitest',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
@ -271,7 +285,8 @@ import react from '@vitejs/plugin-react';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: '../../node_modules/.vite/my-test-react-app',
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
@ -289,6 +304,10 @@ export default defineConfig({
|
|||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
|
build: {
|
||||||
|
outDir: '../../dist/apps/my-test-react-app',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
@ -409,7 +428,8 @@ import { defineConfig } from 'vite';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: '../../node_modules/.vite/my-test-web-app',
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/apps/my-test-web-app',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
@ -427,6 +447,10 @@ export default defineConfig({
|
|||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
|
build: {
|
||||||
|
outDir: '../../dist/apps/my-test-web-app',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
@ -534,7 +558,8 @@ import react from '@vitejs/plugin-react';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: '../../node_modules/.vite/my-test-react-app',
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
@ -553,6 +578,10 @@ export default defineConfig({
|
|||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
|
build: {
|
||||||
|
outDir: '../../dist/apps/my-test-react-app',
|
||||||
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
cache: {
|
cache: {
|
||||||
@ -560,6 +589,11 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
|
|||||||
@ -33,10 +33,11 @@ export async function viteConfigurationGenerator(
|
|||||||
) {
|
) {
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
|
||||||
const { targets, projectType, root } = readProjectConfiguration(
|
const {
|
||||||
tree,
|
targets,
|
||||||
schema.project
|
projectType,
|
||||||
);
|
root: projectRoot,
|
||||||
|
} = readProjectConfiguration(tree, schema.project);
|
||||||
let buildTargetName = 'build';
|
let buildTargetName = 'build';
|
||||||
let serveTargetName = 'serve';
|
let serveTargetName = 'serve';
|
||||||
let testTargetName = 'test';
|
let testTargetName = 'test';
|
||||||
@ -147,7 +148,7 @@ export async function viteConfigurationGenerator(
|
|||||||
|
|
||||||
deleteWebpackConfig(
|
deleteWebpackConfig(
|
||||||
tree,
|
tree,
|
||||||
root,
|
projectRoot,
|
||||||
targets?.[buildTargetName]?.options?.webpackConfig
|
targets?.[buildTargetName]?.options?.webpackConfig
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ export async function viteConfigurationGenerator(
|
|||||||
includeLib: schema.includeLib,
|
includeLib: schema.includeLib,
|
||||||
compiler: schema.compiler,
|
compiler: schema.compiler,
|
||||||
testEnvironment: schema.testEnvironment,
|
testEnvironment: schema.testEnvironment,
|
||||||
rootProject: root === '.',
|
rootProject: projectRoot === '.',
|
||||||
});
|
});
|
||||||
tasks.push(initTask);
|
tasks.push(initTask);
|
||||||
|
|
||||||
@ -178,24 +179,28 @@ export async function viteConfigurationGenerator(
|
|||||||
|
|
||||||
if (projectType === 'library') {
|
if (projectType === 'library') {
|
||||||
// update tsconfig.lib.json to include vite/client
|
// update tsconfig.lib.json to include vite/client
|
||||||
updateJson(tree, joinPathFragments(root, 'tsconfig.lib.json'), (json) => {
|
updateJson(
|
||||||
if (!json.compilerOptions) {
|
tree,
|
||||||
json.compilerOptions = {};
|
joinPathFragments(projectRoot, 'tsconfig.lib.json'),
|
||||||
|
(json) => {
|
||||||
|
if (!json.compilerOptions) {
|
||||||
|
json.compilerOptions = {};
|
||||||
|
}
|
||||||
|
if (!json.compilerOptions.types) {
|
||||||
|
json.compilerOptions.types = [];
|
||||||
|
}
|
||||||
|
if (!json.compilerOptions.types.includes('vite/client')) {
|
||||||
|
return {
|
||||||
|
...json,
|
||||||
|
compilerOptions: {
|
||||||
|
...json.compilerOptions,
|
||||||
|
types: [...json.compilerOptions.types, 'vite/client'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
if (!json.compilerOptions.types) {
|
);
|
||||||
json.compilerOptions.types = [];
|
|
||||||
}
|
|
||||||
if (!json.compilerOptions.types.includes('vite/client')) {
|
|
||||||
return {
|
|
||||||
...json,
|
|
||||||
compilerOptions: {
|
|
||||||
...json.compilerOptions,
|
|
||||||
types: [...json.compilerOptions.types, 'vite/client'],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return json;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!schema.newProject) {
|
if (!schema.newProject) {
|
||||||
|
|||||||
@ -93,6 +93,10 @@ describe('@nx/vite:init', () => {
|
|||||||
expect(vitestDefaults).toEqual({
|
expect(vitestDefaults).toEqual({
|
||||||
cache: true,
|
cache: true,
|
||||||
inputs: ['default', '^production'],
|
inputs: ['default', '^production'],
|
||||||
|
options: {
|
||||||
|
passWithNoTests: true,
|
||||||
|
reporters: ['default'],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -34,23 +34,8 @@ function checkDependenciesInstalled(host: Tree, schema: InitGeneratorSchema) {
|
|||||||
// base deps
|
// base deps
|
||||||
devDependencies['@nx/vite'] = nxVersion;
|
devDependencies['@nx/vite'] = nxVersion;
|
||||||
devDependencies['vite'] = viteVersion;
|
devDependencies['vite'] = viteVersion;
|
||||||
|
devDependencies['vitest'] = vitestVersion;
|
||||||
// Do not install latest version if vitest already exists
|
devDependencies['@vitest/ui'] = vitestVersion;
|
||||||
// because version 0.32 and newer versions break nuxt-vitest
|
|
||||||
// https://github.com/vitest-dev/vitest/issues/3540
|
|
||||||
// https://github.com/danielroe/nuxt-vitest/issues/213#issuecomment-1588728111
|
|
||||||
if (
|
|
||||||
!packageJson.dependencies['vitest'] &&
|
|
||||||
!packageJson.devDependencies['vitest']
|
|
||||||
) {
|
|
||||||
devDependencies['vitest'] = vitestVersion;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!packageJson.dependencies['@vitest/ui'] &&
|
|
||||||
!packageJson.devDependencies['@vitest/ui']
|
|
||||||
) {
|
|
||||||
devDependencies['@vitest/ui'] = vitestVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.testEnvironment === 'jsdom') {
|
if (schema.testEnvironment === 'jsdom') {
|
||||||
devDependencies['jsdom'] = jsdomVersion;
|
devDependencies['jsdom'] = jsdomVersion;
|
||||||
@ -93,7 +78,7 @@ function moveToDevDependencies(tree: Tree) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createVitestConfig(tree: Tree) {
|
export function updateNxJsonSettings(tree: Tree) {
|
||||||
const nxJson = readNxJson(tree);
|
const nxJson = readNxJson(tree);
|
||||||
|
|
||||||
const productionFileSet = nxJson.namedInputs?.production;
|
const productionFileSet = nxJson.namedInputs?.production;
|
||||||
@ -113,13 +98,26 @@ export function createVitestConfig(tree: Tree) {
|
|||||||
'default',
|
'default',
|
||||||
productionFileSet ? '^production' : '^default',
|
productionFileSet ? '^production' : '^default',
|
||||||
];
|
];
|
||||||
|
nxJson.targetDefaults['@nx/vite:test'].options ??= {
|
||||||
|
passWithNoTests: true,
|
||||||
|
reporters: ['default'],
|
||||||
|
};
|
||||||
|
|
||||||
|
nxJson.targetDefaults['@nx/vite:build'] ??= {};
|
||||||
|
|
||||||
|
nxJson.targetDefaults['@nx/vite:build'].options ??= {
|
||||||
|
reportCompressedSize: true,
|
||||||
|
commonjsOptions: {
|
||||||
|
transformMixedEsModules: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
updateNxJson(tree, nxJson);
|
updateNxJson(tree, nxJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function initGenerator(tree: Tree, schema: InitGeneratorSchema) {
|
export async function initGenerator(tree: Tree, schema: InitGeneratorSchema) {
|
||||||
moveToDevDependencies(tree);
|
moveToDevDependencies(tree);
|
||||||
createVitestConfig(tree);
|
updateNxJsonSettings(tree);
|
||||||
const tasks = [];
|
const tasks = [];
|
||||||
|
|
||||||
tasks.push(
|
tasks.push(
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import react from '@vitejs/plugin-react';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: '../../node_modules/.vite/my-test-react-app',
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths()],
|
plugins: [react(), nxViteTsPaths()],
|
||||||
|
|
||||||
@ -27,6 +28,10 @@ export default defineConfig({
|
|||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
@ -39,7 +44,8 @@ import react from '@vitejs/plugin-react';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: '../../node_modules/.vite/my-test-react-app',
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/apps/my-test-react-app',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths()],
|
plugins: [react(), nxViteTsPaths()],
|
||||||
|
|
||||||
@ -55,6 +61,11 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../../coverage/apps/my-test-react-app',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
@ -67,7 +78,8 @@ import react from '@vitejs/plugin-react';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
cacheDir: '../../node_modules/.vite/react-lib-nonb-jest',
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/libs/react-lib-nonb-jest',
|
||||||
|
|
||||||
plugins: [react(), nxViteTsPaths()],
|
plugins: [react(), nxViteTsPaths()],
|
||||||
|
|
||||||
@ -83,6 +95,11 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../../coverage/libs/react-lib-nonb-jest',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"vite.config.ts",
|
"vite.config.ts",
|
||||||
|
"vitest.config.ts",
|
||||||
"src/**/*.test.ts",
|
"src/**/*.test.ts",
|
||||||
"src/**/*.spec.ts",
|
"src/**/*.spec.ts",
|
||||||
"src/**/*.test.tsx",
|
"src/**/*.test.tsx",
|
||||||
|
|||||||
@ -65,6 +65,7 @@ export async function vitestGenerator(
|
|||||||
],
|
],
|
||||||
imports: [`import react from '@vitejs/plugin-react'`],
|
imports: [`import react from '@vitejs/plugin-react'`],
|
||||||
plugins: ['react()'],
|
plugins: ['react()'],
|
||||||
|
coverageProvider: schema.coverageProvider,
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|||||||
@ -55,7 +55,6 @@ describe('vitest generator', () => {
|
|||||||
{
|
{
|
||||||
"executor": "@nx/vite:test",
|
"executor": "@nx/vite:test",
|
||||||
"options": {
|
"options": {
|
||||||
"passWithNoTests": true,
|
|
||||||
"reportsDirectory": "../../coverage/apps/my-test-react-app",
|
"reportsDirectory": "../../coverage/apps/my-test-react-app",
|
||||||
},
|
},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
@ -102,6 +101,7 @@ describe('vitest generator', () => {
|
|||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"include": [
|
"include": [
|
||||||
"vite.config.ts",
|
"vite.config.ts",
|
||||||
|
"vitest.config.ts",
|
||||||
"src/**/*.test.ts",
|
"src/**/*.test.ts",
|
||||||
"src/**/*.spec.ts",
|
"src/**/*.spec.ts",
|
||||||
"src/**/*.test.tsx",
|
"src/**/*.test.tsx",
|
||||||
|
|||||||
@ -0,0 +1,156 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`change-vite-ts-paths-plugin migration should add build outDir to vite.config.ts 1`] = `
|
||||||
|
"/// <reference types="vitest" />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import viteTsConfigPaths from 'vite-tsconfig-paths';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
build: {
|
||||||
|
outDir: '../../dist/apps/demo',
|
||||||
|
},
|
||||||
|
cacheDir: '../../node_modules/.vite/demo',
|
||||||
|
server: {
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
preview: {
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
react(),
|
||||||
|
viteTsConfigPaths({
|
||||||
|
root: '../../',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [
|
||||||
|
// viteTsConfigPaths({
|
||||||
|
// root: '../../',
|
||||||
|
// }),
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
|
||||||
|
test: {
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../../coverage/apps/demo',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
|
globals: true,
|
||||||
|
cache: {
|
||||||
|
dir: '../../node_modules/.vitest',
|
||||||
|
},
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`change-vite-ts-paths-plugin migration should add build outDir to vite.config.ts if build exists 1`] = `
|
||||||
|
"/// <reference types="vitest" />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import viteTsConfigPaths from 'vite-tsconfig-paths';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/demo2',
|
||||||
|
server: {
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
preview: {
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
react(),
|
||||||
|
viteTsConfigPaths({
|
||||||
|
root: '../../',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/demo2',
|
||||||
|
someProperty: 'someValue',
|
||||||
|
},
|
||||||
|
|
||||||
|
test: {
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/demo2',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
|
globals: true,
|
||||||
|
cache: {
|
||||||
|
dir: '../../node_modules/.vitest',
|
||||||
|
},
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`change-vite-ts-paths-plugin migration should add file replacements to vite.config.ts 1`] = `
|
||||||
|
"/// <reference types="vitest" />
|
||||||
|
import replaceFiles from '@nx/vite/plugins/rollup-replace-files.plugin';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import viteTsConfigPaths from 'vite-tsconfig-paths';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../../node_modules/.vite/demo3',
|
||||||
|
server: {
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
preview: {
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
replaceFiles([
|
||||||
|
{
|
||||||
|
replace: 'demo3/src/environments/environment.ts',
|
||||||
|
with: 'demo3/src/environments/environment.prod.ts',
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
react(),
|
||||||
|
viteTsConfigPaths({
|
||||||
|
root: '../../',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/demo3',
|
||||||
|
someProperty: 'someValue',
|
||||||
|
},
|
||||||
|
|
||||||
|
test: {
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/demo3',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
|
globals: true,
|
||||||
|
cache: {
|
||||||
|
dir: '../../node_modules/.vitest',
|
||||||
|
},
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
import { ChangeType, applyChangesToString } from '@nx/devkit';
|
||||||
|
import { FileReplacement } from '../../../../plugins/rollup-replace-files.plugin';
|
||||||
|
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||||
|
|
||||||
|
export function addFileReplacements(
|
||||||
|
configContents: string,
|
||||||
|
fileReplacements: FileReplacement[]
|
||||||
|
): string {
|
||||||
|
const pluginsObject = tsquery.query(
|
||||||
|
configContents,
|
||||||
|
`PropertyAssignment:has(Identifier[name="plugins"])`
|
||||||
|
)?.[0];
|
||||||
|
const replaceFilesPlugin = tsquery.query(
|
||||||
|
configContents,
|
||||||
|
`PropertyAssignment:has(Identifier[name="plugins"]) CallExpression:has(Identifier[name="replaceFiles"])`
|
||||||
|
)?.[0];
|
||||||
|
|
||||||
|
const firstImportDeclaration = tsquery.query(
|
||||||
|
configContents,
|
||||||
|
'ImportDeclaration'
|
||||||
|
)?.[0];
|
||||||
|
|
||||||
|
if (pluginsObject) {
|
||||||
|
if (replaceFilesPlugin) {
|
||||||
|
return configContents;
|
||||||
|
} else {
|
||||||
|
return applyChangesToString(configContents, [
|
||||||
|
{
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: pluginsObject.getStart() + `plugins: [`.length + 1,
|
||||||
|
text: `replaceFiles(${JSON.stringify(fileReplacements)}),`,
|
||||||
|
},
|
||||||
|
firstImportDeclaration
|
||||||
|
? {
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: firstImportDeclaration.getStart(),
|
||||||
|
text: `import replaceFiles from '@nx/vite/plugins/rollup-replace-files.plugin';\n`,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: 0,
|
||||||
|
text: `import replaceFiles from '@nx/vite/plugins/rollup-replace-files.plugin';\n`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const foundDefineConfig = tsquery.query(
|
||||||
|
configContents,
|
||||||
|
'CallExpression:has(Identifier[name="defineConfig"])'
|
||||||
|
)?.[0];
|
||||||
|
|
||||||
|
if (!foundDefineConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return applyChangesToString(configContents, [
|
||||||
|
{
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: foundDefineConfig.getStart() + 14,
|
||||||
|
text: `plugins: [replaceFiles(${JSON.stringify(fileReplacements)})],`,
|
||||||
|
},
|
||||||
|
firstImportDeclaration
|
||||||
|
? {
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: firstImportDeclaration.getStart(),
|
||||||
|
text: `import replaceFiles from '@nx/vite/plugins/rollup-replace-files.plugin';`,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: 0,
|
||||||
|
text: `import replaceFiles from '@nx/vite/plugins/rollup-replace-files.plugin';`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
import {
|
||||||
|
ChangeType,
|
||||||
|
ProjectConfiguration,
|
||||||
|
Tree,
|
||||||
|
applyChangesToString,
|
||||||
|
joinPathFragments,
|
||||||
|
logger,
|
||||||
|
offsetFromRoot,
|
||||||
|
updateProjectConfiguration,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||||
|
import ts = require('typescript');
|
||||||
|
|
||||||
|
export function updateBuildOutDirAndRoot(
|
||||||
|
options: Record<string, any>,
|
||||||
|
configContents: string,
|
||||||
|
projectConfig: ProjectConfiguration,
|
||||||
|
targetName: string,
|
||||||
|
tree: Tree,
|
||||||
|
projectName: string
|
||||||
|
): string {
|
||||||
|
const foundDefineConfig = tsquery.query(
|
||||||
|
configContents,
|
||||||
|
'CallExpression:has(Identifier[name="defineConfig"])'
|
||||||
|
)?.[0];
|
||||||
|
|
||||||
|
if (!foundDefineConfig) {
|
||||||
|
logger.warn(`
|
||||||
|
Could not find defineConfig in your vite.config file.
|
||||||
|
Please add the build.outDir and root options to your vite.config file.
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
configContents = fixBuild(
|
||||||
|
options,
|
||||||
|
configContents,
|
||||||
|
projectConfig,
|
||||||
|
targetName,
|
||||||
|
tree,
|
||||||
|
projectName,
|
||||||
|
foundDefineConfig
|
||||||
|
);
|
||||||
|
|
||||||
|
configContents = addRoot(configContents, foundDefineConfig);
|
||||||
|
|
||||||
|
return configContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fixBuild(
|
||||||
|
options: Record<string, any>,
|
||||||
|
configContents: string,
|
||||||
|
projectConfig: ProjectConfiguration,
|
||||||
|
targetName: string,
|
||||||
|
tree: Tree,
|
||||||
|
projectName: string,
|
||||||
|
foundDefineConfig?: ts.Node
|
||||||
|
) {
|
||||||
|
let outputPath = '';
|
||||||
|
|
||||||
|
// In vite.config.ts, we want to keep the path relative to workspace root
|
||||||
|
if (options.outputPath) {
|
||||||
|
outputPath = joinPathFragments(
|
||||||
|
offsetFromRoot(projectConfig.root),
|
||||||
|
options.outputPath
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
outputPath = joinPathFragments(
|
||||||
|
offsetFromRoot(projectConfig.root),
|
||||||
|
'dist',
|
||||||
|
projectConfig.root
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In project.json, we want to keep the path starting from workspace root
|
||||||
|
projectConfig.targets[targetName].options.outputPath = options.outputPath
|
||||||
|
? options.outputPath
|
||||||
|
: joinPathFragments('dist', projectConfig.root);
|
||||||
|
updateProjectConfiguration(tree, projectName, projectConfig);
|
||||||
|
|
||||||
|
const buildObject = tsquery.query(
|
||||||
|
configContents,
|
||||||
|
`PropertyAssignment:has(Identifier[name="build"])`
|
||||||
|
)?.[0];
|
||||||
|
let buildOutDir: ts.Node[];
|
||||||
|
if (buildObject) {
|
||||||
|
buildOutDir = tsquery.query(
|
||||||
|
buildObject,
|
||||||
|
`PropertyAssignment:has(Identifier[name="outDir"])`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buildOutDir?.length > 0) {
|
||||||
|
return configContents;
|
||||||
|
} else if (buildObject) {
|
||||||
|
// has build, has no outDir
|
||||||
|
// so add outDir
|
||||||
|
return applyChangesToString(configContents, [
|
||||||
|
{
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: buildObject.getStart() + `build: {`.length + 1,
|
||||||
|
text: `outDir: '${outputPath}',`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return addBuildProperty(configContents, outputPath, foundDefineConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addRoot(
|
||||||
|
configFileContents: string,
|
||||||
|
foundDefineConfig?: ts.Node
|
||||||
|
): string {
|
||||||
|
const rootOption = tsquery.query(
|
||||||
|
configFileContents,
|
||||||
|
`PropertyAssignment:has(Identifier[name="root"]) Identifier[name="__dirname"]`
|
||||||
|
)?.[0];
|
||||||
|
|
||||||
|
if (rootOption || !foundDefineConfig) {
|
||||||
|
return configFileContents;
|
||||||
|
} else {
|
||||||
|
return applyChangesToString(configFileContents, [
|
||||||
|
{
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: foundDefineConfig.getStart() + 14,
|
||||||
|
text: `root: __dirname,`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addBuildProperty(
|
||||||
|
configFileContents: string,
|
||||||
|
outputPath: string,
|
||||||
|
foundDefineConfig: ts.Node
|
||||||
|
): string {
|
||||||
|
if (foundDefineConfig) {
|
||||||
|
return applyChangesToString(configFileContents, [
|
||||||
|
{
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: foundDefineConfig.getStart() + 14,
|
||||||
|
text: `build: {
|
||||||
|
outDir: '${outputPath}',
|
||||||
|
},`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
return configFileContents;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
import {
|
||||||
|
ChangeType,
|
||||||
|
ProjectConfiguration,
|
||||||
|
applyChangesToString,
|
||||||
|
joinPathFragments,
|
||||||
|
offsetFromRoot,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||||
|
import ts = require('typescript');
|
||||||
|
|
||||||
|
export function updateTestConfig(
|
||||||
|
configContents: string,
|
||||||
|
projectConfig: ProjectConfiguration
|
||||||
|
): string {
|
||||||
|
const testObject = tsquery.query(
|
||||||
|
configContents,
|
||||||
|
`PropertyAssignment:has(Identifier[name="test"])`
|
||||||
|
)?.[0];
|
||||||
|
let testCoverageDir: ts.Node;
|
||||||
|
let testCoverage: ts.Node;
|
||||||
|
let provider: ts.Node;
|
||||||
|
if (testObject) {
|
||||||
|
testCoverage = tsquery.query(
|
||||||
|
testObject,
|
||||||
|
`PropertyAssignment:has(Identifier[name="coverage"])`
|
||||||
|
)?.[0];
|
||||||
|
if (testCoverage) {
|
||||||
|
testCoverageDir = tsquery.query(
|
||||||
|
testCoverage,
|
||||||
|
`PropertyAssignment:has(Identifier[name="reportsDirectory"])`
|
||||||
|
)?.[0];
|
||||||
|
provider = tsquery.query(
|
||||||
|
testCoverage,
|
||||||
|
`PropertyAssignment:has(Identifier[name="provider"])`
|
||||||
|
)?.[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let coverageDir = '';
|
||||||
|
|
||||||
|
if (projectConfig.targets?.test?.options?.reportsDirectory) {
|
||||||
|
coverageDir = projectConfig.targets?.test?.options?.reportsDirectory;
|
||||||
|
} else {
|
||||||
|
coverageDir = joinPathFragments(
|
||||||
|
offsetFromRoot(projectConfig.root),
|
||||||
|
'coverage',
|
||||||
|
projectConfig.root
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testCoverageDir) {
|
||||||
|
// Do nothing
|
||||||
|
} else if (testCoverage) {
|
||||||
|
// has test.coverage, has no reportsDirectory
|
||||||
|
// so add reportsDirectory
|
||||||
|
configContents = applyChangesToString(configContents, [
|
||||||
|
{
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: testCoverage.getStart() + `coverage: {`.length + 1,
|
||||||
|
text: `reportsDirectory: '${coverageDir}',`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
if (!provider) {
|
||||||
|
configContents = applyChangesToString(configContents, [
|
||||||
|
{
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: testCoverage.getStart() + `coverage: {`.length + 1,
|
||||||
|
text: `provider: 'v8',`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} else if (testObject) {
|
||||||
|
configContents = applyChangesToString(configContents, [
|
||||||
|
{
|
||||||
|
type: ChangeType.Insert,
|
||||||
|
index: testObject.getStart() + `test: {`.length + 1,
|
||||||
|
text: `coverage: {
|
||||||
|
reportsDirectory: '${coverageDir}',
|
||||||
|
provider: 'v8',
|
||||||
|
},`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
// has no test so do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
return configContents;
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { Tree, joinPathFragments } from '@nx/devkit';
|
||||||
|
|
||||||
|
export function findViteConfig(tree: Tree, searchRoot: string) {
|
||||||
|
const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts'];
|
||||||
|
|
||||||
|
for (const ext of allowsExt) {
|
||||||
|
if (tree.exists(joinPathFragments(searchRoot, `vite.config.${ext}`))) {
|
||||||
|
return joinPathFragments(searchRoot, `vite.config.${ext}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,262 @@
|
|||||||
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
|
import {
|
||||||
|
Tree,
|
||||||
|
addProjectConfiguration,
|
||||||
|
readProjectConfiguration,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
|
||||||
|
import updateBuildDir from './update-vite-config';
|
||||||
|
|
||||||
|
describe('change-vite-ts-paths-plugin migration', () => {
|
||||||
|
let tree: Tree;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add build outDir to vite.config.ts', async () => {
|
||||||
|
addProject1(tree, 'demo');
|
||||||
|
await updateBuildDir(tree);
|
||||||
|
expect(tree.read('apps/demo/vite.config.ts', 'utf-8')).toMatchSnapshot();
|
||||||
|
expect(
|
||||||
|
readProjectConfiguration(tree, 'demo').targets.build.options.outputPath
|
||||||
|
).toBe('dist/apps/demo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add build outDir to vite.config.ts if build exists', async () => {
|
||||||
|
addProject2(tree, 'demo2');
|
||||||
|
await updateBuildDir(tree);
|
||||||
|
expect(tree.read('demo2/vite.config.ts', 'utf-8')).toMatchSnapshot();
|
||||||
|
expect(
|
||||||
|
readProjectConfiguration(tree, 'demo2').targets.build.options.outputPath
|
||||||
|
).toBe('dist/demo2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add file replacements to vite.config.ts', async () => {
|
||||||
|
addProject3(tree, 'demo3');
|
||||||
|
await updateBuildDir(tree);
|
||||||
|
expect(tree.read('demo3/vite.config.ts', 'utf-8')).toMatchSnapshot();
|
||||||
|
expect(
|
||||||
|
readProjectConfiguration(tree, 'demo3').targets.build.options.outputPath
|
||||||
|
).toBe('dist/demo3');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function addProject1(tree: Tree, name: string) {
|
||||||
|
addProjectConfiguration(tree, name, {
|
||||||
|
root: `apps/${name}`,
|
||||||
|
sourceRoot: `apps/${name}/src`,
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/vite:build',
|
||||||
|
outputs: ['{options.outputPath}'],
|
||||||
|
defaultConfiguration: 'production',
|
||||||
|
options: {
|
||||||
|
outputPath: `dist/apps/${name}`,
|
||||||
|
buildLibsFromSource: false,
|
||||||
|
},
|
||||||
|
configurations: {
|
||||||
|
development: {
|
||||||
|
mode: 'development',
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
mode: 'production',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
tree.write(
|
||||||
|
`apps/${name}/vite.config.ts`,
|
||||||
|
`
|
||||||
|
/// <reference types="vitest" />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import viteTsConfigPaths from 'vite-tsconfig-paths';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
cacheDir: '../../node_modules/.vite/${name}',
|
||||||
|
server: {
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
preview: {
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
react(),
|
||||||
|
viteTsConfigPaths({
|
||||||
|
root: '../../'
|
||||||
|
})
|
||||||
|
],
|
||||||
|
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [
|
||||||
|
// viteTsConfigPaths({
|
||||||
|
// root: '../../',
|
||||||
|
// }),
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
cache: {
|
||||||
|
dir: '../../node_modules/.vitest',
|
||||||
|
},
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addProject2(tree: Tree, name: string) {
|
||||||
|
addProjectConfiguration(tree, name, {
|
||||||
|
root: `${name}`,
|
||||||
|
sourceRoot: `${name}/src`,
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/vite:build',
|
||||||
|
outputs: ['{options.outputPath}'],
|
||||||
|
defaultConfiguration: 'production',
|
||||||
|
options: {
|
||||||
|
outputPath: `dist/${name}`,
|
||||||
|
},
|
||||||
|
configurations: {
|
||||||
|
development: {
|
||||||
|
mode: 'development',
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
mode: 'production',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
tree.write(
|
||||||
|
`${name}/vite.config.ts`,
|
||||||
|
`
|
||||||
|
/// <reference types="vitest" />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import viteTsConfigPaths from 'vite-tsconfig-paths';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
cacheDir: '../../node_modules/.vite/${name}',
|
||||||
|
server: {
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
preview: {
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
react(),
|
||||||
|
viteTsConfigPaths({
|
||||||
|
root: '../../'
|
||||||
|
})
|
||||||
|
],
|
||||||
|
|
||||||
|
build: {
|
||||||
|
someProperty: 'someValue',
|
||||||
|
},
|
||||||
|
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
cache: {
|
||||||
|
dir: '../../node_modules/.vitest',
|
||||||
|
},
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addProject3(tree: Tree, name: string) {
|
||||||
|
addProjectConfiguration(tree, name, {
|
||||||
|
root: `${name}`,
|
||||||
|
sourceRoot: `${name}/src`,
|
||||||
|
targets: {
|
||||||
|
build: {
|
||||||
|
executor: '@nx/vite:build',
|
||||||
|
outputs: ['{options.outputPath}'],
|
||||||
|
defaultConfiguration: 'production',
|
||||||
|
options: {
|
||||||
|
outputPath: `dist/${name}`,
|
||||||
|
},
|
||||||
|
configurations: {
|
||||||
|
development: {
|
||||||
|
mode: 'development',
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
mode: 'production',
|
||||||
|
fileReplacements: [
|
||||||
|
{
|
||||||
|
replace: `${name}/src/environments/environment.ts`,
|
||||||
|
with: `${name}/src/environments/environment.prod.ts`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
tree.write(
|
||||||
|
`${name}/vite.config.ts`,
|
||||||
|
`
|
||||||
|
/// <reference types="vitest" />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import viteTsConfigPaths from 'vite-tsconfig-paths';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
cacheDir: '../../node_modules/.vite/${name}',
|
||||||
|
server: {
|
||||||
|
port: 4200,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
preview: {
|
||||||
|
port: 4300,
|
||||||
|
host: 'localhost',
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
react(),
|
||||||
|
viteTsConfigPaths({
|
||||||
|
root: '../../'
|
||||||
|
})
|
||||||
|
],
|
||||||
|
|
||||||
|
build: {
|
||||||
|
someProperty: 'someValue',
|
||||||
|
},
|
||||||
|
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
cache: {
|
||||||
|
dir: '../../node_modules/.vitest',
|
||||||
|
},
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
import { Tree, formatFiles, getProjects, joinPathFragments } from '@nx/devkit';
|
||||||
|
import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils';
|
||||||
|
import { ViteBuildExecutorOptions } from '../../executors/build/schema';
|
||||||
|
import { updateBuildOutDirAndRoot } from './lib/edit-build-config';
|
||||||
|
import { updateTestConfig } from './lib/edit-test-config';
|
||||||
|
import { addFileReplacements } from './lib/add-file-replacements';
|
||||||
|
|
||||||
|
export default async function updateBuildDir(tree: Tree) {
|
||||||
|
const projects = getProjects(tree);
|
||||||
|
forEachExecutorOptions<ViteBuildExecutorOptions>(
|
||||||
|
tree,
|
||||||
|
'@nx/vite:build',
|
||||||
|
(options, projectName, targetName) => {
|
||||||
|
const projectConfig = projects.get(projectName);
|
||||||
|
const config =
|
||||||
|
options.configFile || findViteConfig(tree, projectConfig.root);
|
||||||
|
if (!config || !tree.exists(config)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let configContents = tree.read(config, 'utf-8');
|
||||||
|
|
||||||
|
configContents = updateBuildOutDirAndRoot(
|
||||||
|
options,
|
||||||
|
configContents,
|
||||||
|
projectConfig,
|
||||||
|
targetName,
|
||||||
|
tree,
|
||||||
|
projectName
|
||||||
|
);
|
||||||
|
|
||||||
|
configContents = updateTestConfig(configContents, projectConfig);
|
||||||
|
|
||||||
|
if (options.fileReplacements?.length > 0) {
|
||||||
|
configContents = addFileReplacements(
|
||||||
|
configContents,
|
||||||
|
options.fileReplacements
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.write(config, configContents);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await formatFiles(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findViteConfig(tree: Tree, searchRoot: string) {
|
||||||
|
const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts'];
|
||||||
|
|
||||||
|
for (const ext of allowsExt) {
|
||||||
|
if (tree.exists(joinPathFragments(searchRoot, `vite.config.${ext}`))) {
|
||||||
|
return joinPathFragments(searchRoot, `vite.config.${ext}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -32,9 +32,9 @@ export function createBuildableTsConfig(
|
|||||||
context: ExecutorContext
|
context: ExecutorContext
|
||||||
) {
|
) {
|
||||||
const tsConfig = resolve(projectRoot, 'tsconfig.json');
|
const tsConfig = resolve(projectRoot, 'tsconfig.json');
|
||||||
options.buildLibsFromSource ??= true;
|
options['buildLibsFromSource'] ??= true;
|
||||||
|
|
||||||
if (!options.buildLibsFromSource) {
|
if (!options['buildLibsFromSource']) {
|
||||||
const { dependencies } = calculateProjectBuildableDependencies(
|
const { dependencies } = calculateProjectBuildableDependencies(
|
||||||
context.taskGraph,
|
context.taskGraph,
|
||||||
context.projectGraph,
|
context.projectGraph,
|
||||||
|
|||||||
@ -170,17 +170,13 @@ export function addOrChangeTestTarget(
|
|||||||
) {
|
) {
|
||||||
const project = readProjectConfiguration(tree, options.project);
|
const project = readProjectConfiguration(tree, options.project);
|
||||||
|
|
||||||
const coveragePath = joinPathFragments(
|
const reportsDirectory = joinPathFragments(
|
||||||
|
offsetFromRoot(project.root),
|
||||||
'coverage',
|
'coverage',
|
||||||
project.root === '.' ? options.project : project.root
|
project.root === '.' ? options.project : project.root
|
||||||
);
|
);
|
||||||
const testOptions: VitestExecutorOptions = {
|
const testOptions: VitestExecutorOptions = {
|
||||||
passWithNoTests: true,
|
reportsDirectory,
|
||||||
// vitest runs in the project root so we have to offset to the workspaceRoot
|
|
||||||
reportsDirectory: joinPathFragments(
|
|
||||||
offsetFromRoot(project.root),
|
|
||||||
coveragePath
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
project.targets ??= {};
|
project.targets ??= {};
|
||||||
@ -205,6 +201,7 @@ export function addOrChangeBuildTarget(
|
|||||||
target: string
|
target: string
|
||||||
) {
|
) {
|
||||||
const project = readProjectConfiguration(tree, options.project);
|
const project = readProjectConfiguration(tree, options.project);
|
||||||
|
|
||||||
const buildOptions: ViteBuildExecutorOptions = {
|
const buildOptions: ViteBuildExecutorOptions = {
|
||||||
outputPath: joinPathFragments(
|
outputPath: joinPathFragments(
|
||||||
'dist',
|
'dist',
|
||||||
@ -219,8 +216,8 @@ export function addOrChangeBuildTarget(
|
|||||||
project.targets[target].options?.fileReplacements;
|
project.targets[target].options?.fileReplacements;
|
||||||
|
|
||||||
if (project.targets[target].executor === '@nxext/vite:build') {
|
if (project.targets[target].executor === '@nxext/vite:build') {
|
||||||
buildOptions.base = project.targets[target].options?.baseHref;
|
buildOptions['base'] = project.targets[target].options?.baseHref;
|
||||||
buildOptions.sourcemap = project.targets[target].options?.sourcemaps;
|
buildOptions['sourcemap'] = project.targets[target].options?.sourcemaps;
|
||||||
}
|
}
|
||||||
project.targets[target].options = { ...buildOptions };
|
project.targets[target].options = { ...buildOptions };
|
||||||
project.targets[target].executor = '@nx/vite:build';
|
project.targets[target].executor = '@nx/vite:build';
|
||||||
@ -257,9 +254,6 @@ export function addOrChangeServeTarget(
|
|||||||
const serveTarget = project.targets[target];
|
const serveTarget = project.targets[target];
|
||||||
const serveOptions: ViteDevServerExecutorOptions = {
|
const serveOptions: ViteDevServerExecutorOptions = {
|
||||||
buildTarget: `${options.project}:build`,
|
buildTarget: `${options.project}:build`,
|
||||||
https: project.targets[target].options?.https,
|
|
||||||
hmr: project.targets[target].options?.hmr,
|
|
||||||
open: project.targets[target].options?.open,
|
|
||||||
};
|
};
|
||||||
if (serveTarget.executor === '@nxext/vite:dev') {
|
if (serveTarget.executor === '@nxext/vite:dev') {
|
||||||
serveOptions.proxyConfig = project.targets[target].options.proxyConfig;
|
serveOptions.proxyConfig = project.targets[target].options.proxyConfig;
|
||||||
@ -316,8 +310,8 @@ export function addPreviewTarget(
|
|||||||
if (target.executor === '@nxext/vite:dev') {
|
if (target.executor === '@nxext/vite:dev') {
|
||||||
previewOptions.proxyConfig = target.options.proxyConfig;
|
previewOptions.proxyConfig = target.options.proxyConfig;
|
||||||
}
|
}
|
||||||
previewOptions.https = target.options?.https;
|
previewOptions['https'] = target.options?.https;
|
||||||
previewOptions.open = target.options?.open;
|
previewOptions['open'] = target.options?.open;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a preview target.
|
// Adds a preview target.
|
||||||
@ -486,17 +480,21 @@ export interface ViteConfigFileOptions {
|
|||||||
rollupOptionsExternal?: string[];
|
rollupOptionsExternal?: string[];
|
||||||
imports?: string[];
|
imports?: string[];
|
||||||
plugins?: string[];
|
plugins?: string[];
|
||||||
|
coverageProvider?: 'v8' | 'istanbul' | 'custom';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createOrEditViteConfig(
|
export function createOrEditViteConfig(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: ViteConfigFileOptions,
|
options: ViteConfigFileOptions,
|
||||||
onlyVitest: boolean,
|
onlyVitest: boolean,
|
||||||
projectAlreadyHasViteTargets?: TargetFlags
|
projectAlreadyHasViteTargets?: TargetFlags,
|
||||||
|
vitestFileName?: boolean
|
||||||
) {
|
) {
|
||||||
const projectConfig = readProjectConfiguration(tree, options.project);
|
const { root: projectRoot } = readProjectConfiguration(tree, options.project);
|
||||||
|
|
||||||
const viteConfigPath = `${projectConfig.root}/vite.config.ts`;
|
const viteConfigPath = vitestFileName
|
||||||
|
? `${projectRoot}/vitest.config.ts`
|
||||||
|
: `${projectRoot}/vite.config.ts`;
|
||||||
|
|
||||||
const buildOption = onlyVitest
|
const buildOption = onlyVitest
|
||||||
? ''
|
? ''
|
||||||
@ -505,6 +503,7 @@ export function createOrEditViteConfig(
|
|||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
|
outDir: '${offsetFromRoot(projectRoot)}dist/${projectRoot}',
|
||||||
lib: {
|
lib: {
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
@ -517,9 +516,13 @@ export function createOrEditViteConfig(
|
|||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
// External packages that should not be bundled into your library.
|
// External packages that should not be bundled into your library.
|
||||||
external: [${options.rollupOptionsExternal ?? ''}]
|
external: [${options.rollupOptionsExternal ?? ''}]
|
||||||
}
|
},
|
||||||
},`
|
},`
|
||||||
: ``;
|
: `
|
||||||
|
build: {
|
||||||
|
outDir: '${offsetFromRoot(projectRoot)}dist/${projectRoot}',
|
||||||
|
},
|
||||||
|
`;
|
||||||
|
|
||||||
const imports: string[] = options.imports ? options.imports : [];
|
const imports: string[] = options.imports ? options.imports : [];
|
||||||
|
|
||||||
@ -546,15 +549,21 @@ export function createOrEditViteConfig(
|
|||||||
? `test: {
|
? `test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
cache: {
|
cache: {
|
||||||
dir: '${offsetFromRoot(projectConfig.root)}node_modules/.vitest'
|
dir: '${offsetFromRoot(projectRoot)}node_modules/.vitest'
|
||||||
},
|
},
|
||||||
environment: '${options.testEnvironment ?? 'jsdom'}',
|
environment: '${options.testEnvironment ?? 'jsdom'}',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
${
|
${
|
||||||
options.inSourceTests
|
options.inSourceTests
|
||||||
? `includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}']`
|
? `includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],`
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '${offsetFromRoot(projectRoot)}coverage/${projectRoot}',
|
||||||
|
provider: ${
|
||||||
|
options.coverageProvider ? `'${options.coverageProvider}'` : `'v8'`
|
||||||
|
},
|
||||||
|
}
|
||||||
},`
|
},`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
@ -591,8 +600,8 @@ export function createOrEditViteConfig(
|
|||||||
// },`;
|
// },`;
|
||||||
|
|
||||||
const cacheDir = `cacheDir: '${offsetFromRoot(
|
const cacheDir = `cacheDir: '${offsetFromRoot(
|
||||||
projectConfig.root
|
projectRoot
|
||||||
)}node_modules/.vite/${options.project}',`;
|
)}node_modules/.vite/${projectRoot}',`;
|
||||||
|
|
||||||
if (tree.exists(viteConfigPath)) {
|
if (tree.exists(viteConfigPath)) {
|
||||||
handleViteConfigFileExists(
|
handleViteConfigFileExists(
|
||||||
@ -604,7 +613,8 @@ export function createOrEditViteConfig(
|
|||||||
plugins,
|
plugins,
|
||||||
testOption,
|
testOption,
|
||||||
cacheDir,
|
cacheDir,
|
||||||
offsetFromRoot(projectConfig.root),
|
offsetFromRoot(projectRoot),
|
||||||
|
projectRoot,
|
||||||
projectAlreadyHasViteTargets
|
projectAlreadyHasViteTargets
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@ -617,6 +627,7 @@ export function createOrEditViteConfig(
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
${cacheDir}
|
${cacheDir}
|
||||||
${devServerOption}
|
${devServerOption}
|
||||||
${previewServerOption}
|
${previewServerOption}
|
||||||
@ -773,6 +784,7 @@ function handleViteConfigFileExists(
|
|||||||
testOption: string,
|
testOption: string,
|
||||||
cacheDir: string,
|
cacheDir: string,
|
||||||
offsetFromRoot: string,
|
offsetFromRoot: string,
|
||||||
|
projectRoot: string,
|
||||||
projectAlreadyHasViteTargets?: TargetFlags
|
projectAlreadyHasViteTargets?: TargetFlags
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
@ -788,17 +800,22 @@ function handleViteConfigFileExists(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildOptionObject = {
|
const buildOptionObject = options.includeLib
|
||||||
lib: {
|
? {
|
||||||
entry: 'src/index.ts',
|
lib: {
|
||||||
name: options.project,
|
entry: 'src/index.ts',
|
||||||
fileName: 'index',
|
name: options.project,
|
||||||
formats: ['es', 'cjs'],
|
fileName: 'index',
|
||||||
},
|
formats: ['es', 'cjs'],
|
||||||
rollupOptions: {
|
},
|
||||||
external: options.rollupOptionsExternal ?? [],
|
rollupOptions: {
|
||||||
},
|
external: options.rollupOptionsExternal ?? [],
|
||||||
};
|
},
|
||||||
|
outDir: `${offsetFromRoot}dist/${projectRoot}`,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
outDir: `${offsetFromRoot}dist/${projectRoot}`,
|
||||||
|
};
|
||||||
|
|
||||||
const testOptionObject = {
|
const testOptionObject = {
|
||||||
globals: true,
|
globals: true,
|
||||||
@ -807,6 +824,10 @@ function handleViteConfigFileExists(
|
|||||||
},
|
},
|
||||||
environment: options.testEnvironment ?? 'jsdom',
|
environment: options.testEnvironment ?? 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: `${offsetFromRoot}coverage/${projectRoot}`,
|
||||||
|
provider: `${options.coverageProvider ?? 'v8'}`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const changed = ensureViteConfigIsCorrect(
|
const changed = ensureViteConfigIsCorrect(
|
||||||
|
|||||||
@ -6,23 +6,14 @@ import {
|
|||||||
readTargetOptions,
|
readTargetOptions,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { existsSync } from 'fs';
|
import { existsSync } from 'fs';
|
||||||
import { relative } from 'path';
|
import { PreviewOptions, ServerOptions } from 'vite';
|
||||||
import {
|
|
||||||
BuildOptions,
|
|
||||||
InlineConfig,
|
|
||||||
PluginOption,
|
|
||||||
PreviewOptions,
|
|
||||||
ServerOptions,
|
|
||||||
} from 'vite';
|
|
||||||
import { ViteDevServerExecutorOptions } from '../executors/dev-server/schema';
|
import { ViteDevServerExecutorOptions } from '../executors/dev-server/schema';
|
||||||
import { VitePreviewServerExecutorOptions } from '../executors/preview-server/schema';
|
|
||||||
import replaceFiles from '../../plugins/rollup-replace-files.plugin';
|
|
||||||
import { ViteBuildExecutorOptions } from '../executors/build/schema';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the path to the vite config file or undefined when not found.
|
* Returns the path to the vite config file or undefined when not found.
|
||||||
*/
|
*/
|
||||||
export function normalizeViteConfigFilePath(
|
export function normalizeViteConfigFilePath(
|
||||||
|
contextRoot: string,
|
||||||
projectRoot: string,
|
projectRoot: string,
|
||||||
configFile?: string
|
configFile?: string
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
@ -35,11 +26,28 @@ export function normalizeViteConfigFilePath(
|
|||||||
}
|
}
|
||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
return existsSync(joinPathFragments(projectRoot, 'vite.config.ts'))
|
|
||||||
? joinPathFragments(projectRoot, 'vite.config.ts')
|
const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts'];
|
||||||
: existsSync(joinPathFragments(projectRoot, 'vite.config.js'))
|
|
||||||
? joinPathFragments(projectRoot, 'vite.config.js')
|
for (const ext of allowsExt) {
|
||||||
: undefined;
|
if (
|
||||||
|
existsSync(
|
||||||
|
joinPathFragments(contextRoot, projectRoot, `vite.config.${ext}`)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return joinPathFragments(contextRoot, projectRoot, `vite.config.${ext}`);
|
||||||
|
} else if (
|
||||||
|
existsSync(
|
||||||
|
joinPathFragments(contextRoot, projectRoot, `vitest.config.${ext}`)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return joinPathFragments(
|
||||||
|
contextRoot,
|
||||||
|
projectRoot,
|
||||||
|
`vitest.config.${ext}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProjectTsConfigPath(
|
export function getProjectTsConfigPath(
|
||||||
@ -75,36 +83,6 @@ export function getViteServerProxyConfigPath(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the shared options for vite.
|
|
||||||
*
|
|
||||||
* Most shared options are derived from the build target.
|
|
||||||
*/
|
|
||||||
export function getViteSharedConfig(
|
|
||||||
options: ViteBuildExecutorOptions,
|
|
||||||
clearScreen: boolean | undefined,
|
|
||||||
context: ExecutorContext
|
|
||||||
): InlineConfig {
|
|
||||||
const projectRoot =
|
|
||||||
context.projectsConfigurations.projects[context.projectName].root;
|
|
||||||
|
|
||||||
const root =
|
|
||||||
projectRoot === '.'
|
|
||||||
? process.cwd()
|
|
||||||
: relative(context.cwd, joinPathFragments(context.root, projectRoot));
|
|
||||||
|
|
||||||
return {
|
|
||||||
mode: options.mode,
|
|
||||||
root,
|
|
||||||
base: options.base,
|
|
||||||
configFile: normalizeViteConfigFilePath(projectRoot, options.configFile),
|
|
||||||
plugins: [replaceFiles(options.fileReplacements) as PluginOption],
|
|
||||||
optimizeDeps: { force: options.force },
|
|
||||||
clearScreen: clearScreen,
|
|
||||||
logLevel: options.logLevel,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the options for the vite dev server.
|
* Builds the options for the vite dev server.
|
||||||
*/
|
*/
|
||||||
@ -119,12 +97,6 @@ export async function getViteServerOptions(
|
|||||||
const projectRoot =
|
const projectRoot =
|
||||||
context.projectsConfigurations.projects[context.projectName].root;
|
context.projectsConfigurations.projects[context.projectName].root;
|
||||||
const serverOptions: ServerOptions = {
|
const serverOptions: ServerOptions = {
|
||||||
host: options.host,
|
|
||||||
port: options.port,
|
|
||||||
https: options.https,
|
|
||||||
hmr: options.hmr,
|
|
||||||
open: options.open,
|
|
||||||
cors: options.cors,
|
|
||||||
fs: {
|
fs: {
|
||||||
allow: [
|
allow: [
|
||||||
searchForWorkspaceRoot(joinPathFragments(projectRoot)),
|
searchForWorkspaceRoot(joinPathFragments(projectRoot)),
|
||||||
@ -145,53 +117,14 @@ export async function getViteServerOptions(
|
|||||||
return serverOptions;
|
return serverOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the build options for the vite.
|
|
||||||
*/
|
|
||||||
export function getViteBuildOptions(
|
|
||||||
options: ViteBuildExecutorOptions,
|
|
||||||
context: ExecutorContext
|
|
||||||
): BuildOptions {
|
|
||||||
const projectRoot =
|
|
||||||
context.projectsConfigurations.projects[context.projectName].root;
|
|
||||||
|
|
||||||
const outputPath = joinPathFragments(
|
|
||||||
'dist',
|
|
||||||
projectRoot != '.' ? projectRoot : context.projectName
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
outDir: relative(projectRoot, options.outputPath ?? outputPath),
|
|
||||||
emptyOutDir: options.emptyOutDir,
|
|
||||||
reportCompressedSize: true,
|
|
||||||
cssCodeSplit: options.cssCodeSplit,
|
|
||||||
target: options.target,
|
|
||||||
commonjsOptions: {
|
|
||||||
transformMixedEsModules: true,
|
|
||||||
},
|
|
||||||
sourcemap: options.sourcemap,
|
|
||||||
minify: options.minify,
|
|
||||||
manifest: options.manifest,
|
|
||||||
ssrManifest: options.ssrManifest,
|
|
||||||
ssr: options.ssr,
|
|
||||||
watch: options.watch as BuildOptions['watch'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the options for the vite preview server.
|
* Builds the options for the vite preview server.
|
||||||
*/
|
*/
|
||||||
export function getVitePreviewOptions(
|
export function getVitePreviewOptions(
|
||||||
options: VitePreviewServerExecutorOptions,
|
options: Record<string, any>,
|
||||||
context: ExecutorContext
|
context: ExecutorContext
|
||||||
): PreviewOptions {
|
): PreviewOptions {
|
||||||
const serverOptions: ServerOptions = {
|
const serverOptions: ServerOptions = {};
|
||||||
host: options.host,
|
|
||||||
port: options.port,
|
|
||||||
https: options.https,
|
|
||||||
open: options.open,
|
|
||||||
};
|
|
||||||
|
|
||||||
const proxyConfigPath = getViteServerProxyConfigPath(
|
const proxyConfigPath = getViteServerProxyConfigPath(
|
||||||
options.proxyConfig,
|
options.proxyConfig,
|
||||||
context
|
context
|
||||||
|
|||||||
@ -85,7 +85,12 @@ function handleBuildOrTestNode(
|
|||||||
let updatedPropsString = '';
|
let updatedPropsString = '';
|
||||||
for (const prop of existingProperties) {
|
for (const prop of existingProperties) {
|
||||||
const propName = prop.name.getText();
|
const propName = prop.name.getText();
|
||||||
if (!configContentObject[propName] && propName !== 'dir') {
|
if (
|
||||||
|
!configContentObject[propName] &&
|
||||||
|
propName !== 'dir' &&
|
||||||
|
propName !== 'reportsDirectory' &&
|
||||||
|
propName !== 'provider'
|
||||||
|
) {
|
||||||
updatedPropsString += `'${propName}': ${prop.initializer.getText()},\n`;
|
updatedPropsString += `'${propName}': ${prop.initializer.getText()},\n`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,7 @@ import vue from '@vitejs/plugin-vue';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/test',
|
cacheDir: '../node_modules/.vite/test',
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
@ -65,6 +66,10 @@ export default defineConfig({
|
|||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
// },
|
// },
|
||||||
|
|
||||||
|
build: {
|
||||||
|
outDir: '../dist/test',
|
||||||
|
},
|
||||||
|
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
cache: {
|
cache: {
|
||||||
@ -72,6 +77,11 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/test',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
@ -141,7 +151,6 @@ exports[`application generator should set up project correctly with given option
|
|||||||
"executor": "@nx/vite:test",
|
"executor": "@nx/vite:test",
|
||||||
"outputs": ["{options.reportsDirectory}"],
|
"outputs": ["{options.reportsDirectory}"],
|
||||||
"options": {
|
"options": {
|
||||||
"passWithNoTests": true,
|
|
||||||
"reportsDirectory": "../coverage/test"
|
"reportsDirectory": "../coverage/test"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import * as path from 'path';
|
|||||||
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
@ -56,6 +57,7 @@ export default defineConfig({
|
|||||||
// Configuration for building your library.
|
// Configuration for building your library.
|
||||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||||
build: {
|
build: {
|
||||||
|
outDir: '../dist/my-lib',
|
||||||
lib: {
|
lib: {
|
||||||
// Could also be a dictionary or array of multiple entry points.
|
// Could also be a dictionary or array of multiple entry points.
|
||||||
entry: 'src/index.ts',
|
entry: 'src/index.ts',
|
||||||
@ -78,6 +80,11 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/my-lib',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
|
|||||||
@ -404,7 +404,6 @@ describe('app', () => {
|
|||||||
it('should setup the nrwl vite:build builder if bundler is vite', async () => {
|
it('should setup the nrwl vite:build builder if bundler is vite', async () => {
|
||||||
await applicationGenerator(tree, {
|
await applicationGenerator(tree, {
|
||||||
name: 'my-app',
|
name: 'my-app',
|
||||||
|
|
||||||
bundler: 'vite',
|
bundler: 'vite',
|
||||||
projectNameAndRootFormat: 'as-provided',
|
projectNameAndRootFormat: 'as-provided',
|
||||||
});
|
});
|
||||||
|
|||||||
@ -22,7 +22,9 @@ export default async function addDroppedDependencies(tree: Tree) {
|
|||||||
projectConfiguration.targets ?? {}
|
projectConfiguration.targets ?? {}
|
||||||
)) {
|
)) {
|
||||||
for (const droppedDependency of droppedDependencies) {
|
for (const droppedDependency of droppedDependencies) {
|
||||||
if (targetConfiguration.executor?.startsWith(droppedDependency + ':')) {
|
if (
|
||||||
|
targetConfiguration?.['executor']?.startsWith(droppedDependency + ':')
|
||||||
|
) {
|
||||||
devDependencies[droppedDependency] = NX_VERSION;
|
devDependencies[droppedDependency] = NX_VERSION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,7 +37,9 @@ export default async function addDroppedDependencies(tree: Tree) {
|
|||||||
nxJson?.targetDefaults ?? {}
|
nxJson?.targetDefaults ?? {}
|
||||||
)) {
|
)) {
|
||||||
for (const droppedDependency of droppedDependencies) {
|
for (const droppedDependency of droppedDependencies) {
|
||||||
if (targetConfiguration.executor?.startsWith(droppedDependency + ':')) {
|
if (
|
||||||
|
targetConfiguration?.['executor']?.startsWith(droppedDependency + ':')
|
||||||
|
) {
|
||||||
devDependencies[droppedDependency] = NX_VERSION;
|
devDependencies[droppedDependency] = NX_VERSION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user