---
title: "Writing JavaScript Plugins"
locale: "en"
version: "1.x"
canonicalUrl: "https://farmfe.org/docs/1.x/plugins/writing-plugins/js-plugin"
publicationStatus: "prerelease"
---

<a id="writing-javascript-plugins"></a>
# Writing JavaScript Plugins


A JavaScript plugin is simply a pure JavaScript object that defines a set of property hooks:


```js
// farm.config.ts
import { defineConfig } from "@farmfe/core";

export default defineConfig({
  // ...
  plugins: [
    // a plugin object
    {
      name: "my-resolve-plugin",
      priority: 1000, // the priority of this plugin, the larger the value, the earlier the execution. Normally internal plugins is 100.
      resolve: {
        filters: {
          // Only execute the hook when following conditions satisfied
          sources: ["\\./index.ts"], // a regex array
          importers: ["None"],
        },
        executor: async (param) => {
          // this hook executor
          console.log(param); // resolve params
          // return the resolve result
          return {
            resolvedPath: "virtual:my-module",
            query: {},
            sideEffects: false,
            external: false,
          };
        },
      },
    },
    // load, transform are similar to resolve, refer to their types
  ],
});
```


If you want to pass args to your plugins，you can use a closure.


```ts
// my-resolve-plugin.ts
export function myResolvePlugin(options: Options) {
  const { xx } = options;

  return {
    name: "my-resolve-plugin",
    resolve: {
      // ...
    },
  };
}

// farm.config.ts
import { defineConfig } from "@farmfe/core";
import { myResolvePlugin } from "./myResolvePlugin.ts";

export default defineConfig({
  // ...
  plugins: [myResolvePlugin({ xx: "xx" })],
});
```



