"version": "3.4.19"
@umijs/preset-built-in 负责注册umi命令
比如:umi generate tmp
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"
}
react 中使用svg
webpack 做配置:
[..]
{
test: /\.svg$/,
use: ['@svgr/webpack'],
},
[..]
使用:
import { ReactComponent as Logo } from './logo.svg';
用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
umi@3.5.3 项目瘦身
目的:虽然是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文件处:
翻阅代码可以发现在.umrc中定义的chunks: ['react', 'charts','docx','antd', 'umi']
在此会被插入到HTML中,插入的顺序是按照从左到右的顺序,左边的会先加载,我们可以把antd的代码写在前面,我们自己写的代码会被打包到umi.js umi.css 中,这样就保证我们自己的代码会把antd的样式覆盖了。将charts跟docx从chunks删掉,修改后的chunks: ['react', 'antd', 'umi']
这样首页就不会加载charts跟docx。
umi@3.5.3 重写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函数。