diff --git a/packages/rollup/plugin.ts b/packages/rollup/plugin.ts index 5fe67b97f727b..b89b934cfa380 100644 --- a/packages/rollup/plugin.ts +++ b/packages/rollup/plugin.ts @@ -1 +1,5 @@ -export { createNodes, RollupPluginOptions } from './src/plugins/plugin'; +export { + createNodes, + createNodesV2, + RollupPluginOptions, +} from './src/plugins/plugin'; diff --git a/packages/rollup/src/plugins/__snapshots__/plugin.spec.ts.snap b/packages/rollup/src/plugins/__snapshots__/plugin.spec.ts.snap index c33b815791263..f7d8977bb8fec 100644 --- a/packages/rollup/src/plugins/__snapshots__/plugin.spec.ts.snap +++ b/packages/rollup/src/plugins/__snapshots__/plugin.spec.ts.snap @@ -1,70 +1,110 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`@nx/rollup/plugin non-root project should create nodes 1`] = ` -{ - "projects": { - "mylib": { - "root": "mylib", - "targets": { - "build": { - "cache": true, - "command": "rollup -c rollup.config.js", - "dependsOn": [ - "^build", - ], - "inputs": [ - "production", - "^production", - { - "externalDependencies": [ - "rollup", +[ + [ + "mylib/rollup.config.js", + { + "projects": { + "mylib": { + "root": "mylib", + "targets": { + "build": { + "cache": true, + "command": "rollup -c rollup.config.js", + "dependsOn": [ + "^build", + ], + "inputs": [ + "production", + "^production", + { + "externalDependencies": [ + "rollup", + ], + }, + ], + "metadata": { + "description": "Run Rollup", + "help": { + "command": "npx rollup --help", + "example": { + "options": { + "sourcemap": true, + "watch": true, + }, + }, + }, + "technologies": [ + "rollup", + ], + }, + "options": { + "cwd": "mylib", + }, + "outputs": [ + "{workspaceRoot}/mylib/build", + "{workspaceRoot}/mylib/dist", ], }, - ], - "options": { - "cwd": "mylib", }, - "outputs": [ - "{workspaceRoot}/mylib/build", - "{workspaceRoot}/mylib/dist", - ], }, }, }, - }, -} + ], +] `; exports[`@nx/rollup/plugin root project should create nodes 1`] = ` -{ - "projects": { - ".": { - "root": ".", - "targets": { - "build": { - "cache": true, - "command": "rollup -c rollup.config.js", - "dependsOn": [ - "^build", - ], - "inputs": [ - "production", - "^production", - { - "externalDependencies": [ - "rollup", +[ + [ + "rollup.config.js", + { + "projects": { + ".": { + "root": ".", + "targets": { + "build": { + "cache": true, + "command": "rollup -c rollup.config.js", + "dependsOn": [ + "^build", + ], + "inputs": [ + "production", + "^production", + { + "externalDependencies": [ + "rollup", + ], + }, + ], + "metadata": { + "description": "Run Rollup", + "help": { + "command": "npx rollup --help", + "example": { + "options": { + "sourcemap": true, + "watch": true, + }, + }, + }, + "technologies": [ + "rollup", + ], + }, + "options": { + "cwd": ".", + }, + "outputs": [ + "{workspaceRoot}/dist", ], }, - ], - "options": { - "cwd": ".", }, - "outputs": [ - "{workspaceRoot}/dist", - ], }, }, }, - }, -} + ], +] `; diff --git a/packages/rollup/src/plugins/plugin.spec.ts b/packages/rollup/src/plugins/plugin.spec.ts index 8a974380e7c22..67c7b6e8202ae 100644 --- a/packages/rollup/src/plugins/plugin.spec.ts +++ b/packages/rollup/src/plugins/plugin.spec.ts @@ -1,5 +1,5 @@ import { type CreateNodesContext } from '@nx/devkit'; -import { createNodes } from './plugin'; +import { createNodesV2 } from './plugin'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; // Jest 29 does not support dynamic import() unless --experimental-vm-modules is set. @@ -11,7 +11,7 @@ jest.mock('rollup/loadConfigFile', () => { }); describe('@nx/rollup/plugin', () => { - let createNodesFunction = createNodes[1]; + let createNodesFunction = createNodesV2[1]; let context: CreateNodesContext; let cwd = process.cwd(); @@ -77,7 +77,7 @@ describe('@nx/rollup/plugin', () => { it('should create nodes', async () => { // ACT const nodes = await createNodesFunction( - 'rollup.config.js', + ['rollup.config.js'], { buildTargetName: 'build', }, @@ -154,7 +154,7 @@ describe('@nx/rollup/plugin', () => { it('should create nodes', async () => { // ACT const nodes = await createNodesFunction( - 'mylib/rollup.config.js', + ['mylib/rollup.config.js'], { buildTargetName: 'build', }, diff --git a/packages/rollup/src/plugins/plugin.ts b/packages/rollup/src/plugins/plugin.ts index d46690c8d5c79..0c4ec4d8c5c75 100644 --- a/packages/rollup/src/plugins/plugin.ts +++ b/packages/rollup/src/plugins/plugin.ts @@ -5,8 +5,12 @@ import { type CreateDependencies, type CreateNodes, CreateNodesContext, + createNodesFromFiles, + CreateNodesV2, detectPackageManager, + getPackageManagerCommand, joinPathFragments, + logger, readJsonFile, type TargetConfiguration, writeJsonFile, @@ -15,27 +19,27 @@ import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash import { getLockFileName } from '@nx/js'; import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs'; import { type RollupOptions } from 'rollup'; +import { hashObject } from 'nx/src/hasher/file-hasher'; -const cachePath = join(workspaceDataDirectory, 'rollup.hash'); -const targetsCache = readTargetsCache(); +const pmc = getPackageManagerCommand(); -function readTargetsCache(): Record< - string, - Record -> { +function readTargetsCache( + cachePath: string +): Record> { return existsSync(cachePath) ? readJsonFile(cachePath) : {}; } -function writeTargetsToCache() { - const oldCache = readTargetsCache(); - writeJsonFile(cachePath, { - ...oldCache, - ...targetsCache, - }); +function writeTargetsToCache( + cachePath: string, + results: Record> +) { + writeJsonFile(cachePath, results); } +/** + * @deprecated The 'createDependencies' function is now a no-op. This functionality is included in 'createNodesV2'. + */ export const createDependencies: CreateDependencies = () => { - writeTargetsToCache(); return []; }; @@ -43,47 +47,95 @@ export interface RollupPluginOptions { buildTargetName?: string; } +const rollupConfigGlob = '**/rollup.config.{js,cjs,mjs}'; + export const createNodes: CreateNodes = [ - '**/rollup.config.{js,cjs,mjs}', + rollupConfigGlob, async (configFilePath, options, context) => { - const projectRoot = dirname(configFilePath); - const fullyQualifiedProjectRoot = join(context.workspaceRoot, projectRoot); - // Do not create a project if package.json and project.json do not exist - const siblingFiles = readdirSync(fullyQualifiedProjectRoot); - if ( - !siblingFiles.includes('package.json') && - !siblingFiles.includes('project.json') - ) { - return {}; - } - - options = normalizeOptions(options); - - const hash = await calculateHashForCreateNodes( - projectRoot, - options, - context, - [getLockFileName(detectPackageManager(context.workspaceRoot))] + logger.warn( + '`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.' ); - - targetsCache[hash] ??= await buildRollupTarget( + return createNodesInternal( configFilePath, - projectRoot, - options, - context + normalizeOptions(options), + context, + {} ); + }, +]; - return { - projects: { - [projectRoot]: { - root: projectRoot, - targets: targetsCache[hash], - }, - }, - }; +export const createNodesV2: CreateNodesV2 = [ + rollupConfigGlob, + async (configFilePaths, options, context) => { + const normalizedOptions = normalizeOptions(options); + const optionsHash = hashObject(normalizedOptions); + const cachePath = join( + workspaceDataDirectory, + `rollup-${optionsHash}.hash` + ); + const targetsCache = readTargetsCache(cachePath); + + try { + return await createNodesFromFiles( + (configFile, _, context) => + createNodesInternal( + configFile, + normalizedOptions, + context, + targetsCache + ), + configFilePaths, + normalizedOptions, + context + ); + } finally { + writeTargetsToCache(cachePath, targetsCache); + } }, ]; +async function createNodesInternal( + configFilePath: string, + options: Required, + context: CreateNodesContext, + targetsCache: Record> +) { + const projectRoot = dirname(configFilePath); + const fullyQualifiedProjectRoot = join(context.workspaceRoot, projectRoot); + + // Do not create a project if package.json and project.json do not exist + const siblingFiles = readdirSync(fullyQualifiedProjectRoot); + if ( + !siblingFiles.includes('package.json') && + !siblingFiles.includes('project.json') + ) { + return {}; + } + + const hash = await calculateHashForCreateNodes( + projectRoot, + options, + context, + [getLockFileName(detectPackageManager(context.workspaceRoot))] + ); + + targetsCache[hash] ??= await buildRollupTarget( + configFilePath, + projectRoot, + options, + context + ); + + return { + projects: { + [projectRoot]: { + root: projectRoot, + targets: targetsCache[hash], + }, + }, + }; +} + async function buildRollupTarget( configFilePath: string, projectRoot: string, @@ -134,6 +186,19 @@ async function buildRollupTarget( { externalDependencies: ['rollup'] }, ], outputs, + metadata: { + technologies: ['rollup'], + description: 'Run Rollup', + help: { + command: `${pmc.exec} rollup --help`, + example: { + options: { + sourcemap: true, + watch: true, + }, + }, + }, + }, }; return targets; } @@ -173,9 +238,10 @@ function getOutputs( return Array.from(outputs); } -function normalizeOptions(options: RollupPluginOptions) { - options ??= {}; - options.buildTargetName ??= 'build'; - - return options; +function normalizeOptions( + options: RollupPluginOptions +): Required { + return { + buildTargetName: options.buildTargetName ?? 'build', + }; }