umi插件开发

1,930 阅读1分钟
  • 如果有依赖的插件,需要先下载安装至package.json中

  • 被依赖的项目中需要安装其它插件,在peerDepencecies中记录

  • README.MD文档中介绍插件功能以及umirc的简单配置

umi相应插件 API

api.describe

使用api.describe进行插件注册

  api.describe({
    key: 'szhooks',
    config: {
      schema(joi) {
        return joi.object({
          name: joi.string(),
          publicPath: joi.string(),
          proxyTarget: joi.string(),
        });
      },
      onChange: api.ConfigChangeType.regenerateTmpFiles,
    },
  });
  • config.default 为配置的默认值,用户没有配置时取这个

  • config.schema 用于声明配置的类型,如果你希望用户进行配置,这个是必须的,否则用户的配置无效

  • config.onChange 是 dev 阶段配置被修改后的处理机制,默认会重启 dev 进程,也可以修改为 api.ConfigChangeType.regenerateTmpFiles 只重新生成临时文件,还可以通过函数的格式自定义

  • enableBy 为启用方式,默认是注册启用,可更改为 api.EnableBy.config,还可以用自定义函数的方式决定其启用时机(动态生效)

api.addDepInfo

使用api.addDepInfo添加依赖信息,包括 semver range 和别名信息。

  api.addDepInfo(() => {
    const pkg = require('../package.json');
    return [
      {
        name: '@szzj/hooks',
        range: pkg.devDependencies['@szzj/hooks'],
      },
    ];
  });

api.addUmiExports

添加需要umi额外导出的内容,返回值格式为{ source: string, specifers?: (string | (local: string, exported: string)) [], exportAll?: boollean }比如api.addUmiExports(() => { source: 'dva', specifiers:['connect'] }),然后就可以通过 import { connect } from 'umi' 使用 dva 的 connect 方法了。

  // 导出 hooks
  api.addUmiExports(() => [
    {
      specifiers: [ 'useModal','useList','useTree', 'useForm','useFetch','useRoutes'],
      source: `../${DIR_NAME}/hooks`,
    },
  ]);

api.onGenerateFiles

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

  api.onGenerateFiles(() => {
    if (generatedOnce) return;
    generatedOnce = true;
    const cwd = join(__dirname, '../src');
    const files = utils.glob.sync('**/*', {
      cwd,
    });
    const base = join(api.paths.absTmpPath!, DIR_NAME);
    utils.mkdirp.sync(base);
    files.forEach((file) => {
      if (['index.ts'].includes(file)) return;
      const source = join(cwd, file);
      const target = join(base, file);
      if (statSync(source).isDirectory()) {
        utils.mkdirp.sync(target);
      } else {
        copyFileSync(source, target);
      }
    });

插件编译后保留的文件有src下的除index.ts文件

api.modifyDefaultConfig

umirc的默认配置,如history、cssloader、define、qiankun等

api.modifyDefaultConfig(config => {
    config.history = { 
      type: 'hash' 
    };

    config.dynamicImport = { };

    config.cssLoader = {
      localsConvention: 'camelCase',
    };

    const { name, proxyTarget, publicPath } = api.userConfig.subapp;
    if (name) {
      config.base = `/${name}`;
      config.mountElementId = `app_slave_${name}`;
    };

    const { NODE_ENV, DEPLOY_ENV, DEPLOY_REGION } = process.env;
    config.define = {
      'process.env.NODE_ENV': NODE_ENV,
      'process.env.DEPLOY_ENV': DEPLOY_ENV,
      'process.env.DEPLOY_REGION': DEPLOY_REGION,
      'process.env.URL_PREFIX': NODE_ENV === 'development' ? '/api' : `/${name}`,
    };

    if (process.env.NODE_ENV !== 'production' && name && proxyTarget){
      config.proxy = {
        '/api': {
          target: proxyTarget,
          pathRewrite: {
            '^/api': `/${name}`,
          },
          changeOrigin: true,
        },
      }
    };

    if (publicPath){
      config.publicPath = process.env.NODE_ENV === 'production' ? publicPath : '/';
    };

    // 会修改 publicPath 属性,所以需要放在 publicPath 后
    config.qiankun = {
      slave: {},
    };

    config.sass = {};

    config.externals = process.env.NODE_ENV !== 'production'
      ? undefined
      : {
          react: {
            root: 'React',
            commonjs2: 'react',
            commonjs: 'react',
            amd: 'react',
          },
          'react-dom': {
            root: 'ReactDOM',
            commonjs2: 'ReactDOM',
            commonjs: 'ReactDOM',
            amd: 'ReactDOM',
          },
        };

    return config;
  });

api.chainWebpack

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

  api.chainWebpack((config) => {
    config.output.filename(`[name].[hash].js`);
    config.output.chunkFilename(`[name].[hash].async.js`);
    config.plugin('extract-css').tap(() => { 
      return [
        {
          filename: `[name].[hash].css`,
          chunkFilename: `[name].[hash].chunk.css`,
          ignoreOrder: true,
        },
      ];
    });

    return config;
  });

注意:要有返回值