Plugin API
WinJS's core lies in its plugin mechanism. Based on WinJS's plugin mechanism, you can gain the ability to extend your project's compile-time and runtime capabilities. The following lists all the plugin APIs we provide for you to help you write plugins freely.
Before using the WinJS plugin API, we recommend you first read the Plugins section to understand the mechanisms and principles of WinJS plugins, which will help you better use the plugin APIs.
For easy reference, the following content is sorted alphabetically.
Core APIs
Methods defined in service and PluginAPI.
applyPlugins
api.applyPlugins({ key: string, type? : api.ApplyPluginsType, initialValue? : any, args? : any })
Gets the data from the execution of hooks registered by register()
. This is an asynchronous function, so it returns a Promise. For examples and detailed explanations of this method, see the register API.
describe
api.describe({ key? : string, config? : { default, schema, onChange }, enableBy? })
Executed during the plugin registration stage (initPresets or initPlugins stage), used to describe the plugin or plugin set's key, configuration information, and enablement method.
key
is the key name for this plugin's configuration in the configconfig.default
is the default value of the plugin configuration. When the user hasn't configured the key in the configuration, the default configuration will take effect.config.schema
is used to declare the configuration type, based on joi. This is required if you want users to configure it, otherwise user configuration will be invalidconfig.onChange
is the handling mechanism when configuration is modified in dev mode. The default value isapi.ConfigChangeType.reload
, which means the dev process will restart when the configuration item is modified in dev mode. You can also change it toapi.ConfigChangeType.regenerateTmpFiles
, which means only temporary files will be regenerated. You can also pass in a method to customize the handling mechanism.enableBy
is the plugin enablement method. The default isapi.EnableBy.register
, which means registration enablement, i.e., the plugin will be enabled as long as it's registered. Can be changed toapi.EnableBy.config
, which means configuration enablement, the plugin is only enabled when the plugin's configuration item is configured. You can also customize a method that returns a boolean value (true for enabled) to determine its enablement timing, which is usually used to implement dynamic enabling.
e.g.
api.describe({
key: 'foo',
config: {
schema(joi) {
return joi.string();
},
onChange: api.ConfigChangeType.regenerateTmpFiles,
},
enableBy: api.EnableBy.config,
})
In this example, the plugin's key
is foo
, so the key name in the configuration is foo
, the configuration type is string, when the foo
configuration changes, dev will only regenerate temporary files. This plugin will only be enabled after the user configures foo
.
isPluginEnable
api.isPluginEnable(key:string)
Determines whether a plugin is enabled. The parameter passed in is the plugin's key.
register
api.register({ key: string, fn, before? : string, stage? : number })
Registers hooks for use by api.applyPlugins
.
key
is the category name of the registered hook. You can useregister
multiple times to register hooks to the samekey
, and they will be executed in sequence. Thiskey
is also the samekey
used when usingapplyPlugins
to collect hooks data. Note: this key has no relationship with the plugin's key.fn
is the hook definition, which can be synchronous or asynchronous (just return a Promise)stage
is used to adjust execution order, default is 0. Set to -1 or less will execute earlier, set to 1 or more will execute later.before
is also used to adjust execution order, the value passed in is the name of the registered hook. Note: the name of the hook registered byregister
is the id of the WinJS plugin it belongs to. For more usage of stage and before, refer to tapable
The writing of fn needs to be determined in combination with the type parameter of the applyPlugins that will be used:
api.ApplyPluginsType.add
applyPlugins
will concatenate their return values into an array according to hook order. At this time,fn
needs to have a return value, andfn
will receive theargs
parameter ofapplyPlugins
as its own parameter. TheinitialValue
ofapplyPlugins
must be an array, with a default value of empty array. Whenkey
starts with'add'
and notype
is explicitly declared,applyPlugins
will execute according to this type by default.api.ApplyPluginsType.modify
applyPlugins
will sequentially modify theinitialValue
received byapplyPlugins
according to hook order, soinitialValue
is required at this time. At this time,fn
needs to receive amemo
as its first parameter, and will take theargs
parameter ofapplyPlugins
as its second parameter.memo
is the result of the previous series of hooks modifyinginitialValue
, andfn
needs to return the modifiedmemo
. Whenkey
starts with'modify'
and notype
is explicitly declared,applyPlugins
will execute according to this type by default.api.ApplyPluginsType.event
applyPlugins
will execute sequentially according to hook order. At this time, there's no need to pass ininitialValue
.fn
doesn't need to have a return value, and will take theargs
parameter ofapplyPlugins
as its own parameter. Whenkey
starts with'on'
and notype
is explicitly declared,applyPlugins
will execute according to this type by default.
e.g.1 add type
api.register({
key: 'addFoo',
// synchronous
fn: (args) => args
});
api.register({
key: 'addFoo',
// asynchronous
fn: async (args) => args * 2
})
api.applyPlugins({
key: 'addFoo',
// key is add type, no need to explicitly declare as api.ApplyPluginsType.add
args: 1
}).then((data) => {
console.log(data); // [1,2]
})
e.g.2 modify type
api.register({
key: 'foo',
fn: (memo, args) => ({ ...memo, a: args })
})
api.register({
key: 'foo',
fn: (memo) => ({ ...memo, b: 2 })
})
api.applyPlugins({
key: 'foo',
type: api.ApplyPluginsType.modify,
// initialValue is required
initialValue: {
a: 0,
b: 0
},
args: 1
}).then((data) => {
console.log(data); // { a: 1, b: 2 }
});
registerCommand
api.registerCommand({
name: string,
description? : string,
options? : string,
details? : string,
fn,
alias? : string | string[]
resolveConfigMode? : 'strict' | 'loose'
})
Registers a command.
alias
is an alias, such as the aliasg
for generate- The parameter of
fn
is{ args }
, args format is the same as yargs parsing result. Note that the command itself in_
has been removed, for example, when executingwin generate page foo
,args._
is['page','foo']
- The
resolveConfigMode
parameter controls the configuration parsing method when executing commands. Instrict
mode, it strictly validates the WinJS project's configuration file content, and interrupts command execution if there's illegal content; inloose
mode, it doesn't perform configuration file validation checks.
registerMethod
api.registerMethod({ name: string, fn? })
往 api 上注册一个名为 'name'
的方法。
- 当传入了 fn 时,执行 fn
- 当没有传入 fn 时,
registerMethod
会将name
作为api.register
的key
并且将其柯里化后作为fn
。这种情况下相当于注册了一个register
的快捷调用方式,便于注册 hook。
注意:
- 通常不建议注册额外的方法,因为它们不会有 ts 提示,直接使用
api.register()
是一个更安全的做法。
e.g.1
api.registerMethod({
name: foo,
// 有 fn
fn: (args) => {
console.log(args);
}
})
api.foo('hello, win!'); // hello, win!
该例子中,我们往api上注册了一个 foo 方法,该方法会把参数 console 到控制台。
e.g.2
import api from './api';
api.registerMethod({
name: 'addFoo'
// 没有 fn
})
api.addFoo(args => args);
api.addFoo(args => args * 2);
api.applyPlugins({
key: 'addFoo',
args: 1
}).then((data) => {
console.log(data); // [ 1, 2 ]
});
该例子中,我们没有向 api.registerMethod
中传入 fn。此时,我们相当于往 api 上注册了一个"注册器":addFoo
。每次调用该方法都相当于调用了 register({ key: 'addFoo', fn })
。因此当我们使用 api.applyPlugins
的时候(由于我们的方法是 add 型的,可以不用显式声明其 type )就可以获取刚刚注册的 hook 的值。
registerPresets
api.registerPresets(presets
:
string[]
)
注册插件集,参数为路径数组。该 api 必须在 initPresets stage 执行,即只可以在 preset 中注册其他 presets
e.g.
api.registerPresets([
'./preset',
require.resolve('./preset_foo')
])
registerPlugins
api.registerPlugins(plugins
:
string[]
)
注册插件,参数为路径数组。该 api 必须在 initPresets 和 initPlugins stage 执行。
e.g.
api.registerPlugins([
'./plugin',
require.resolve('./plugin_foo')
])
注意:只允许传入插件的路径。
registerGenerator
注册微生成器用来快捷生成模板代码。
示例:
import { GeneratorType } from '@winner-fed/core';
import { logger } from '@winner-fed/utils';
import { join } from 'path';
import { writeFileSync } from 'fs';
api.registerGenerator({
key: 'editorconfig',
name: 'Create .editorconfig',
description: 'Setup editorconfig config',
type: GeneratorType.generate,
fn: () => {
const configFilePath = join(api.cwd, '.editorconfig')
if (existsSync(configFilePath)) {
logger.info(`The .editorconfig file already exists.`)
return
}
writeFileSync(
configFilePath,
`
# 🎨 http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
`.trimStart(),
'utf-8'
)
logger.info(`Generate .editorconfig file successful.`)
}
})
skipPlugins
api.skipPlugins(keys
:
string[]
)
声明哪些插件需要被禁用,参数为插件 key 的数组
扩展方法
通过api.registerMethod()
扩展的方法,它们的作用都是注册一些 hook 以供使用,因此都需要接收一个 fn。这些方法中的大部分都按照 add-
modify-
on-
的方式命名,它们分别对应了 api.ApplyPluginsType
的三种方式,不同方式接收的 fn 不太相同,详见 register 一节。
注意: 下文提到的所有 fn 都可以是同步的或者异步的(返回一个 Promise 即可)。fn 都可以被
{
fn,
name ? : string,
before ? : string | string[],
stage
:
number,
}
代替。其中各个参数的作用详见 tapable
addBeforeBabelPlugins
增加额外的 Babel 插件。传入的 fn 不需要参数,且需要返回一个 Babel 插件或插件数组。
api.addBeforeBabelPlugins(() => {
// 返回一个 Babel 插件(来源于 Babel 官网的例子)
return () => {
visitor: {
Identifier(path)
{
const name = path.node.name;
path.node.name = name.split("").reverse().join("");
}
}
}
})
addBeforeBabelPresets
增加额外的 Babel 插件集。传入的 fn 不需要参数,且需要返回一个 Babel 插件集( presets )或插件集数组。
api.addBeforeBabelPresets(() => {
// 返回一个 Babel 插件集
return () => {
return {
plugins: ["Babel_Plugin_A", "Babel_Plugin_B"]
}
}
})
addBeforeMiddlewares
在 webpack-dev-middleware 之前添加中间件。传入的 fn 不需要参数,且需要返回一个 express 中间件或其数组。
api.addBeforeMiddlewares(() => {
return (req, res, next) => {
if (false) {
res.end('end');
}
next();
}
})
addEntryCode
在入口文件的最后面添加代码(render 后)。传入的 fn 不需要参数,且需要返回一个 string 或者 string 数组。
api.addEntryCode(() => `console.log('I am after render!')`);
addEntryCodeAhead
在入口文件的最前面添加代码(render 前,import 后)。传入的 fn 不需要参数,且需要返回一个 string 或者 string 数组。
api.addEntryCodeAhead(() => `console.log('I am before render!')`)
addEntryImports
在入口文件中添加 import 语句 (import 最后面)。传入的 fn 不需要参数,其需要返回一个 {source: string, specifier?: string}
或其数组。
api.addEntryImports(() => ({
source: '/modulePath/xxx.js',
specifier: 'moduleName'
}))
addEntryImportsAhead
在入口文件中添加 import 语句 (import 最前面)。传入的 fn 不需要参数,其需要返回一个 {source: string, specifier?: string}
或其数组。
api.addEntryImportsAhead(() => ({
source: 'anyPackage'
}))
addExtraBabelPlugins
添加额外的 Babel 插件。 传入的 fn 不需要参数,且需要返回一个 Babel 插件或插件数组。
addExtraBabelPresets
添加额外的 Babel 插件集。传入的 fn 不需要参数,且需要返回一个 Babel 插件集或其数组。
addHTMLHeadScripts
往 HTML 的 <head>
元素里添加 Script。传入的 fn 不需要参数,且需要返回一个 string(想要加入的代码) 或者 { async?: boolean, charset?: string, crossOrigin?: string | null, defer?: boolean, src?: string, type?: string, content?: string }
或者它们的数组。
api.addHTMLHeadScripts(() => `console.log('I am in HTML-head')`)
addHTMLLinks
往 HTML 里添加 Link 标签。 传入的 fn 不需要参数,返回的对象或其数组接口如下:
{
as ? : string, crossOrigin
:
string | null,
disabled ? : boolean,
href ? : string,
hreflang ? : string,
imageSizes ? : string,
imageSrcset ? : string,
integrity ? : string,
media ? : string,
referrerPolicy ? : string,
rel ? : string,
rev ? : string,
target ? : string,
type ? : string
}
addHTMLMetas
往 HTML 里添加 Meta 标签。 传入的 fn 不需要参数,返回的对象或其数组接口如下:
{
content ? : string,
'http-equiv' ? : string,
name ? : string,
scheme ? : string
}
例如,
api.addHTMLMetas(() => [
{
'http-equiv': 'Cache-Control',
'content': 'no-store, no-cache, must-revalidate'
},
{
'http-equiv': 'Pragma',
'content': 'no-cache'
},
{
'http-equiv': 'Expires',
'content': '0'
}
]);
addHTMLScripts
往 HTML 尾部添加 Script。 传入的 fn 不需要参数,返回的对象接口同 addHTMLHeadScripts
addHTMLStyles
往 HTML 里添加 Style 标签。 传入的 fn 不需要参数,返回一个 string (style 标签里的代码)或者 { type?: string, content?: string }
,或者它们的数组。
addLayouts
添加全局 layout 组件。 传入的 fn 不需要参数,返回 { id?: string, file: string }
addMiddlewares
添加中间件,在 route 中间件之后。 传入的 fn 不需要参数,返回 express 中间件。
addPolyfillImports
添加补丁 import,在整个应用的最前面执行。 传入的 fn 不需要参数,返回 { source: string, specifier?:string }
addPrepareBuildPlugins
addRuntimePlugin
添加运行时插件,传入的 fn 不需要参数,返回 string ,表示插件的路径。
addRuntimePluginKey
添加运行时插件的 Key, 传入的 fn 不需要参数,返回 string ,表示插件的路径。
addTmpGenerateWatcherPaths
添加监听路径,变更时会重新生成临时文件。传入的 fn 不需要参数,返回 string,表示要监听的路径。
addOnDemandDeps
添加按需安装的依赖,他们会在项目启动时检测是否安装:
api.addOnDemandDeps(() => [{ name: '@swc/core', version: '^1.0.0', dev: true }])
chainWebpack
通过 webpack-chain 的方式修改 webpack 配置。传入一个fn,该 fn 不需要返回值。它将接收两个参数:
memo
对应 webpack-chain 的 configargs:{ webpack, env }
arg.webpack
是 webpack 实例,args.env
代表当前的运行环境。
e.g.
api.chainWebpack((memo, { webpack, env }) => {
// set alias
memo.resolve.alias.set('a', 'path/to/a');
// Delete progess bar plugin
memo.plugins.delete('progess');
})
modifyAppData
修改 app 元数据。传入的 fn 接收 appData 并且返回它。
api.modifyAppData((memo) => {
memo.foo = 'foo';
return memo;
})
modifyBundlerChain
modifyBundlerChain
用于调用 rspack-chain 来修改 Rspack 的配置。 rspack-chain
是一个用于配置 Rspack 的工具库。它提供了链式 API,使得配置 Rspack 变得更加灵活。通过使用 rspack-chain
,你可以更方便地修改和扩展 Rspack 配置,而不需要直接操作复杂的配置对象。
可以参考 配置 Rspack。
- 类型:
type ModifyBundlerChainUtils = {
environment: EnvironmentContext;
env: NodeEnv;
isDev: boolean;
isProd: boolean;
target: RsbuildTarget;
isServer: boolean;
isWebWorker: boolean;
CHAIN_ID: ChainIdentifier;
HtmlPlugin: typeof import('html-rspack-plugin');
bundler: {
BannerPlugin: rspack.BannerPlugin;
DefinePlugin: rspack.DefinePlugin;
IgnorePlugin: rspack.IgnorePlugin;
ProvidePlugin: rspack.ProvidePlugin;
HotModuleReplacementPlugin: rspack.HotModuleReplacementPlugin;
};
};
function ModifyBundlerChain(
callback: (
chain: RspackChain,
utils: ModifyBundlerChainUtils,
) => Promise<void> | void,
): void;
- 示例:
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
api.modifyBundlerChain((chain, utils) => {
if (utils.env === 'development') {
chain.devtool('eval');
}
chain.plugin('bundle-analyze').use(BundleAnalyzerPlugin);
});
modifyConfig
修改配置,相较于用户的配置,这份是最终传给 WinJS 使用的配置。传入的 fn 接收 config 作为第一个参数,并且返回它。另外 fn 可以接收 { paths }
作为第二个参数。paths
保存了 WinJS 的各个路径。
api.modifyConfig((memo, { paths }) => {
memo.alias = {
...memo.alias,
'@': paths.absSrcPath
}
return memo;
})
modifyDefaultConfig
修改默认配置。传入的 fn 接收 config 并且返回它。
modifyHTML
修改 HTML,基于 cheerio 的 ast。传入的 fn 接收 cheerioAPI 并且返回它。另外 fn 还可以接收{ path }
作为它的第二个参数,该参数代表路由的 path
api.modifyHTML(($, { path }) => {
$('h2').addClass('welcome');
return $;
})
modifyHTMLFavicon
修改 HTML 的 favicon 路径。 传入的 fn 接收原本的 favicon 路径(string 类型)并且返回它。
modifyPaths
修改 paths,比如 absOutputPath、absTmpPath。传入的 fn 接收 paths 并且返回它。
paths 的接口如下:
paths:{
cwd ? : string;
absSrcPath ? : string;
absPagesPath ? : string;
absTmpPath ? : string;
absNodeModulesPath ? : string;
absOutputPath ? : string;
}
modifyRendererPath
修改 renderer path。传入的 fn 接收原本的 path (string 类型)并且返回它。
modifyServerRendererPath
修改 server renderer path。传入的 fn 接收原本的 path (string 类型)并且返回它。
modifyRoutes
修改路由。 传入的 fn 接收 id-route 的 map 并且返回它。其中 route 的接口如下:
interface IRoute {
path: string;
file?: string;
id: string;
parentId?: string;
[key: string]: any;
}
e.g.
api.modifyRoutes((memo) => {
Object.keys(memo).forEach((id) => {
const route = memo[id];
if (route.path === '/') {
route.path = '/redirect'
}
});
return memo;
})
modifyRsbuildConfig
修改传递给 Rsbuild 的配置项,你可以直接修改传入的 config 对象,也可以返回一个新的对象来替换传入的对象。
可以参考 配置 Rsbuild。
- 类型:
import { RsbuildConfig, Rspack, rspack } from '@rsbuild/core';
export enum Env {
development = 'development',
production = 'production',
}
function ModifyRsbuildConfig(
callback: (
config: RsbuildConfig,
args: {
env: Env;
rspack: typeof rspack
},
) => MaybePromise<RsbuildConfig | void>,
): void;
- 示例: 为某个配置项设置一个默认值:
api.modifyRsbuildConfig((config) => {
config.html ||= {};
config.html.title = 'My Default Title';
return config;
});
modifyRspackConfig
修改最终的 Rspack 配置,你可以直接修改传入的 config 对象,也可以返回一个新的对象来替换传入的对象。
可以参考 配置 Rspack。
- 类型:
type ModifyRspackConfigUtils = {
environment: EnvironmentContext;
env: NodeEnv;
isDev: boolean;
isProd: boolean;
target: RsbuildTarget;
isServer: boolean;
isWebWorker: boolean;
rspack: Rspack;
};
function ModifyRspackConfig(
callback: (
config: RspackConfig,
utils: ModifyRspackConfigUtils,
) => Promise<RspackConfig | void> | RspackConfig | void,
): void;
- 示例:
api.modifyRspackConfig((config, utils) => {
if (utils.env === 'development') {
config.devtool = 'eval-cheap-source-map';
}
});
modifyTSConfig
修改临时目录下的 tsconfig 文件内容。
api.modifyTSConfig((memo) => {
memo.compilerOptions.paths['foo'] = ['bar'];
return memo;
});
modifyViteConfig
修改 vite 最终配置。 传入的 fn 接收 vite 的 Config 对象作为第一个参数并且返回它。另外 fn 还可以接收 { env }
作为第二个参数,可以通过该参数获取当前的环境。
api.modifyViteConfig((memo, { env }) => {
if (env === 'development') {
// do something
}
return memo;
})
modifyWebpackConfig
修改 webpack 最终配置。传入的 fn 接收 webpack 的 Config 对象作为第一个参数并且返回它。另外 fn 还可以接收 { webpack, env }
作为第二个参数,其中 webpack 是 webpack 实例,env 代表当前环境。
api.modifyWebpackConfig((memo, { webpack, env }) => {
// do something
return memo;
})
onBeforeCompiler
generate 之后,webpack / vite / rsbuild compiler 之前。传入的 fn 不接收任何参数。
onBeforeMiddleware
提供在服务器内部执行所有其他中间件之前执行自定义中间件的能力, 这可以用来定义自定义处理程序, 例如:
api.onBeforeMiddleware(({ app }) => {
app.get('/some/path', function (req, res) {
res.json({ custom: 'response' });
});
});
onBuildComplete
build 完成时。传入的 fn 接收 { isFirstCompile: boolean, stats, time: number, err?: Error }
作为参数。
onBuildHtmlComplete
build 完成且 html 完成构建之后。传入的 fn 接收的参数接口如下:
args: {
htmlFiles ? : Array<{ path: string, content: string }>
}
- path:
html
文件路径 - content:
html
文件内容
如:
htmlFiles: [
{
path: 'index.html',
content: '<!DOCTYPE html><html lang="zh-CN"><head>\n' +
'<meta charset="utf-8">\n' +
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">\n' +
'<meta http-equiv="X-UA-Compatible" content="ie=edge">\n' +
'<meta name="renderer" content="webkit">\n' +
'<meta name="mobile-web-app-capable" content="yes">\n' +
'<meta name="apple-mobile-web-app-status-bar-style" content="black">\n' +
'<meta name="telephone=no" content="format-detection">\n' +
'<meta name="email=no" content="format-detection">\n' +
'<style>\n' +
' html,\n' +
' body,\n' +
' #root {\n' +
' height: 100%;\n' +
' margin: 0;\n' +
' padding: 0;\n' +
' }</style>\n' +
'</head>\n' +
'<body>\n' +
'\n' +
' <div id="root">\n' +
'<div style="\n' +
' display: flex;\n' +
' flex-direction: column;\n' +
' align-items: center;\n' +
' justify-content: center;\n' +
' height: 100%;\n' +
' min-height: 362px;\n' +
' ">\n' +
' <div class="loading-title">\n' +
' 正在加载资源\n' +
' </div>\n' +
' <div class="loading-sub-title">\n' +
' 初次加载资源可能需要较多时间 请耐心等待\n' +
' </div>\n' +
'</div>\n' +
'</div>\n' +
'\n' +
'<script src="/win.js"></script>\n' +
'\n' +
'</body></html>'
}
]
onCheck
检查时,在 onStart 之前执行。传入的 fn 不接收任何参数
onCheckCode
检查代码时。传入的 fn 接收的参数接口如下:
args: {
file: string;
code: string;
isFromTmp: boolean;
imports: {
source: string;
loc: any;
default:
string;
namespace: string;
kind: babelImportKind;
specifiers: Record<string, { name: string; kind: babelImportKind }>;
}
[];
exports: any[];
cjsExports: string[];
}
onCheckConfig
检查 config 时。传入的 fn 接收 { config, userConfig }
作为参数,它们分别表示实际的配置和用户的配置。
onCheckPkgJSON
检查 package.json 时。传入的 fn 接收 {origin?, current}
作为参数。它们的类型都是 package.json 对象
onDevCompileDone
dev 完成时。传入的 fn 接收的参数接口如下:
args: {
isFirstCompile: boolean;
stats: any;
time: number;
}
onGenerateFiles
生成临时文件时,随着文件变化会频繁触发,有缓存。 传入的 fn 接收的参数接口如下:
args: {
isFirstTime ? : boolean;
files ? : {
event: string;
path: string;
} | null;
}
onPatchRoute
匹配单个路由,可以修改路由,给路由打补丁
onPkgJSONChanged
package.json 变更时。传入的 fn 接收 {origin?, current}
作为参数。它们的类型都是 package.json 对象
onPrepareBuildSuccess
onStart
启动时。传入的 fn 不接收任何参数。
writeTmpFile
api.writeTmpFile()
的 type 参数的类型。
- content: 写入的文本内容,有内容就不会使用模板。
- context: 模板上下文。
- noPluginDir: 是否使用插件名做为目录。
- path: 写入文件的路径。
- tpl: 使用模板字符串,没有模板路径会使用它。
- tplPath: 使用模板文件的路径。
属性
从 api 可以直接访问到的属性,这些属性有一部分来自于 service
appData
args
命令行参数,这里去除了命令本身。
e.g.
$ win dev --foo
, args 为{ _:[], foo: true }
$ win g page index --typescript --less
, args 为{ _: [ 'page', 'index''], typescript: true, less: true }
config
最终的配置(取决于你访问的时机,可能是当前收集到的最终配置)
cwd
当前路径
env
即 process.env.NODE_ENV
可能有 development
、production
和 test
logger
插件日志对象,包含 { log, info, debug, error, warn, profile }
,他们都是方法。其中 api.logger.profile
可用于性能耗时记录。
api.logger.profile('barId');
setTimeout(() => {
api.logger.profile('barId');
})
// profile - barId Completed in 6254ms
name
当前命令的名称,例如 $ win dev
, name
就是 dev
paths
项目相关的路径:
absNodeModulesPath
,node_modules 目录绝对路径absOutputPath
,输出路径,默认是 ./distabsPagesPath
,pages 目录绝对路径absSrcPath
,src 目录绝对路径,需注意 src 目录是可选的,如果没有 src 目录,absSrcPath 等同于 cwdabsTmpPath
,临时目录绝对路径cwd
,当前路径
注意: 注册阶段不能获取到。因此不能在插件里直接获取,要在 hook 里使用。
pkg
当前项目的 package.json
对象
pkgPath
当前项目的 package.json
的绝对路径。
plugin
当前插件的对象。
type
插件类型,有 preset 和 plugin 两种path
插件路径id
插件 idkey
插件 keyconfig
插件的配置enableBy
插件的启用方式
注意: 注册阶段使用的 plugin 对象是你 describe
之前的对象。
service
WinJS 的 Service
实例。通常不需要用到,除非你知道为什么。
userConfig
用户的配置,从 .winrc
或 config/config
中读取的内容,没有经过 defaultConfig 以及插件的任何处理。可以在注册阶段使用。
ApplyPluginsType
api.applyPlugins()
的 type 参数的类型。包含
- add
- modify
- event
ConfigChangeType
为 api.describe()
提供 config.onChange
的类型,目前包含两种:
- restart,重启 dev 进程,是默认值
- regenerateTmpFiles,重新生成临时文件
EnableBy
插件的启用方式,包含三种:
- register
- config
ServiceStage
WinJS service 的运行阶段。有如下阶段:
- uninitialized
- init
- initPresets
- initPlugins
- resolveConfig
- collectAppData
- onCheck
- onStart
- runCommand