fes.js/docs/reference/plugin/dev/api.md
2021-03-08 20:45:57 +08:00

11 KiB
Raw Blame History

插件 API

属性

api.paths

一些关键的路径:

  • cwd执行命令的绝对路径
  • absNodeModulesPathnodeModule的绝对路径
  • absOutputPath输出 build 产物的绝对路径
  • absSrcPathsrc 目录的绝对路径
  • absPagesPathpages目录的绝对路径
  • absTmpPath.fes临时文件目录的绝对路径

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({
    key: 'esbuild',
    config: {
        schema(joi) {
            return joi.object();
        },
        default: {}
    },
    enableBy: api.EnableBy.config,
});

注:

  • config.default 为配置的默认值,用户没有配置时取这个
  • config.schema 用于声明配置的类型,基于 joi,如果你希望用户进行配置,这个是必须的,否则用户的配置无效
  • config.onChangedev 阶段配置被修改后的处理机制,默认会重启 dev 进程,也可以修改为 api.ConfigChangeType.regenerateTmpFiles 只重新生成临时文件,还可以通过函数的格式自定义
  • enableBy 为启用方式,默认是注册启用,可更改为 api.EnableBy.config,还可以用自定义函数的方式决定其启用时机(动态生效)

applyPlugins

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

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

参数:

  • key
  • type hook的类型。
  • initialValue 初始值。
  • args参数hook函数执行时args会作为参数传入。

例如:

const foo = await api.applyPlugins({
  key: 'foo',
  type: api.ApplyPluginsType.add,
  initialValue: [],
});
console.log(foo); // ['a', 'b']

api.ApplyPluginsType

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

  • compose用于合并执行多个函数函数可决定前序函数的执行时机
  • modify用于修改值
  • event用于执行事件前面没有依赖关系

registerCommand

注册命令,基于 commander 实现的机制。

用法:registerCommand({ command: string, description: string, fn: Function, options?: Object })

参数:

  • command
  • description描述文字输入 --help 会打印
  • fn命令执行的函数参数有
    • rawArgv原始参数
    • args参数
    • options执行命令时附带的的参数配置
    • programcommander对象
  • options参数配置基于 commander

例如:

api.registerCommand({
    command: 'webpack',
    description: 'inspect webpack configurations',
    options: [{
        name: '--rule <ruleName>',
        description: 'inspect a specific module rule'
    }, {
        name: '--plugin <pluginName>',
        description: 'inspect a specific plugin'
    }, {
        name: '--rules',
        description: 'list all module rule names'
    }, {
        name: '--plugins',
        description: 'list all plugin names'
    }, {
        name: '--verbose',
        description: 'show full function definitions in output'
    }],
    async fn({ rawArgv, args, options, program}) {
    }
})

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

fes webpack

registerMethod

api 上注册方法。可以是 api.register() 的快捷使用方式,便于调用;也可以不是,如果有提供 fn,则执行 fn 定义的函数。

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

例如:

 api.registerMethod({
    name: 'writeTmpFile',
    fn({
        path,
        content
    }) {
        assert(
            api.stage >= api.ServiceStage.pluginReady,
            'api.writeTmpFile() should not execute in register stage.'
        );
        const absPath = join(api.paths.absTmpPath, path);
        api.utils.mkdirp.sync(dirname(absPath));
        if (!existsSync(absPath) || readFileSync(absPath, 'utf-8') !== content) {
            writeFileSync(absPath, content, 'utf-8');
        }
    }
});

registerPresets

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

用法:registerPresets(presets: string[])

例如:

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

registerPlugins

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

用法:registerPlugins(plugins: string[])

例如:

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

hasPlugins

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

  • id 默认为包名
  • 内置插件以 @@ 为前缀,比如 @@/registerMethod

用法:hasPlugins(pluginIds: string[])

例如

// 判断是否有注册 @fesjs/plugin-locale
api.hasPlugins(['@fesjs/plugin-locale']);

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

hasPresets

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

