Skip to content

快速入门

快速新建一个插件

Umi 体系中约定了根目录下存在 plugin 文件,作为本地插件的约定入口,只要存在这个文件,就会被挂载。

目录

  • 目录结构如下:
bash

├── plugin
   ├── plugin1.ts
└── src
  • plugin1.ts 内容如下:
ts
import { IApi } from "umi";

export default (api: IApi) => {
  api.onStart(() => {
    console.log("插件1启动");
  });
};

加载

  • config/config.ts 中配置: 或者对应的环境文件中配置
ts
export default {
  plugins: [require.resolve("../plugin/plugin1.ts")],
};
  • 启动项目,可以看到控制台输出:
bash
插件1启动

通过 presets 加载插件

presets 就是插件集合,所以你可以通过在插件集中配置 plugins,这个效果和直接在配置中配置 plugins 是一样的。

目录

  • 目录结构如下:
bash

├── presets
   ├── presets.ts
└── src

先写两个 plugin 插件

根目录创建文件夹 plugin在创建两个文件 plugin1.tsplugin2.ts

  • plugin1.ts 内容如下:
ts
import { IApi } from "umi";

export default (api: IApi) => {
  api.onStart(() => {
    console.log("插件1启动");
  });
};
  • plugin2.ts 内容如下:
ts
import { IApi } from "umi";

export default (api: IApi) => {
  api.onStart(() => {
    console.log("插件2启动");
  });
};

代码(presets)

ts
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
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",
});

启动

  • 启动项目,可以看到控制台输出:
bash
插件1启动
插件2启动

插件 API

如我们上面提到的 api.onStart 就是其中的一个 Api ,也相映对应了一个 Umi 的生命周期,“在项目启动时”。

今天我们先对他们有一个粗略的了解。Umi 的 Api 主要分为三类。核心方法扩展方法属性

属性

性就是提供的一些全局数据,在你需要的时候,直接去取就行,后续会详细介绍,这里不做过多讲解。

比如api.pathsonStart中打印它

ts
import { IApi } from "umi";

export default (api: IApi) => {
  api.onStart(() => {
    console.log("Local Plugin");
    console.log(api.paths);
  });
};
  • 打印结果
bash
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 来作为唯一标识。

ts
api.registerXXXX({ key: string, name: string });
  • 注册一个命令
ts
api.registerCommand({
  name: "hello",
  fn: () => {
    console.log("插件1执行了注册模块");
  },
});
  • 然后再 package.json 里面写命令
bash
  "scripts": {
    "dev": "umi dev",
    "build": "umi build",
    "postinstall": "umi setup",
    "start:testplugin": "cross-env PORT=3000 UMI_ENV=development MOCK=none umi hello",
  },
  • 接着敲击命令即可
bash
npm run start:testplugin

api.addXXXX

add 开头的 Api 是为了增加某个东西的,大部分属于增加数据类的接口。这意味着每个接口都会对应着一个“原始数据对象”。比如你需要增加一个 babel 插件配置,你就可以使用 addBeforeBabelPlugins。在主入口增加一些代码,你可以用 addEntryCode。给项目加一个全局的布局组件 addLayouts。 这部分的理解成本比较低,有部分 api 提供的方法,通过配置文件中提供的配置也可以实现,通过 api 的方式,就可以更自由一点,比如你可以按条件增加某个"东西"。 这里有个原则,“如果你不知道这是什么东西,说明你用不到它”。这会让你在阅读这部分官方文档的时候,无比的舒畅。

api.modifyXXXX

modify 开头的 Api 是为了修改某个东西的,大部分属于修改数据类的接口。比如修改 webpack 配置,你可以使用 modifyWebpackConfig。修改路由,你可以使用 modifyRoutes。修改插件配置,你可以使用 modifyConfig

ts
api.modifyXXXX({ key: string, name: string });
  • 举例
ts
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;
});

需要特别关注的点是memoreturn memo

ts
api.modifyConfig((memo: any) => {
  // some beautiful code
  return memo;
});

理解了上述内容,那 Umi 的 70 个 Api 在你的眼里就是

ts
api.registerXXXX({
  name: "唯一值",
  fn: () => {
    "干些啥事";
  },
});
api.addXXXXX(() => {
  return "返回要添加的一些东西";
});
api.modifyXXXX((memo) => {
  memo.some = "一些想要修改的东西";
  return memo;
});
if (api.属性 === "xxx") {
  ("当某个条件时,我想做一些事情。");
}
// 有一个方法类,我需要获取一点数据
someUtil(api.属性);