Created
May 16, 2023 05:43
-
-
Save ShayDavidson/e89751a5bc57a17ca6846dfd68aabf45 to your computer and use it in GitHub Desktop.
Override rollup executor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"builders": { | |
"rollup": { | |
"implementation": "./impl", | |
"schema": "./schema.json", | |
"description": "Custom rollup executor" | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
// THIS IS DUE TO THE FACT NX TEAM DIDN'T ADD A SIMPLE CONDITION TO ALLOW TYPE GENERATION | |
// https://github.com/nrwl/nx/issues/9059 | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
exports.createRollupOptions = exports.rollupExecutor = void 0; | |
const tslib_1 = require("tslib"); | |
require("dotenv/config"); | |
const ts = require("typescript"); | |
const rollup = require("rollup"); | |
const peerDepsExternal = require("rollup-plugin-peer-deps-external"); | |
const plugin_babel_1 = require("@rollup/plugin-babel"); | |
const path_1 = require("path"); | |
const rxjs_1 = require("rxjs"); | |
const operators_1 = require("rxjs/operators"); | |
const rxjs_for_await_1 = require("@nx/devkit/src/utils/rxjs-for-await"); | |
const autoprefixer = require("autoprefixer"); | |
const devkit_1 = require("@nx/devkit"); | |
const buildable_libs_utils_1 = require("@nx/js/src/utils/buildable-libs-utils"); | |
const plugin_node_resolve_1 = require("@rollup/plugin-node-resolve"); | |
const run_rollup_1 = require("@nx/rollup/src/executors/rollup/lib/run-rollup"); | |
const normalize_1 = require("@nx/rollup/src/executors/rollup/lib/normalize"); | |
const analyze_plugin_1 = require("@nx/rollup/src/executors/rollup/lib/analyze-plugin"); | |
const fs_1 = require("@nx/rollup/src/utils/fs"); | |
const swc_plugin_1 = require("@nx/rollup/src/executors/rollup/lib/swc-plugin"); | |
const validate_types_1 = require("@nx/rollup/src/executors/rollup/lib//validate-types"); | |
const update_package_json_1 = require("@nx/rollup/src/executors/rollup/lib//update-package-json"); | |
// These use require because the ES import isn't correct. | |
const commonjs = require('@rollup/plugin-commonjs'); | |
const image = require('@rollup/plugin-image'); | |
const json = require('@rollup/plugin-json'); | |
const copy = require('rollup-plugin-copy'); | |
const postcss = require('rollup-plugin-postcss'); | |
const fileExtensions = ['.js', '.jsx', '.ts', '.tsx']; | |
function rollupExecutor(rawOptions, context) { | |
var _a, _b; | |
var _c; | |
return tslib_1.__asyncGenerator(this, arguments, function* rollupExecutor_1() { | |
(_a = (_c = process.env).NODE_ENV) !== null && _a !== void 0 ? _a : (_c.NODE_ENV = 'production'); | |
const project = context.projectsConfigurations.projects[context.projectName]; | |
const sourceRoot = project.sourceRoot; | |
const { target, dependencies } = (0, buildable_libs_utils_1.calculateProjectDependencies)(context.projectGraph, context.root, context.projectName, context.targetName, context.configurationName, true); | |
const options = (0, normalize_1.normalizeRollupExecutorOptions)(rawOptions, context.root, sourceRoot); | |
const packageJson = (0, devkit_1.readJsonFile)(options.project); | |
const npmDeps = ((_b = context.projectGraph.dependencies[context.projectName]) !== null && _b !== void 0 ? _b : []) | |
.filter((d) => d.target.startsWith('npm:')) | |
.map((d) => d.target.slice(4)); | |
const rollupOptions = createRollupOptions(options, dependencies, context, packageJson, sourceRoot, npmDeps); | |
const outfile = resolveOutfile(context, options); | |
if (options.compiler === 'swc') { | |
try { | |
yield tslib_1.__await((0, validate_types_1.validateTypes)({ | |
workspaceRoot: context.root, | |
projectRoot: options.projectRoot, | |
tsconfig: options.tsConfig, | |
})); | |
} | |
catch (_d) { | |
return yield tslib_1.__await({ success: false }); | |
} | |
} | |
if (options.watch) { | |
const watcher = rollup.watch(rollupOptions); | |
return yield tslib_1.__await(yield tslib_1.__await(yield* tslib_1.__asyncDelegator(tslib_1.__asyncValues((0, rxjs_for_await_1.eachValueFrom)(new rxjs_1.Observable((obs) => { | |
watcher.on('event', (data) => { | |
if (data.code === 'START') { | |
devkit_1.logger.info(`Bundling ${context.projectName}...`); | |
} | |
else if (data.code === 'END') { | |
(0, update_package_json_1.updatePackageJson)(options, context, target, dependencies, packageJson); | |
devkit_1.logger.info('Bundle complete. Watching for file changes...'); | |
obs.next({ success: true, outfile }); | |
} | |
else if (data.code === 'ERROR') { | |
devkit_1.logger.error(`Error during bundle: ${data.error.message}`); | |
obs.next({ success: false }); | |
} | |
}); | |
// Teardown logic. Close watcher when unsubscribed. | |
return () => watcher.close(); | |
})))))); | |
} | |
else { | |
devkit_1.logger.info(`Bundling ${context.projectName}...`); | |
// Delete output path before bundling | |
if (options.deleteOutputPath) { | |
(0, fs_1.deleteOutputDir)(context.root, options.outputPath); | |
} | |
const start = process.hrtime.bigint(); | |
return yield tslib_1.__await((0, rxjs_1.from)(rollupOptions) | |
.pipe((0, operators_1.concatMap)((opts) => (0, run_rollup_1.runRollup)(opts).pipe((0, operators_1.catchError)((e) => { | |
devkit_1.logger.error(`Error during bundle: ${e}`); | |
return (0, rxjs_1.of)({ success: false }); | |
}))), (0, operators_1.scan)((acc, result) => { | |
if (!acc.success) | |
return acc; | |
return result; | |
}, { success: true, outfile }), (0, operators_1.last)(), (0, operators_1.tap)({ | |
next: (result) => { | |
if (result.success) { | |
const end = process.hrtime.bigint(); | |
const duration = `${(Number(end - start) / 1000000000).toFixed(2)}s`; | |
(0, update_package_json_1.updatePackageJson)(options, context, target, dependencies, packageJson); | |
devkit_1.logger.info(`⚡ Done in ${duration}`); | |
} | |
else { | |
devkit_1.logger.error(`Bundle failed: ${context.projectName}`); | |
} | |
}, | |
})) | |
.toPromise()); | |
} | |
}); | |
} | |
exports.rollupExecutor = rollupExecutor; | |
// ----------------------------------------------------------------------------- | |
function createRollupOptions(options, dependencies, context, packageJson, sourceRoot, npmDeps) { | |
const useBabel = options.compiler === 'babel'; | |
const useTsc = options.compiler === 'tsc'; | |
const useSwc = options.compiler === 'swc'; | |
const tsConfigPath = (0, devkit_1.joinPathFragments)(context.root, options.tsConfig); | |
const configFile = ts.readConfigFile(tsConfigPath, ts.sys.readFile); | |
const config = ts.parseJsonConfigFileContent(configFile.config, ts.sys, (0, path_1.dirname)(tsConfigPath)); | |
if (!options.format || !options.format.length) { | |
options.format = readCompatibleFormats(config); | |
} | |
return options.format.map((format, idx) => { | |
const plugins = [ | |
copy({ | |
targets: convertCopyAssetsToRollupOptions(options.outputPath, options.assets), | |
}), | |
image(), | |
json(), | |
require('rollup-plugin-typescript2')({ | |
check: !options.skipTypeCheck, | |
tsconfig: options.tsConfig, | |
tsconfigOverride: { | |
compilerOptions: createTsCompilerOptions(config, dependencies, options), | |
}, | |
}), | |
peerDepsExternal({ | |
packageJsonPath: options.project, | |
}), | |
postcss({ | |
inject: true, | |
extract: options.extractCss, | |
autoModules: true, | |
plugins: [autoprefixer], | |
use: { | |
less: { | |
javascriptEnabled: options.javascriptEnabled, | |
}, | |
}, | |
}), | |
(0, plugin_node_resolve_1.default)({ | |
preferBuiltins: true, | |
extensions: fileExtensions, | |
}), | |
useSwc && (0, swc_plugin_1.swc)(), | |
useBabel && | |
(0, plugin_babel_1.getBabelInputPlugin)({ | |
// Lets `@nx/js/babel` preset know that we are packaging. | |
caller: { | |
// @ts-ignore | |
// Ignoring type checks for caller since we have custom attributes | |
isNxPackage: true, | |
// Always target esnext and let rollup handle cjs | |
supportsStaticESM: true, | |
isModern: true, | |
}, | |
cwd: (0, path_1.join)(context.root, sourceRoot), | |
rootMode: 'upward', | |
babelrc: true, | |
extensions: fileExtensions, | |
babelHelpers: 'bundled', | |
skipPreflightCheck: true, | |
exclude: /node_modules/, | |
plugins: [ | |
format === 'esm' | |
? undefined | |
: require.resolve('babel-plugin-transform-async-to-promises'), | |
].filter(Boolean), | |
}), | |
commonjs(), | |
(0, analyze_plugin_1.analyze)(), | |
]; | |
let externalPackages = [ | |
...Object.keys(packageJson.dependencies || {}), | |
...Object.keys(packageJson.peerDependencies || {}), | |
]; // If external is set to none, include all dependencies and peerDependencies in externalPackages | |
if (options.external === 'all') { | |
externalPackages = externalPackages | |
.concat(dependencies.map((d) => d.name)) | |
.concat(npmDeps); | |
} | |
else if (Array.isArray(options.external) && options.external.length > 0) { | |
externalPackages = externalPackages.concat(options.external); | |
} | |
externalPackages = [...new Set(externalPackages)]; | |
const rollupConfig = { | |
input: options.outputFileName | |
? { | |
[(0, path_1.parse)(options.outputFileName).name]: options.main, | |
} | |
: options.main, | |
output: { | |
format, | |
dir: `${options.outputPath}`, | |
name: (0, devkit_1.names)(context.projectName).className, | |
entryFileNames: `[name].${format === 'esm' ? 'js' : 'cjs'}`, | |
chunkFileNames: `[name].${format === 'esm' ? 'js' : 'cjs'}`, | |
}, | |
external: (id) => { | |
return externalPackages.some((name) => id === name || id.startsWith(`${name}/`)); // Could be a deep import | |
}, | |
plugins, | |
}; | |
return options.rollupConfig.reduce((currentConfig, plugin) => { | |
return require(plugin)(currentConfig, options); | |
}, rollupConfig); | |
}); | |
} | |
exports.createRollupOptions = createRollupOptions; | |
function createTsCompilerOptions(config, dependencies, options) { | |
const compilerOptionPaths = (0, buildable_libs_utils_1.computeCompilerOptionsPaths)(config, dependencies); | |
const compilerOptions = { | |
rootDir: options.projectRoot, | |
allowJs: options.allowJs, | |
declaration: true, | |
paths: compilerOptionPaths, | |
}; | |
if (config.options.module === ts.ModuleKind.CommonJS) { | |
compilerOptions['module'] = 'ESNext'; | |
} | |
return compilerOptions; | |
} | |
function convertCopyAssetsToRollupOptions(outputPath, assets) { | |
return assets | |
? assets.map((a) => ({ | |
src: (0, path_1.join)(a.input, a.glob).replace(/\\/g, '/'), | |
dest: (0, path_1.join)(outputPath, a.output).replace(/\\/g, '/'), | |
})) | |
: undefined; | |
} | |
function readCompatibleFormats(config) { | |
switch (config.options.module) { | |
case ts.ModuleKind.CommonJS: | |
case ts.ModuleKind.UMD: | |
case ts.ModuleKind.AMD: | |
return ['cjs']; | |
default: | |
return ['esm']; | |
} | |
} | |
function resolveOutfile(context, options) { | |
var _a, _b; | |
if (!((_a = options.format) === null || _a === void 0 ? void 0 : _a.includes('cjs'))) | |
return undefined; | |
const { name } = (0, path_1.parse)((_b = options.outputFileName) !== null && _b !== void 0 ? _b : options.main); | |
return (0, path_1.resolve)(context.root, options.outputPath, `${name}.cjs`); | |
} | |
exports.default = (0, devkit_1.convertNxExecutor)(rollupExecutor); | |
//# sourceMappingURL=rollup.impl.js.map |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"builders": "./builder.json" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"version": 2, | |
"outputCapture": "direct-nodejs", | |
"title": "Web Library Rollup Target (Experimental)", | |
"description": "Packages a library for different web usages (ESM, CommonJS).", | |
"cli": "nx", | |
"type": "object", | |
"presets": [ | |
{ | |
"name": "Including Dependencies in package.json", | |
"keys": [ | |
"main", | |
"outputPath", | |
"project", | |
"tsConfig", | |
"buildableProjectDepsInPackageJsonType", | |
"updateBuildableProjectDepsInPackageJson" | |
] | |
} | |
], | |
"properties": { | |
"project": { | |
"type": "string", | |
"description": "The path to package.json file.", | |
"x-priority": "important" | |
}, | |
"main": { | |
"type": "string", | |
"description": "The path to the entry file, relative to project.", | |
"alias": "entryFile", | |
"x-completion-type": "file", | |
"x-completion-glob": "**/*@(.js|.ts)", | |
"x-priority": "important" | |
}, | |
"outputPath": { | |
"type": "string", | |
"description": "The output path of the generated files.", | |
"x-completion-type": "directory", | |
"x-priority": "important" | |
}, | |
"outputFileName": { | |
"type": "string", | |
"description": "Name of the main output file. Defaults same basename as 'main' file." | |
}, | |
"deleteOutputPath": { | |
"type": "boolean", | |
"description": "Delete the output path before building.", | |
"default": true | |
}, | |
"tsConfig": { | |
"type": "string", | |
"description": "The path to tsconfig file.", | |
"x-completion-type": "file", | |
"x-completion-glob": "tsconfig.*.json", | |
"x-priority": "important" | |
}, | |
"allowJs": { | |
"type": "boolean", | |
"description": "Allow JavaScript files to be compiled.", | |
"default": false | |
}, | |
"format": { | |
"type": "array", | |
"description": "List of module formats to output. Defaults to matching format from tsconfig (e.g. CJS for CommonJS, and ESM otherwise).", | |
"alias": "f", | |
"items": { | |
"type": "string", | |
"enum": ["esm", "cjs"] | |
} | |
}, | |
"external": { | |
"type": "array", | |
"description": "A list of external modules that will not be bundled (`react`, `react-dom`, etc.).", | |
"oneOf": [ | |
{ | |
"type": "string", | |
"enum": ["all", "none"] | |
}, | |
{ | |
"type": "array", | |
"items": { | |
"type": "string" | |
} | |
} | |
] | |
}, | |
"watch": { | |
"type": "boolean", | |
"description": "Enable re-building when files change.", | |
"default": false | |
}, | |
"updateBuildableProjectDepsInPackageJson": { | |
"type": "boolean", | |
"description": "Update buildable project dependencies in `package.json`.", | |
"default": true | |
}, | |
"buildableProjectDepsInPackageJsonType": { | |
"type": "string", | |
"description": "When `updateBuildableProjectDepsInPackageJson` is `true`, this adds dependencies to either `peerDependencies` or `dependencies`.", | |
"enum": ["dependencies", "peerDependencies"], | |
"default": "peerDependencies" | |
}, | |
"rollupConfig": { | |
"oneOf": [ | |
{ | |
"type": "array", | |
"items": { | |
"type": "string", | |
"x-completion-type": "file", | |
"x-completion-glob": "rollup?(*)@(.js|.ts)" | |
} | |
}, | |
{ | |
"type": "string", | |
"x-completion-type": "file", | |
"x-completion-glob": "rollup?(*)@(.js|.ts)" | |
} | |
], | |
"description": "Path to a function which takes a rollup config and returns an updated rollup config." | |
}, | |
"extractCss": { | |
"type": ["boolean", "string"], | |
"description": "CSS files will be extracted to the output folder. Alternatively custom filename can be provided (e.g. styles.css)", | |
"default": true | |
}, | |
"assets": { | |
"type": "array", | |
"description": "List of static assets.", | |
"default": [], | |
"items": { | |
"$ref": "#/definitions/assetPattern" | |
} | |
}, | |
"compiler": { | |
"type": "string", | |
"enum": ["babel", "swc", "tsc"], | |
"default": "babel", | |
"description": "Which compiler to use." | |
}, | |
"javascriptEnabled": { | |
"type": "boolean", | |
"description": "Sets `javascriptEnabled` option for less loader", | |
"default": false | |
}, | |
"generateExportsField": { | |
"type": "boolean", | |
"description": "Generate package.json with 'exports' field. This field defines entry points in the package and is used by Node and the TypeScript compiler.", | |
"default": false | |
}, | |
"skipTypeCheck": { | |
"type": "boolean", | |
"description": "Whether to skip TypeScript type checking.", | |
"default": false | |
} | |
}, | |
"required": ["tsConfig", "main", "outputPath"], | |
"definitions": { | |
"assetPattern": { | |
"oneOf": [ | |
{ | |
"type": "object", | |
"properties": { | |
"glob": { | |
"type": "string", | |
"description": "The pattern to match." | |
}, | |
"input": { | |
"type": "string", | |
"description": "The input directory path in which to apply `glob`. Defaults to the project root." | |
}, | |
"output": { | |
"type": "string", | |
"description": "Relative path within the output folder." | |
} | |
}, | |
"additionalProperties": false, | |
"required": ["glob", "input", "output"] | |
}, | |
{ | |
"type": "string" | |
} | |
] | |
} | |
}, | |
"examplesFile": "../../docs/rollup-examples.md" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment