"use strict";(self.webpackChunkfes_js=self.webpackChunkfes_js||[]).push([[287],{4020:(n,s,a)=>{a.r(s),a.d(s,{data:()=>p});const p={key:"v-c5618810",path:"/reference/plugin/dev/api.html",title:"插件 API",lang:"zh-CN",frontmatter:{},excerpt:"",headers:[{level:2,title:"属性",slug:"属性",children:[{level:3,title:"api.paths",slug:"api-paths",children:[]},{level:3,title:"api.cwd",slug:"api-cwd",children:[]},{level:3,title:"api.pkg",slug:"api-pkg",children:[]},{level:3,title:"api.configInstance",slug:"api-configinstance",children:[]},{level:3,title:"userConfig",slug:"userconfig",children:[]},{level:3,title:"config",slug:"config",children:[]},{level:3,title:"env",slug:"env",children:[]},{level:3,title:"args",slug:"args",children:[]}]},{level:2,title:"核心方法",slug:"核心方法",children:[{level:3,title:"describe",slug:"describe",children:[]},{level:3,title:"register",slug:"register",children:[]},{level:3,title:"applyPlugins",slug:"applyplugins",children:[]},{level:3,title:"registerMethod",slug:"registermethod",children:[]},{level:3,title:"registerCommand",slug:"registercommand",children:[]},{level:3,title:"registerPresets",slug:"registerpresets",children:[]},{level:3,title:"registerPlugins",slug:"registerplugins",children:[]},{level:3,title:"hasPlugins",slug:"hasplugins",children:[]},{level:3,title:"hasPresets",slug:"haspresets",children:[]},{level:3,title:"skipPlugins",slug:"skipplugins",children:[]}]},{level:2,title:"扩展方法",slug:"扩展方法",children:[{level:3,title:"addPluginExports",slug:"addpluginexports",children:[]},{level:3,title:"addCoreExports",slug:"addcoreexports",children:[]},{level:3,title:"addRuntimePlugin",slug:"addruntimeplugin",children:[]},{level:3,title:"addRuntimePluginKey",slug:"addruntimepluginkey",children:[]},{level:3,title:"addEntryImportsAhead",slug:"addentryimportsahead",children:[]},{level:3,title:"addEntryImports",slug:"addentryimports",children:[]},{level:3,title:"addEntryCodeAhead",slug:"addentrycodeahead",children:[]},{level:3,title:"addEntryCode",slug:"addentrycode",children:[]},{level:3,title:"addHTMLHeadScripts",slug:"addhtmlheadscripts",children:[]},{level:3,title:"addBeforeMiddlewares",slug:"addbeforemiddlewares",children:[]},{level:3,title:"addMiddlewares",slug:"addmiddlewares",children:[]},{level:3,title:"addTmpGenerateWatcherPaths",slug:"addtmpgeneratewatcherpaths",children:[]},{level:3,title:"chainWebpack",slug:"chainwebpack",children:[]},{level:3,title:"copyTmpFiles",slug:"copytmpfiles",children:[]},{level:3,title:"getPort",slug:"getport",children:[]},{level:3,title:"getHostname",slug:"gethostname",children:[]},{level:3,title:"getServer",slug:"getserver",children:[]},{level:3,title:"getRoutes",slug:"getroutes",children:[]},{level:3,title:"getRoutesJSON",slug:"getroutesjson",children:[]},{level:3,title:"modifyRoutes",slug:"modifyroutes",children:[]},{level:3,title:"modifyBundleConfigOpts",slug:"modifybundleconfigopts",children:[]},{level:3,title:"modifyBundleConfig",slug:"modifybundleconfig",children:[]},{level:3,title:"modifyBabelOpts",slug:"modifybabelopts",children:[]},{level:3,title:"modifyBabelPresetOpts",slug:"modifybabelpresetopts",children:[]},{level:3,title:"modifyPaths",slug:"modifypaths",children:[]},{level:3,title:"modifyDefaultConfig",slug:"modifydefaultconfig",children:[]},{level:3,title:"modifyConfig",slug:"modifyconfig",children:[]},{level:3,title:"modifyPublicPathStr",slug:"modifypublicpathstr",children:[]},{level:3,title:"onPluginReady",slug:"onpluginready",children:[]},{level:3,title:"onStart",slug:"onstart",children:[]},{level:3,title:"onExit",slug:"onexit",children:[]},{level:3,title:"onGenerateFiles",slug:"ongeneratefiles",children:[]},{level:3,title:"restartServer",slug:"restartserver",children:[]},{level:3,title:"writeTmpFile",slug:"writetmpfile",children:[]}]}],filePathRelative:"reference/plugin/dev/api.md",git:{updatedTime:165345025e4,contributors:[{name:"wanchun",email:"445436867@qq.com",commits:1}]}}},7965:(n,s,a)=>{a.r(s),a.d(s,{default:()=>T});var p=a(6252);const e=(0,p.uE)('

插件 API

属性

api.paths

一些关键的路径:

api.cwd

执行命令的绝对路径

api.pkg

package.json的内容

api.configInstance

config实例

userConfig

用户配置

config

插件配置可被修改,此为最终的配置

env

process.env

args

环境变量

核心方法

describe

注册阶段执行,用于描述插件或插件集的 id、key、配置信息、启用方式等。

用法:describe({ id?: string, key?: string, config?: { default, schema, onChange } }, enableBy?)

例如:

 api.describe({\n    key: 'esbuild',\n    config: {\n        schema(joi) {\n            return joi.object();\n        },\n        default: {}\n    },\n    enableBy: api.EnableBy.config,\n});\n
1
2
3
4
5
6
7
8
9
10

注:

',26),t=(0,p._)("li",null,[(0,p._)("code",null,"config.default"),(0,p.Uk)(" 为配置的默认值,用户没有配置时取这个")],-1),o=(0,p._)("code",null,"config.schema",-1),c=(0,p.Uk)(" 用于声明配置的类型,基于 "),l={href:"https://hapi.dev/module/joi",target:"_blank",rel:"noopener noreferrer"},i=(0,p.Uk)("joi"),r=(0,p.Uk)(",如果你希望用户进行配置,这个是必须的,否则用户的配置无效"),u=(0,p._)("li",null,[(0,p._)("code",null,"config.onChange"),(0,p.Uk)(" 是 "),(0,p._)("code",null,"dev"),(0,p.Uk)(" 阶段配置被修改后的处理机制,默认会重启 dev 进程,也可以修改为 api.ConfigChangeType.regenerateTmpFiles 只重新生成临时文件,还可以通过函数的格式自定义")],-1),d=(0,p._)("li",null,[(0,p._)("code",null,"enableBy"),(0,p.Uk)(" 为启用方式,默认是注册启用,可更改为 "),(0,p._)("code",null,"api.EnableBy.config"),(0,p.Uk)(",还可以用自定义函数的方式决定其启用时机(动态生效)")],-1),k=(0,p.uE)('

register

为 api.applyPlugins 注册可供其使用的 hook。

用法:register({ key: string, fn: Function, pluginId?: string, before?: string, stage?: number })

参数:

// 可同步\napi.register({\n  key: 'foo',\n  fn() {\n    return 'a';\n  },\n});\n\n// 可异步\napi.register({\n  key: 'foo',\n  async fn() {\n    await delay(100);\n    return 'b';\n  },\n});\n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

注意:

applyPlugins

取得 register 注册的 hooks 执行后的数据。

用法:applyPlugins({ key: string, type: api.ApplyPluginsType, initialValue?: any, args?: any })

参数:

例如:

const foo = await api.applyPlugins({\n  key: 'foo',\n  type: api.ApplyPluginsType.add,\n  initialValue: [],\n});\nconsole.log(foo); // ['a', 'b']\n
1
2
3
4
5
6

api.ApplyPluginsType

编译时插件hook执行类型,enum 类型,包含三个属性:

registerMethod

api 上注册方法。如果有提供 fn,则执行 fn 定义的函数。

用法:registerMethod({ name: string, fn?: Function, exitsError?: boolean })

例如:

 api.registerMethod({\n    name: 'writeTmpFile',\n    fn({\n        path,\n        content\n    }) {\n        assert(\n            api.stage >= api.ServiceStage.pluginReady,\n            'api.writeTmpFile() should not execute in register stage.'\n        );\n        const absPath = join(api.paths.absTmpPath, path);\n        api.utils.mkdirp.sync(dirname(absPath));\n        if (!existsSync(absPath) || readFileSync(absPath, 'utf-8') !== content) {\n            writeFileSync(absPath, content, 'utf-8');\n        }\n    }\n});\n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

然后在插件中可以使用:

api.writeTmpFile()\n
1

registerCommand

',26),b=(0,p.Uk)("注册命令,基于 "),m={href:"https://github.com/tj/commander.js/",target:"_blank",rel:"noopener noreferrer"},g=(0,p.Uk)("commander"),h=(0,p.Uk)(" 实现的机制。"),f=(0,p._)("p",null,[(0,p.Uk)("用法:"),(0,p._)("strong",null,"registerCommand({ command: string, description: string, fn: Function, options?: Object })")],-1),v=(0,p._)("p",null,"参数:",-1),y=(0,p._)("li",null,"command",-1),j=(0,p._)("li",null,[(0,p.Uk)("description,描述文字,输入 "),(0,p._)("code",null,"--help"),(0,p.Uk)(" 会打印")],-1),x=(0,p._)("li",null,[(0,p.Uk)("fn,命令执行的函数,参数有: "),(0,p._)("ul",null,[(0,p._)("li",null,"rawArgv,原始参数"),(0,p._)("li",null,"args,参数"),(0,p._)("li",null,"options,执行命令时附带的的参数配置"),(0,p._)("li",null,"program,commander对象")])],-1),P=(0,p.Uk)("options,参数配置,基于 "),w={href:"https://github.com/tj/commander.js/",target:"_blank",rel:"noopener noreferrer"},_=(0,p.Uk)("commander"),C=(0,p.Uk)(" 。"),E=(0,p.uE)('

例如:

api.registerCommand({\n    command: 'webpack',\n    description: 'inspect webpack configurations',\n    options: [{\n        name: '--rule <ruleName>',\n        description: 'inspect a specific module rule'\n    }, {\n        name: '--plugin <pluginName>',\n        description: 'inspect a specific plugin'\n    }, {\n        name: '--rules',\n        description: 'list all module rule names'\n    }, {\n        name: '--plugins',\n        description: 'list all plugin names'\n    }, {\n        name: '--verbose',\n        description: 'show full function definitions in output'\n    }],\n    async fn({ rawArgv, args, options, program}) {\n    }\n})\n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

当项目引入此插件后,使用:

fes webpack\n
1

registerPresets

注册插件集,参数为路径数组。

用法:registerPresets(presets: string[])

例如:

api.registerPresets([\n    { id: 'preset_2', key: 'preset2', apply: () => () => {} },\n    require.resolve('./preset_3'),\n]);\n
1
2
3
4

registerPlugins

注册插件,参数为路径数组。

用法:registerPlugins(plugins: string[])

例如:

api.registerPlugins([\n    { id: 'preset_2', key: 'preset2', apply: () => () => {} },\n    require.resolve('./preset_3'),\n]);\n
1
2
3
4

hasPlugins

判断是否有注册某个插件,插件的 id 规则:

用法:hasPlugins(pluginIds: string[])

例如

// 判断是否有注册 @fesjs/plugin-locale\napi.hasPlugins(['@fesjs/plugin-locale']);\n
1
2

提示

如果在注册阶段使用,只能判断在他之前是否有注册某个插件。

hasPresets

判断是否有注册某个插件集。

用法:hasPresets(presetIds: string[])

例如

// 判断是否有注册\napi.hasPlugins(['@fesjs/preset-xxx']);\n
1
2

提示

如果在注册阶段使用,只能判断在他之前是否有注册某个插件集。

skipPlugins

声明哪些插件需要被禁用,参数为插件 id 的数组。

用法:hasPresets(presetIds: string[])

例如:

// 禁用 plugin-model 插件\napi.skipPlugins(['@fesjs/plugin-model']);\n
1
2

扩展方法

通过 api.registerMethod() 扩展的方法。

addPluginExports

把插件需要导出的运行时 API 写入@fesjs/fes

api.addPluginExports(() => [\n    {\n        specifiers: ['access', 'useAccess'],\n        source: absoluteFilePath\n    }\n]);\n
1
2
3
4
5
6

这样用户使用时:

import { access, useAccess } from '@fesjs/fes';\n
1

addCoreExports

提供给其他插件运行时需要的 API。

api.addCoreExports(() => [\n    {\n        specifiers: ['getRoutes', 'getRouter', 'getHistory', 'destroyRouter'],\n        source: absCoreFilePath\n    }\n]);\n
1
2
3
4
5
6

使用:

import { getHistory, destroyRouter } from '@@/core/coreExports';\n
1

addRuntimePlugin

添加运行时插件,返回值格式为表示文件路径的字符串。

例如:

api.addRuntimePlugin(() => join(__dirname, './runtime'));\n
1

addRuntimePluginKey

添加插件提供的运行时配置的 key,返回值格式为字符串。

例如:

api.addRuntimePluginKey(() => 'some');\n
1

则用户可以:

// app.js\nconst some = function(){\n    return {\n\n    }\n}\n\n
1
2
3
4
5
6
7

addEntryImportsAhead

在入口文件现有 import 的前面添加 import。

例如:

api.addEntryImportsAhead(() => [{ source: 'anypackage' }]);\n
1

addEntryImports

在入口文件现有 import 的后面添加 import。

例如:

api.addEntryImport(() => {\n  return [\n    {\n      source: '/modulePath/xxx.js',\n      specifier: 'moduleName',\n    }\n  ]\n});\n
1
2
3
4
5
6
7
8

addEntryCodeAhead

在入口文件最前面(import 之后)添加代码。

例如:

api.addEntryCodeAhead(\n    () => `${globalCSSFile\n        .map(file => `require('${winPath(relative(absTmpPath, file))}');`)\n        .join('')}`\n\n
1
2
3
4
5

addEntryCode

在入口文件最后添加代码。

例如:

api.addEntryCode(() => {\n  return `console.log('works!')`\n})\n
1
2
3

addHTMLHeadScripts

在 HTML 头部添加脚本。

例如:

api.addHTMLHeadScripts(() => {\n  return [\n    {\n      content: '',\n      src: '',\n      // ...attrs\n    },\n  ];\n});\n
1
2
3
4
5
6
7
8
9

addBeforeMiddlewares

添加在 webpack compiler 中间件之前的中间件,返回值格式为 express 中间件。

例如:

api.addBeforeMiddlewares(() => {\n  return (req, res, next) => {\n    if (false) {\n      res.end('end');\n    } else {\n      next();\n    }\n  };\n});\n
1
2
3
4
5
6
7
8
9

addMiddlewares

添加在 webpack compiler 中间件之后的中间件,返回值格式为 express 中间件。

addTmpGenerateWatcherPaths

添加重新生成临时文件的监听路径。

例如:

api.addTmpGenerateWatcherPaths(() => [\n    './app.js',\n]);\n
1
2
3

chainWebpack

通过 [webpack-chain] 的方式修改 webpack 配置。

例如:

api.chainWebpack((memo) => {\n    memo.resolve.alias.set('vue-i18n', 'vue-i18n/dist/vue-i18n.esm-bundler.js');\n});\n
1
2
3

copyTmpFiles

批量写临时文件。

例如:

 api.copyTmpFiles({\n    namespace,\n    path: join(__dirname, 'runtime'),\n    ignore: ['.tpl']\n});\n
1
2
3
4
5

参数:

提示

不能在注册阶段使用,通常放在 api.onGenerateFiles() 里,这样能在需要时重新生成临时文件 临时文件的写入做了缓存处理,如果内容一致,不会做写的操作,以减少触发 webpack 的重新编译

getPort

获取端口号,dev 时有效。

getHostname

获取 hostname,dev 时有效。

getServer

获取 devServer,dev 时有效。

getRoutes

获取 api.modifyRoutes 修改过后的路由信息。

getRoutesJSON

获取格式化后的路由信息

modifyRoutes

修改路由。

例如:

// 把BaseLayout插入到路由配置中,作为根路由\napi.modifyRoutes(routes => [\n    {\n        path: '/',\n        component: winPath(\n            join(api.paths.absTmpPath || '', absFilePath)\n        ),\n        children: routes\n    }\n]);\n
1
2
3
4
5
6
7
8
9
10

modifyBundleConfigOpts

修改获取 bundleConfig 的函数参数。

例如:

api.modifyBundleConfigOpts(memo => {\n    memo.miniCSSExtractPluginPath = require.resolve('mini-css-extract-plugin');\n    memo.miniCSSExtractPluginLoaderPath = require.resolve(\n    'mini-css-extract-plugin/dist/loader',\n    );\n    return memo;\n});\n\n
1
2
3
4
5
6
7
8

modifyBundleConfig

修改 bundle 配置。

api.modifyBundleConfig((bundleConfig) => {\n    // do something\n    return bundleConfig;\n});\n
1
2
3
4

modifyBabelOpts

修改 babel 配置项。

例如:

api.modifyBabelOpts((babelOpts) => {\n    if (api.config.babelPluginImport) {\n        api.config.babelPluginImport.forEach((config) => {\n            babelOpts.plugins.push(['import', config]);\n        });\n    }\n    return babelOpts;\n});\n
1
2
3
4
5
6
7
8

modifyBabelPresetOpts

修改 babel 插件的配置。

例如:

api.modifyBabelPresetOpts(opts => {\n    return {\n      ...opts,\n      import: (opts.import || []).concat([\n        { libraryName: 'ant-design-vue', libraryDirectory: 'es', style: true },\n      ]),\n    };\n});\n
1
2
3
4
5
6
7
8

modifyPaths

修改 paths 对象。

modifyDefaultConfig

修改默认配置。 例如:

api.modifyDefaultConfig((memo) => {\n  return {\n    ...memo,\n    ...defaultOptions,\n  };\n});\n
1
2
3
4
5
6

modifyConfig

修改最终配置。

例如:

api.modifyConfig((memo) => {\n  return {\n    ...memo,\n    ...defaultOptions,\n  };\n});\n\n
1
2
3
4
5
6
7

modifyPublicPathStr

修改 publicPath 字符串。

例如:

api.modifyPublicPathStr(() => {\n  return api.config.publicPath || '/';\n});\n
1
2
3

onPluginReady

在插件初始化完成触发。在 onStart 之前,此时还没有 config 和 paths,他们尚未解析好。

onStart

在命令注册函数执行前触发。可以使用 config 和 paths。

onExit

dev 退出时触发。

onGenerateFiles

生成临时文件,触发时机在 webpack 编译之前。

restartServer

重启 devServer,dev 时有效。

writeTmpFile

写临时文件。

例如:

api.writeTmpFile({\n    path: absoluteFilePath,\n    content: Mustache.render(\n        readFileSync(join(__dirname, 'runtime/core.tpl'), 'utf-8'),\n        {\n            REPLACE_ROLES: JSON.stringify(roles)\n        }\n    )\n});\n
1
2
3
4
5
6
7
8
9

参数:

提示

不能在注册阶段使用,通常放在 api.onGenerateFiles() 里,这样能在需要时重新生成临时文件 临时文件的写入做了缓存处理,如果内容一致,不会做写的操作,以减少触发 webpack 的重新编译

',154),S={},T=(0,a(3744).Z)(S,[["render",function(n,s){const a=(0,p.up)("OutboundLink");return(0,p.wg)(),(0,p.iD)(p.HY,null,[e,(0,p._)("ul",null,[t,(0,p._)("li",null,[o,c,(0,p._)("a",l,[i,(0,p.Wm)(a)]),r]),u,d]),k,(0,p._)("p",null,[b,(0,p._)("a",m,[g,(0,p.Wm)(a)]),h]),f,v,(0,p._)("ul",null,[y,j,x,(0,p._)("li",null,[P,(0,p._)("a",w,[_,(0,p.Wm)(a)]),C])]),E],64)}]])},3744:(n,s)=>{s.Z=(n,s)=>{const a=n.__vccOpts||n;for(const[n,p]of s)a[n]=p;return a}}}]);