umi

"version": "3.4.19"

@umijs/preset-built-in 负责注册umi命令

比如:umi generate tmp

image.png

umi generate tmp 的tmp也是在文件generate.ts中

  api.registerGenerator({
    key: 'tmp',
    // @ts-ignore
    Generator: createTmpGenerator({ api }),
  });

使用lerna组合umi跟dumi项目,umi一直安装不成功

lerna.json

{
  "packages": ["packages/*"],
  "npmClient": "yarn",
  "useWorkspaces": true,
  "version": "independent"
}

package.json

{
  "workspaces": [
    "packages/*"
  ]
}

其实控制台做了提示


提示不成功

只是warning不醒目,改成error 提醒要好点,两个项目都加上version字段就顺利安装成功了

使用lerna run 控制台没有umi的脚本输出

加上--stream参数

  "scripts": {
    "start": "lerna run start --stream",
    "start:ui": "lerna --scope geek-ui run start --stream"
  }
有umi输出

umi3.0 dva onAction 在哪里设置

react 中使用svg

webpack 做配置:

[..]
{
    test: /\.svg$/,
    use: ['@svgr/webpack'],
},
[..]

使用:

import { ReactComponent as Logo } from './logo.svg';

Loader: Load SVG images

用vscode观察umi是怎样启动项目的

用umi生成的web项目,在scripts通常是这样

  "scripts": {
    "start": "umi dev",
    "build": "umi build",
    "postinstall": "umi generate tmp",
  },

怎样观测umi是怎样启动项目的,我想debug看看,做如下配置:
launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "inspect umi",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}",
      "program": "${workspaceFolder}/node_modules/umi/lib/cli.js", // umi 脚本所在位置
      // "outFiles": ["${workspaceFolder:cmp}/node_modules/umi/lib/**/*/js"],
      "args": ["dev"] // umi 命令需要的参数
    }
  ]
}

program 跟 args合起来就是umi dev 命令,这样就可以愉快的debug umirc.ts了

如何在VS Code中debug umi,观察编译过程
vscode 调试 umi

[email protected] 项目瘦身

目的:虽然是B端的项目,但是用户首次打开页面觉得很慢,所以需要优化首页文件大小。脑海里的方向有两个:分包,按需加载。查阅umi文档,首先找到dynamicImport,开开心心的做了配置,首页加载的文件大小的确小了大概一半,但是样式出来问题,ant的样式把自定义的样式覆盖了,别人也需要到同样的问题开启dynamicImport后样式引入顺序问题 #5883,审查元素发现自定义的样式是内联的,ant的样式是link进去的,也就是说ant的样式的顺序在自定义样式的后面加载,覆盖了自定义样式,因此需要将ant的顺序在自定义文件之前加载。umijs文档有个chunks配置跟文件加载顺序有关。

import Config from 'webpack-chain'
const AntdDayjsWebpackPlugin = require('antd-dayjs-webpack-plugin')

const webpackConfig: any = (_: Config) => {
  _.merge({
    optimization: {
      splitChunks: {
        cacheGroups: {
          antd: {
            name: 'antd',
            chunks: 'all',
            test: /[\\/]node_modules[\\/](antd|@ant-design)[\\/]/,
            priority: 10
          }
        }
      }
    }
  })
}
export default webpackConfig

chunks: ['antd', 'umi'],

这样样式就不会有问题了。但是通过umi-webpack-bundle-analyzer分析有些很大的包(比如echarts docx)被打包到umi.js中导致首页加载的还是比较慢,继续分包

  _.merge({
    optimization: {
      splitChunks: {
        cacheGroups: {
          // 组件库相关
          react: {
            name: 'react',
            chunks: 'all',
            test: /[\\/]node_modules[\\/](react|react-dom|react-router|react-router-dom)[\\/]/,
            priority: 12
          },
          // 图表库相关
          charts: {
            name: 'charts',
            chunks: 'async',
            test: /[\\/]node_modules[\\/](echarts|zrender)[\\/]/,
            priority: 11
          },
          docx: {
            name: 'docx',
            chunks: 'async',
            test: /[\\/]node_modules[\\/](docx)[\\/]/,
            priority: 11
          },
          antd: {
            name: 'antd',
            chunks: 'all',
            test: /[\\/]node_modules[\\/](antd|@ant-design)[\\/]/,
            priority: 10
          }
        }
      }
    }
  })

