Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document and fix this.addWatchFile plugin context function #2633

Merged
merged 1 commit into from Jan 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Expand Up @@ -57,8 +57,8 @@
- transformChunk
- ongenerate
- onwrite
* Plugin transform dependencies are deprecated in favour of the `watchChange` plugin hook (#2409)
* Accessing `this.watcher` in plugin hooks is deprecated in favour of the `watchChange` plugin hook (#2409)
* Plugin transform dependencies are deprecated in favour of using the `this.addWatchFile` plugin context function (#2409)
* Accessing `this.watcher` in plugin hooks is deprecated in favour of the `watchChange` plugin hook and the `this.addWatchFile` plugin context function (#2409)
* Using dynamic import statements will by default create a new chunk unless `inlineDynamicImports` is used (#2293)
* Rollup now uses acorn@6 which means that acorn plugins must be compatible with this version; acorn is now external for non-browser builds to make plugins work (#2293)

Expand Down
10 changes: 9 additions & 1 deletion docs/05-plugins.md
Expand Up @@ -169,7 +169,7 @@ Defines a custom resolver. A resolver loader can be useful for e.g. locating thi
#### `transform`
Type: `(code: string, id: string) => string | { code: string, map?: string | SourceMap, ast? : ESTree.Program } | null | Promise<...>`

Can be used to transform individual modules.
Can be used to transform individual modules. Note that in watch mode, the result of this hook is cached when rebuilding and the hook is only triggered again for a module `id` if either the `code` of the module has changed or a file has changed that was added via `this.addWatchFile` the last time the hook was triggered for this module.

#### `watchChange`
Type: `(id: string) => void`
Expand Down Expand Up @@ -199,6 +199,14 @@ More properties may be supported in future, as and when they prove necessary.

A number of utility functions and informational bits can be accessed from within all [hooks](guide/en#hooks) via `this`:

#### `this.addWatchFile(id: string) => void`

Adds additional files to be monitored in watch mode so that changes to these files will trigger rebuilds. `id` can be an absolute path to a file or directory or a path relative to the current working directory. This context function can only be used in hooks during the build phase, i.e. in `buildStart`, `load`, `resolveId`, and `transform`.

**Note:** Usually in watch mode to improve rebuild speed, the `transform` hook will only be triggered for a given module if its contents actually changed. Using `this.addWatchFile` from within the `transform` hook will make sure the `transform` hook is also reevaluated for this module if the watched file changes.

In general, it is recommended to use `this.addWatchfile` from within the hook that depends on the watched file.

#### `this.emitAsset(assetName: string, source: string) => void`

Emits a custom file to include in the build output, returning its `assetId`. You can defer setting the source if you provide it later via `this.setAssetSource(assetId)`. A string or Buffer source must be set for each asset through either method or an error will be thrown on generate completion.
Expand Down
15 changes: 8 additions & 7 deletions src/utils/pluginDriver.ts
Expand Up @@ -57,18 +57,17 @@ export function createPluginDriver(
): PluginDriver {
const plugins = [...(options.plugins || []), getRollupDefaultPlugin(options)];
const { emitAsset, getAssetFileName, setAssetSource } = createAssetPluginHooks(graph.assetsById);
const existingPluginKeys: string[] = [];
const existingPluginKeys: { [key: string]: true } = {};

let hasLoadersOrTransforms = false;

const pluginContexts: PluginContext[] = plugins.map((plugin, pidx) => {
let cacheable = true;
if (typeof plugin.cacheKey !== 'string') {
if (typeof plugin.name !== 'string') {
if (typeof plugin.name !== 'string' || existingPluginKeys[plugin.name]) {
cacheable = false;
} else {
if (existingPluginKeys.indexOf(plugin.name) !== -1) cacheable = false;
existingPluginKeys.push(plugin.name);
existingPluginKeys[plugin.name] = true;
}
}

Expand All @@ -90,14 +89,16 @@ export function createPluginDriver(
cacheInstance = uncacheablePlugin(plugin.name);
}

const firstWatchHandler = true;
let watcherDeprecationWarningShown = false;

function deprecatedWatchListener(event: string, handler: () => void): EventEmitter {
if (firstWatchHandler)
if (!watcherDeprecationWarningShown) {
context.warn({
code: 'PLUGIN_WATCHER_DEPRECATED',
message: `this.watcher usage is deprecated in plugins. Use the watchChange plugin hook instead.`
message: `this.watcher usage is deprecated in plugins. Use the watchChange plugin hook and this.addWatchFile() instead.`
});
watcherDeprecationWarningShown = true;
}
return watcher.on(event, handler);
}

Expand Down
5 changes: 5 additions & 0 deletions src/utils/transform.ts
Expand Up @@ -130,6 +130,11 @@ export default function transform(
pluginContext.error(err);
},
emitAsset,
addWatchFile(id: string) {
if (!transformDependencies) transformDependencies = [];
transformDependencies.push(id);
pluginContext.addWatchFile(id);
},
setAssetSource(assetId, source) {
pluginContext.setAssetSource(assetId, source);
if (!customTransformCache && !setAssetSourceErr) {
Expand Down
2 changes: 1 addition & 1 deletion test/hooks/index.js
Expand Up @@ -1139,7 +1139,7 @@ module.exports = input;
assert.equal(warning.pluginCode, 'PLUGIN_WATCHER_DEPRECATED');
assert.equal(
warning.message,
'this.watcher usage is deprecated in plugins. Use the watchChange plugin hook instead.'
'this.watcher usage is deprecated in plugins. Use the watchChange plugin hook and this.addWatchFile() instead.'
);
},
plugins: [
Expand Down