> [!NOTE]
> note
> 
> - See [Create Plugin](</docs/1.x/plugins/writing-plugins/js-plugin#create-plugin>) to create a new plugin quickly based on official plugin templates.
> - This document only covers how to create, develop and publish a js plugin, for more detail about the plugin hooks, see [Js Plugin Hooks](</docs/api/js-plugin-api>).



<a id="conventions"></a>
## Conventions


For farm specific js plugins:


- The Farm Js plugin should have a name with a ` farm-plugin- ` prefix and clear semantics.
- Include the ` farm-plugin- ` keyword in package.json.


If your plugin is only applicable to a specific framework, its name should follow the following prefix format:


- ` farm-plugin-vue- `: Prefix as a Vue plugin
- ` farm-plugin-react- `: Prefix as a React plugin
- ` farm-plugin-svelte- `: Prefix as a svelte plugin
- ...


<a id="concepts"></a>
## Concepts


Before you start to write your js plugin, you should know the following concepts:


- **filters**: Cause Js Plugins are much slower than Rust Plugins, your js plugin need to set explicit filters to avoid unnecessary call for js plugins hook. For example, you should set ` transform.filters.moduleTypes = ['js'] ` to make sure that the transform hook of your js plugin only runs for ` .js/mjs/cjs ` files.
- **module\_type**: The type of the module, it can be ` js `, ` ts `, ` css `, ` sass `, ` json `, etc. Farm supports ` js/ts/jsx/tsx `, ` css `, ` html `, ` json `, ` static assets(png, svg, etc) ` natively. ` module_type ` is returned by ` load ` hook or ` transform ` hook.
- **resolved\_path and module\_id**: ` resolved_path ` is the absolute path of the module, and ` module_id ` is the unique id of the module, it's usually ` relative path of the module from the project root ` + ` query `. For example, we import a module as ` import './a?query' `, the resolved\_path is ` /project/src/a.ts ` and the module\_id is ` src/a.ts?query `.
- **context**: All the hooks in the plugin accept a ` context ` argument, it's the compilation context of the farm project, you can use it to get the ModuleGraph, Module, Resources, etc.
- **Resource and Resource Pot**: ` Resource ` is the final output bundle file, and ` Resource Pot ` is the abstract representation of the resource, similar to ` Chunk ` of other bundlers. Inside Farm, first we will generate ` Resource Pots ` from ` ModuleGraph `, render ` Resource Pots ` and finally generate ` Resources ` from ` Resource Pots `.


<a id="filters"></a>
### Filters


Cause ` Js Plugins ` are much slower than ` Rust Plugins `, Farm use ` filters ` to control the execution of js plugin hooks. The plugin hook executes only when given ` filters ` matched to improve performance. ` filters ` is neccessary for some commonly used hooks, such as ` resolve `, ` load `, ` transform `, etc.


For example, if you want to transform css files, you can use ` transform.filters.moduleTypes = ['css'] ` to make sure that the transform hook of your js plugin only runs for ` .css ` files:


```ts
const myCssPlugin = {
  name: "my-css-plugin",
  transform: {
    filters: {
      // Only execute the hook when following conditions satisfied
      // resolvedPaths: ["\\./index.ts"], // a regex array to match the resolvedPaths
      moduleTypes: ["css"],
    },
    executor: async (param) => {
      // transform css
    },
  },
};
```


<a id="module-type"></a>
### Module Type


In Farm, every thing is ` First Class Citizens `, so Farm designs ` module_type ` to identify the type of a module and handle different kinds of ModuleTypes in different plugins.


` module_type ` returned by ` load ` hook, and can be transformed by ` transform ` hook. Farm supports ` js/ts/jsx/tsx `, ` css `, ` html `, ` json `, ` static assets(png, svg, etc) ` natively. For these module types, you can return them directly in ` load ` or ` transform ` hook directly. But if you want to handle custom module types, you may need to implement ohter hooks like ` parse `, ` render_resource_pot_modules `, ` generate resources `, etc to control how to parse, render and generate resources for the custom module types.



> [!NOTE]
> note
> 
> Js Plugins don't support ` parse `, ` render_resource_pot_modules `, ` generate resources ` hooks, you have to use Rust Plugins to handle custom module types.



<a id="create-plugin"></a>
## Create Plugin


Farm provides official templates to help your create your js plugins quickly:


**pnpm**

```javascript
pnpm create farm-plugin
```


**npm**

```javascript
npm create farm-plugin@latest
```


**yarn**

```javascript
yarn create farm-plugin
```



then follow the prompts to create your plugin.


or you can create a plugin derectly by running the following command:


**pnpm**

```javascript
pnpm create farm-plugin my-farm-plugin --type js
```


**npm**

```javascript
npm create my-farm-plugin --type js
```


**yarn**

```javascript
yarn create my-farm-plugin --type js
```



Above command will create new js plugin with name ` my-farm-plugin ` in the current directory. ` --type ` can be ` rust ` or ` js `


<a id="develop-plugin"></a>
## Develop Plugin


After creating the plugin, you can start to develop your plugin. The plugin is a pure JavaScript object that defines a set of property hooks:


```ts
// import { readFileSync } from 'node:fs';
import type { JsPlugin } from '@farmfe/core';

interface Options {
  /* Your options here */
}

export default function farmPlugin(options: Options): JsPlugin {
  return {
    name: '<FARM-JS-PLUGIN-NPM-NAME>',
    /* Your plugin hooks here: */ 

    // transform: {
    //   filters: {
    //     moduleTypes: ['js']
    //   },
    //   async executor(params) {
    //     const { content } = params;
    //     return {
    //       content,
    //       moduleType: 'js'
    //     };
    //   }
    // },
    // finish: {
    //   executor() {}
    // }
  };
}
```



> [!TIP]
> tip
> 
> For more detail about the plugin hooks, see [Js Plugin Hooks](</docs/api/js-plugin-api>).



Run ` npm run dev ` to compile the plugin and watch for changes. Run ` npm run build ` to build the plugin.


<a id="publish-plugin"></a>
## Publish Plugin


A js plugin package is a normal npm package, you can publish it to npm registry by running ` npm publish `.