同时在chunks中做配置

chunks: ['react', 'charts','docx','antd', 'umi'],

包文件是拆分出来了,但是首页加载的时候charts docx等文件还是被加载了,docx echarts并没有在首页用到,why?搜索并没有查到,只好翻看umijs源码。
body插入script文件处:


Html.ts getContent

翻阅代码可以发现在.umrc中定义的chunks: ['react', 'charts','docx','antd', 'umi']在此会被插入到HTML中,插入的顺序是按照从左到右的顺序,左边的会先加载,我们可以把antd的代码写在前面,我们自己写的代码会被打包到umi.js umi.css 中,这样就保证我们自己的代码会把antd的样式覆盖了。将charts跟docx从chunks删掉,修改后的chunks: ['react', 'antd', 'umi'] 这样首页就不会加载charts跟docx。

[email protected] 重写node.js module的_resolveFilename方法的目的是啥子?

requireHook.ts

// files 为webpack的代码
export const files = [
  'webpack/lib/Chunk',
  'webpack/lib/Compilation',
  'webpack/lib/dependencies/ConstDependency',
  'webpack/lib/javascript/JavascriptParserHelpers',
  'webpack/lib/LibraryTemplatePlugin',
  'webpack/lib/LoaderTargetPlugin',
  'webpack/lib/node/NodeTargetPlugin',
  'webpack/lib/node/NodeTemplatePlugin',
  'webpack/lib/ModuleFilenameHelpers',
  'webpack/lib/NormalModule',
  'webpack/lib/RequestShortener',
  'webpack/lib/RuntimeGlobals',
  'webpack/lib/RuntimeModule',
  'webpack/lib/optimize/LimitChunkCountPlugin',
  'webpack/lib/ParserHelpers',
  'webpack/lib/SingleEntryPlugin',
  'webpack/lib/Template',
  'webpack/lib/webworker/WebWorkerTemplatePlugin',
];

export function init() {
  // Allow run once
  if (inited) return;
  inited = true;

  const filesMap = files.map((file) => {
    const fileName = getFileName(file);
    return [file, `@umijs/deps/compiled/webpack/${fileName}`];
  });

  const hookPropertyMap = new Map(
    [
      ['webpack', '@umijs/deps/compiled/webpack'],
      ['webpack/package.json', '@umijs/deps/compiled/webpack/pkgInfo'],
      ...filesMap,
      // ['webpack-sources', '@umijs/deps/compiled/webpack/sources'],
    ].map(([request, replacement]) => [request, require.resolve(replacement)]),
  );

  const mod = require('module');
  const resolveFilename = mod._resolveFilename;
  mod._resolveFilename = function (
    request: string,
    parent: any,
    isMain: boolean,
    options: any,
  ) {
    const hookResolved = hookPropertyMap.get(request);
    if (hookResolved) request = hookResolved;
    return resolveFilename.call(mod, request, parent, isMain, options);
  };
}

Module._resolveFilename 是为了获取模块的绝对路径,重写是为了在使用比如const webpack =require("webpack")的时候不是去node_modules加载webpack,而是从@umijs/deps/compiled/webpack加载。我们在node_modules也可以搜索下webpack目录,发现压根找不到,而是被umi塞到了@umijs/deps/compiled/webpack下,为什么要这么做?,很大的可能性就是为了兼容4 5 两个版本。但是我们使用webpack方式不会变,所以就重写了node.js Module._resolveFilename函数。

你可能感兴趣的:(umi)