From 062a590355762c1771f3aa2ec878cc2d5e996f42 Mon Sep 17 00:00:00 2001 From: Bright <1521488775@qq.com> Date: Thu, 1 Feb 2024 09:29:09 +0800 Subject: [PATCH] chore: add hmr api and js plugin api --- docs/api/hmr-api.md | 64 ++++++++++++ docs/api/js-plugin-api.md | 151 +++++++++++++++++++--------- docs/config/environment-variable.md | 32 ------ docs/features/env.md | 33 +++++- sidebars.js | 3 +- 5 files changed, 199 insertions(+), 84 deletions(-) delete mode 100644 docs/config/environment-variable.md diff --git a/docs/api/hmr-api.md b/docs/api/hmr-api.md index f92888fe3..4fb887c4d 100644 --- a/docs/api/hmr-api.md +++ b/docs/api/hmr-api.md @@ -1 +1,65 @@ # Hmr Api +:::note +The HMR API is compatible with [Vite's HMR API](https://vitejs.dev/guide/api-hmr.html). +::: + +Farm exposes its manual HMR API via the special import.meta.hot object(the same as Vite): +```ts +export interface ViteHotContext { + readonly data: any; + + accept(): void; + accept(cb: (mod: ModuleNamespace | undefined) => void): void; + accept(dep: string, cb: (mod: ModuleNamespace | undefined) => void): void; + accept( + deps: readonly string[], + cb: (mods: Array) => void + ): void; + + // acceptExports is not supported in Farm for now + // acceptExports( + // exportNames: string | readonly string[], + // cb?: (mod: ModuleNamespace | undefined) => void + // ): void; + + dispose(cb: (data: any) => void): void; + prune(cb: (data: any) => void): void; + invalidate(message?: string): void; + + on( + event: T, + cb: (payload: InferCustomEventPayload) => void + ): void; + off( + event: T, + cb: (payload: InferCustomEventPayload) => void + ): void; + send(event: T, data?: InferCustomEventPayload): void; +} +``` + +## Required Conditional Guard + +## IntelliSense for TypeScript + +## hot.accept() + +## hot.accept(cb) + +## hot.accept(deps, cb) + +## hot.dispose(cb) + +## hot.prune(cb) + +## hot.data + +## hot.decline() + +## hot.invalidate(message?: string) + +## hot.on(event, cb) + +## hot.off(event, cb) + +## hot.send(event, data) \ No newline at end of file diff --git a/docs/api/js-plugin-api.md b/docs/api/js-plugin-api.md index 922add4bd..24330ef6a 100644 --- a/docs/api/js-plugin-api.md +++ b/docs/api/js-plugin-api.md @@ -15,80 +15,133 @@ If your plugin is only applicable to a specific framework, its name should follo - `farm-plugin-vue-`: Prefix as a Vue plugin - `farm-plugin-react-`: Prefix as a React plugin - `farm-plugin-svelte-`: Prefix as a svelte plugin +- ... -## Plugins config +## Configuring Js Plugins -```ts -// farm.config.js +Adding JS plugins by `plugins` option: + +```ts title="farm.config.ts" {3,7} import { defineConfig } from "@farmfe/core"; -import farmPlugin from "farm-plugin"; -import vitePlugin from "vite-plugin"; -import rollupPlugin from "roll-plugin"; +// import a js plugin +import farmPluginFoo from "farm-plugin-foo"; export default defineConfig({ - plugins: [farmPlugin(), vitePlugin(), rollupPlugin()], + // configuring it in plugins + plugins: [farmPluginFoo()], }); ``` -Plugins can also accept `multiple plugins` as presets for a single element. +## Writing Js Plugins +A Farm Js Plugin is a plain javascript object which exposes a set of `hook`s. for example: -```ts -import framework1 from "farm-plugin-framework1"; -import framework2 from "farm-plugin-framework2"; +```ts title="my-farm-plugin.ts" +// Create a plugin file that exports a plugin function which returns a `JsPlugin` Object: + +import type { JsPlugin } from '@farmfe/core'; -export default function framework(config) { - return [framework1(config), framework2(config)]; +// Plugin Options +export interface PluginOptions { + test: boolean; } -``` +// export a Plugin Function +export default function MyPlugin(options: PluginOptions): JsPlugin { + // reading options + const { test } = options; -```ts + // return a object that exposes hook + return { + name: 'my-farm-plugin', + // using load hook to load custom modules + load: { + filters: { + resolvedPaths: ['\\.test$'] // filter files to improve performance + }, + executor({ resolvedPath }) { + if (test && resolvedPath.endsWith('.test')) { + return { + content: 'test file', + sourceMap: null + } + } + } + } + } +} +``` +then using the plugin in `farm.config.ts`: +```ts title="farm.config.ts" {3,7} import { defineConfig } from "@farmfe/core"; -import framework from "farm-plugin-framework"; +// import a js plugin +import myFarmPlugin from "./my-farm-plugin"; export default defineConfig({ - plugins: [framework()], + // configuring it in plugins + plugins: [myFarmPlugin({ + test: true + })], }); ``` -## Example +:::note +For more details of writing JS plugins, refer to [Writing JS Plugins](/docs/plugins/writing-plugins/js-plugin) +::: -### transform vue suffix file +## hooks +### name +- **type: `string`** +- **required: `true`** +The name of this plugins, MUST not be empty. ```ts -export default function plugin() { +export default function MyPlugin() { return { - name: "transform--vue-file", - load: { - filters: { - resolvedPaths: [".vue$"], - }, - async executor(params) { - const { resolvedPath } = params; - const content = await tryToReadFileSync(resolvedPath); - return { - content, - moduleType: "vue", - }; - }, - }, - transform: { - filter: { - moduleTypes: ["vue"], - }, - async executor(params) { - const { resolvedPath, content } = params; - ctx.handleTransform(resolvedPath); - return { - content, - moduleType: "js", - }; - }, - }, - }; + name: 'my-plugin', + // ... + } } ``` -## hook +### priority +### name +- **type: `number`** +- **required: `false`** +- **default: `100`** + +The priority of this plugins, default to `100`. `priority` controls the execution order of plugins, the larger the value, the earlier the plugin is executed. + +```ts +export default function MyPlugin() { + return { + name: 'my-plugin', + priority: 1000, // make this plugins execute bebore all other plugins + // ... + } +} +``` +:::note +Note that the priority of most farm internal plugins like `plugin-script`, `plugin-resolve` is `99`, which means your plugins is always executed before the internal plugins. If your want to make your plugin executed after farm internal plugins, set `priority` to a value that smaller than `99`, for example: `98`. Also the priority value can be negative, you can set it to `-9999` to make sure it is always executed at last. +::: + +### config +### configResolved +### configureDevServer +### configureCompiler +### buildStart +### resolve +### load +### transform +### buildEnd +### renderStart +### renderResourcePot +### argumentResourceHash +### finalizeResources +### transformHtml +### writeResources +### pluginCacheLoaded +### writePluginCache +### finish +### updateModules ```ts export interface JsPlugin { diff --git a/docs/config/environment-variable.md b/docs/config/environment-variable.md deleted file mode 100644 index 829ea5785..000000000 --- a/docs/config/environment-variable.md +++ /dev/null @@ -1,32 +0,0 @@ -# Environment variable - -`Farm` distinguishes between development and production environments through `Farm` process.env.NODE\_ ENV`. - -In different environments, environment variables are replaced statically, so use static constants to represent environment variables instead of dynamic expressions. - -### `.env` file - -`Farm` uses `dotenv` to load your additional environment variables, such as `.env` files. - -```js -// .env -FARM_APP_SECRET=secret -Farm_APP_PASSWORD=password -APP_VERSION=1.0.0 -``` - -`Farm` loads the file `.env` via dotenv, and loads it into `process.env` and finally injects it into define. - -:::warning -In order to ensure the security of the client, preventing the environment variables in the current system from being exposed to the client `Farm` will only identify some important environment variables that start with `Farm`. -::: - -`Farm` expands environment variables through dotenv-expand - -If you want to customize the prefix of env variables, you can configure `envPrefix`. - -### envPrefix - -- **default value**: `FARM_` - -Customize the prefix of the `env` variable by configuring `envPrefix`. diff --git a/docs/features/env.md b/docs/features/env.md index 4103bae99..b47c8452c 100644 --- a/docs/features/env.md +++ b/docs/features/env.md @@ -1 +1,32 @@ -# Enviroment Variables and Modes \ No newline at end of file +# Enviroment Variables and Modes + +`Farm` distinguishes between development and production environments through `Farm` process.env.NODE\_ ENV`. + +In different environments, environment variables are replaced statically, so use static constants to represent environment variables instead of dynamic expressions. + +## `.env` file + +`Farm` uses `dotenv` to load your additional environment variables, such as `.env` files. + +```js +// .env +FARM_APP_SECRET=secret +Farm_APP_PASSWORD=password +APP_VERSION=1.0.0 +``` + +`Farm` loads the file `.env` via dotenv, and loads it into `process.env` and finally injects it into define. + +:::warning +In order to ensure the security of the client, preventing the environment variables in the current system from being exposed to the client `Farm` will only identify some important environment variables that start with `Farm`. +::: + +`Farm` expands environment variables through dotenv-expand + +If you want to customize the prefix of env variables, you can configure `envPrefix`. + +## envPrefix + +- **default value**: `FARM_` + +Customize the prefix of the `env` variable by configuring `envPrefix`. diff --git a/sidebars.js b/sidebars.js index 890241087..161b0f851 100644 --- a/sidebars.js +++ b/sidebars.js @@ -38,7 +38,7 @@ const sidebars = { { type: "category", label: "Features", - collapsed: true, + collapsed: false, items: [ "features/dev-server", "features/html", @@ -82,7 +82,6 @@ const sidebars = { "config/compilation-options", "config/dev-server", "config/shared", - "config/environment-variable", "config/plugins-options", ], },