diff --git a/docs/05-plugins.md b/docs/05-plugins.md
index 7130a9ecfd3..a5b14232d73 100644
--- a/docs/05-plugins.md
+++ b/docs/05-plugins.md
@@ -147,7 +147,7 @@ Defines a custom loader. Returning `null` defers to other `load` functions (and
Type: `(options: InputOptions) => InputOptions | null`
Kind: `sync, sequential`
-Reads and replaces or manipulates the options object passed to `rollup.rollup`. Returning `null` does not replace anything.
+Reads and replaces or manipulates the options object passed to `rollup.rollup`. Returning `null` does not replace anything. This is the only hook that does not have access to most [plugin context](guide/en#plugin-context) utility functions as it is run before rollup is fully configured.
#### `outro`
Type: `string | (() => string)`
@@ -225,7 +225,7 @@ More properties may be supported in future, as and when they prove necessary.
### Plugin Context
-A number of utility functions and informational bits can be accessed from within all [hooks](guide/en#hooks) via `this`:
+A number of utility functions and informational bits can be accessed from within most [hooks](guide/en#hooks) via `this`:
#### `this.addWatchFile(id: string) => void`
@@ -267,7 +267,7 @@ Determine if a given module ID is external.
#### `this.meta: {rollupVersion: string}`
-An `Object` containing potentially useful Rollup metadata.
+An `Object` containing potentially useful Rollup metadata. `meta` is the only context property accessible from the [`options`](guide/en#options) hook.
#### `this.moduleIds: IterableIterator`
diff --git a/src/rollup/index.ts b/src/rollup/index.ts
index 1950afad5a4..a24e1662069 100644
--- a/src/rollup/index.ts
+++ b/src/rollup/index.ts
@@ -1,3 +1,4 @@
+import { version as rollupVersion } from 'package.json';
import Chunk from '../Chunk';
import { optimizeChunks } from '../chunk-optimization';
import Graph from '../Graph';
@@ -59,7 +60,8 @@ const throwAsyncGenerateError = {
};
function applyOptionHook(inputOptions: InputOptions, plugin: Plugin) {
- if (plugin.options) return plugin.options(inputOptions) || inputOptions;
+ if (plugin.options)
+ return plugin.options.call({ meta: { rollupVersion } }, inputOptions) || inputOptions;
return inputOptions;
}
@@ -144,7 +146,7 @@ export default function rollup(rawInputOptions: GenericConfigObject): Promise
graph.build(
inputOptions.input,
diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts
index 80575b9f25c..4eca8448153 100644
--- a/src/rollup/types.d.ts
+++ b/src/rollup/types.d.ts
@@ -104,14 +104,17 @@ export interface PluginCache {
delete(id: string): boolean;
}
-export interface PluginContext {
+export interface MinimalPluginContext {
+ meta: PluginContextMeta;
+}
+
+export interface PluginContext extends MinimalPluginContext {
/** @deprecated */
watcher: EventEmitter;
addWatchFile: (id: string) => void;
cache: PluginCache;
resolveId: ResolveIdHook;
isExternal: IsExternal;
- meta: PluginContextMeta;
parse: (input: string, options: any) => ESTree.Program;
emitAsset(name: string, source?: string | Buffer): string;
setAssetSource: (assetId: string, source: string | Buffer) => void;
@@ -228,7 +231,7 @@ export interface Plugin {
options: OutputOptions,
chunk: OutputChunk
) => void | Promise;
- options?: (options: InputOptions) => InputOptions | void | null;
+ options?: (this: MinimalPluginContext, options: InputOptions) => InputOptions | void | null;
outro?: AddonHook;
renderChunk?: RenderChunkHook;
renderError?: (this: PluginContext, err?: Error) => Promise | void;
diff --git a/test/hooks/index.js b/test/hooks/index.js
index 6b85bac1269..769d295f995 100644
--- a/test/hooks/index.js
+++ b/test/hooks/index.js
@@ -5,6 +5,30 @@ const { loader } = require('../utils.js');
const rollup = require('../../dist/rollup.js');
describe('hooks', () => {
+ it('allows to read and modify options in the options hook', () => {
+ return rollup
+ .rollup({
+ input: 'input',
+ treeshake: false,
+ plugins: [
+ loader({ newInput: `alert('hello')` }),
+ {
+ buildStart(options) {
+ assert.strictEqual(options.input, 'newInput');
+ assert.strictEqual(options.treeshake, false);
+ },
+ options(options) {
+ assert.strictEqual(options.input, 'input');
+ assert.strictEqual(options.treeshake, false);
+ assert.ok(/^\d+\.\d+\.\d+/.test(this.meta.rollupVersion));
+ return Object.assign({}, options, { input: 'newInput' });
+ }
+ }
+ ]
+ })
+ .then(bundle => {});
+ });
+
it('supports buildStart and buildEnd hooks', () => {
let buildStartCnt = 0;
let buildEndCnt = 0;