快速入门
快速新建一个插件
Umi 体系中约定了根目录下存在 plugin
文件,作为本地插件的约定入口,只要存在这个文件,就会被挂载。
目录
- 目录结构如下:
├── plugin
│ ├── plugin1.ts
└── src
plugin1.ts
内容如下:
import { IApi } from "umi";
export default (api: IApi) => {
api.onStart(() => {
console.log("插件1启动");
});
};
加载
- 在
config/config.ts
中配置: 或者对应的环境文件中配置
export default {
plugins: [require.resolve("../plugin/plugin1.ts")],
};
- 启动项目,可以看到控制台输出:
插件1启动
通过 presets 加载插件
presets
就是插件集合,所以你可以通过在插件集中配置 plugins
,这个效果和直接在配置中配置 plugins
是一样的。
目录
- 目录结构如下:
├── presets
│ ├── presets.ts
└── src
先写两个 plugin 插件
根目录创建文件夹 plugin
在创建两个文件 plugin1.ts
和 plugin2.ts
plugin1.ts
内容如下:
import { IApi } from "umi";
export default (api: IApi) => {
api.onStart(() => {
console.log("插件1启动");
});
};
plugin2.ts
内容如下:
import { IApi } from "umi";
export default (api: IApi) => {
api.onStart(() => {
console.log("插件2启动");
});
};
代码(presets)
import type { IApi } from "umi";
export default (api: IApi) => {
const plugins = [
require.resolve("../plugin/plugin1.ts"),
require.resolve("../plugin/plugin2.ts"),
];
return {
plugins,
};
};
加载
- config.ts
import { defineConfig } from "umi";
export default defineConfig({
title: "development",
// plugins: [require.resolve("../plugin/plugin1.ts")],
presets: [require.resolve("../presets/preset1")],
routes: [
{ path: "/", component: "index" },
{ path: "/docs", component: "docs" },
],
define: {
"process.env": {
UMI_ENV: process.env.UMI_ENV,
DOMAIN: "默认环境",
},
},
npmClient: "pnpm",
});
启动
- 启动项目,可以看到控制台输出:
插件1启动
插件2启动
插件 API
如我们上面提到的 api.onStart
就是其中的一个 Api
,也相映对应了一个 Umi
的生命周期,“在项目启动时”。
今天我们先对他们有一个粗略的了解。Umi 的 Api 主要分为三类。核心方法
,扩展方法
和 属性
。
属性
性就是提供的一些全局数据,在你需要的时候,直接去取就行,后续会详细介绍,这里不做过多讲解。
比如api.paths
在onStart
中打印它
import { IApi } from "umi";
export default (api: IApi) => {
api.onStart(() => {
console.log("Local Plugin");
console.log(api.paths);
});
};
- 打印结果
Local Plugin
{
cwd: 'E:\\Code\\Front\\UMI\\umidemo2',
absSrcPath: 'E:/Code/Front/UMI/umidemo2/src',
absPagesPath: 'E:/Code/Front/UMI/umidemo2/src/pages',
absApiRoutesPath: 'E:/Code/Front/UMI/umidemo2/src/api',
absTmpPath: 'E:/Code/Front/UMI/umidemo2/src/.umi',
absNodeModulesPath: 'E:/Code/Front/UMI/umidemo2/node_modules',
absOutputPath: 'E:/Code/Front/UMI/umidemo2/dist'
}
需要注意的一点是,所有的属性一般都只能在 hooks 里面使用。也就是需要在 api.xxxxx(()=>{ })
的回调中使用。因为有些属性是在注册阶段不存在的,如果你直接使用这些属性,则会产生意料之外的错误。
除了属性之外的其他 Api 差不多都是通过 api.xxxxx(()=>{ })
注册的。这里我们可以简单的对它们进行分类
api.registerXXX
以 register
开头的这部分 Api 多是用于“注册”某些东西,比如注册一个命令 registerCommand
,注册一个微生成器 registerGenerator
。
大多数是传入一个对象,并且这个对象中有一个值,比如 key 或者 name 来作为唯一标识。
api.registerXXXX({ key: string, name: string });
- 注册一个命令
api.registerCommand({
name: "hello",
fn: () => {
console.log("插件1执行了注册模块");
},
});
- 然后再 package.json 里面写命令
"scripts": {
"dev": "umi dev",
"build": "umi build",
"postinstall": "umi setup",
"start:testplugin": "cross-env PORT=3000 UMI_ENV=development MOCK=none umi hello",
},
- 接着敲击命令即可
npm run start:testplugin
api.addXXXX
以 add
开头的 Api 是为了增加某个东西的,大部分属于增加数据类的接口。这意味着每个接口都会对应着一个“原始数据对象”。比如你需要增加一个 babel 插件配置,你就可以使用 addBeforeBabelPlugins
。在主入口增加一些代码,你可以用 addEntryCode
。给项目加一个全局的布局组件 addLayouts
。 这部分的理解成本比较低,有部分 api 提供的方法,通过配置文件中提供的配置也可以实现,通过 api
的方式,就可以更自由一点,比如你可以按条件增加某个"东西"。 这里有个原则,“如果你不知道这是什么东西,说明你用不到它”。这会让你在阅读这部分官方文档的时候,无比的舒畅。
api.modifyXXXX
以 modify
开头的 Api 是为了修改某个东西的,大部分属于修改数据类的接口。比如修改 webpack 配置,你可以使用 modifyWebpackConfig
。修改路由,你可以使用 modifyRoutes
。修改插件配置,你可以使用 modifyConfig
。
api.modifyXXXX({ key: string, name: string });
- 举例
const configDefaults = {
history: { type: "hash" },
targets: {
ie: 9,
},
hash: true,
model: {},
request: {},
displayName: "alita-demo",
...api.userConfig,
};
api.modifyConfig((memo: any) => {
Object.keys(configDefaults).forEach((key) => {
memo[key] = configDefaults[key];
});
return memo;
});
需要特别关注的点是memo
和return memo
api.modifyConfig((memo: any) => {
// some beautiful code
return memo;
});
理解了上述内容,那 Umi 的 70 个 Api 在你的眼里就是
api.registerXXXX({
name: "唯一值",
fn: () => {
"干些啥事";
},
});
api.addXXXXX(() => {
return "返回要添加的一些东西";
});
api.modifyXXXX((memo) => {
memo.some = "一些想要修改的东西";
return memo;
});
if (api.属性 === "xxx") {
("当某个条件时,我想做一些事情。");
}
// 有一个方法类,我需要获取一点数据
someUtil(api.属性);