用法:hasPresets(presetIds: string[])

例如

// 判断是否有注册
api.hasPlugins(['@fesjs/preset-xxx']);

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

扩展方法

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

onStart

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

onExit

dev 退出时触发。

onGenerateFiles

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

addPluginExports

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

api.addPluginExports(() => [
    {
        specifiers: ['access', 'useAccess'],
        source: absoluteFilePath
    }
]);

这样用户使用时:

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

addRuntimePlugin

添加运行时插件返回值格式为表示文件路径的字符串。Fes.js 会把

例如:

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

addRuntimePluginKey

添加运行时插件的 key返回值格式为字符串。

例如:

api.addRuntimePluginKey(() => 'some');

addEntryImportsAhead

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

例如:

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

addEntryImports

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

例如:

api.addEntryImport(() => {
  return [
    {
      source: '/modulePath/xxx.js',
      specifier: 'moduleName',
    }
  ]
});

addEntryCodeAhead

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

例如:

api.addEntryCodeAhead(
    () => `${globalCSSFile
        .map(file => `require('${winPath(relative(absTmpPath, file))}');`)
        .join('')}`

addEntryCode

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

例如:

api.addEntryCode(() => {
  return `console.log('works!')`
})

addBeforeMiddlewares

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

例如:

api.addBeforeMiddlewares(() => {
  return (req, res, next) => {
    if (false) {
      res.end('end');
    } else {
      next();
    }
  };
});

addMiddlewares

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

modifyRoutes

修改路由。

例如:

// 把BaseLayout插入到路由配置中作为根路由
api.modifyRoutes(routes => [
    {
        path: '/',
        component: winPath(
            join(api.paths.absTmpPath || '', absFilePath)
        ),
        children: routes
    }
]);

modifyBundleConfigOpts

修改获取 bundleConfig 的函数参数。

例如:

api.modifyBundleConfigOpts(memo => {
    memo.miniCSSExtractPluginPath = require.resolve('mini-css-extract-plugin');
    memo.miniCSSExtractPluginLoaderPath = require.resolve(
    'mini-css-extract-plugin/dist/loader',
    );
    return memo;
});

modifyBundleConfig

修改 bundle 配置。

api.modifyBundleConfig((bundleConfig) => {
    // do something
    return bundleConfig;
});

modifyBabelOpts

修改 babel 配置项。

例如:

api.modifyBabelOpts((babelOpts) => {
    if (api.config.babelPluginImport) {
        api.config.babelPluginImport.forEach((config) => {
            babelOpts.plugins.push(['import', config]);
        });
    }
    return babelOpts;
});

modifyBabelPresetOpts

修改 babel 插件的配置。

例如:

api.modifyBabelPresetOpts(opts => {
    return {
      ...opts,
      import: (opts.import || []).concat([
        { libraryName: 'ant-design-vue', libraryDirectory: 'es', style: true },
      ]),
    };
});

modifyPaths

修改 paths 对象。

modifyConfig

修改最终配置。

例如:

api.modifyConfig((memo) => {
  return {
    ...memo,
    ...defaultOptions,
  };
});

chainWebpack

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

例如:

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

addTmpGenerateWatcherPaths

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

例如:

api.addTmpGenerateWatcherPaths(() => [
    './app.js',
]);

writeTmpFile

写临时文件。

例如:

api.writeTmpFile({
    path: absoluteFilePath,
    content: Mustache.render(
        readFileSync(join(__dirname, 'runtime/core.tpl'), 'utf-8'),
        {
            REPLACE_ROLES: JSON.stringify(roles)
        }
    )
});

参数:

  • path相对于临时文件夹的路径
  • content文件内容

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

copyTmpFiles

批量写临时文件。

例如:

 api.copyTmpFiles({
    namespace,
    path: join(__dirname, 'runtime'),
    ignore: ['.tpl']
});

参数:

  • namespace复制到临时文件夹下的目标目录
  • path需要复制的文件目录
  • ignore需要排除的文件

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