偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一篇非常 Nice 的 UmiJS 教程

開發(fā) 前端
網(wǎng)上的umi教程是真的少,很多人都只寫了一點點,很多水文,所以打算自己寫一篇,自己搭建umi,并封裝了一下常用的功能,并用到公司實際項目中。

[[437884]]

 前言

網(wǎng)上的umi教程是真的少,很多人都只寫了一點點,很多水文,所以打算自己寫一篇,自己搭建umi,并封裝了一下常用的功能,并用到公司實際項目中.

umi介紹

Umi 是什么?

Umi,中文可發(fā)音為烏米,是可擴(kuò)展的企業(yè)級前端應(yīng)用框架。Umi 以路由為基礎(chǔ)的,同時支持配置式路由和約定式路由,保證路由的功能完備,并以此進(jìn)行功能擴(kuò)展。然后配以生命周期完善的插件體系,覆蓋從源碼到構(gòu)建產(chǎn)物的每個生命周期,支持各種功能擴(kuò)展和業(yè)務(wù)需求。

Umi 是螞蟻金服的底層前端框架,已直接或間接地服務(wù)了 3000+ 應(yīng)用,包括 java、node、H5 無線、離線(Hybrid)應(yīng)用、純前端 assets 應(yīng)用、CMS 應(yīng)用等。他已經(jīng)很好地服務(wù)了我們的內(nèi)部用戶,同時希望他也能服務(wù)好外部用戶。

它主要具備以下功能:

  •   🎉 可擴(kuò)展,Umi 實現(xiàn)了完整的生命周期,并使其插件化,Umi 內(nèi)部功能也全由插件完成。此外還支持插件和插件集,以滿足功能和垂直域的分層需求。
  •   📦 開箱即用,Umi 內(nèi)置了路由、構(gòu)建、部署、測試等,僅需一個依賴即可上手開發(fā)。并且還提供針對 React 的集成插件集,內(nèi)涵豐富的功能,可滿足日常 80% 的開發(fā)需求。
  •   🐠 企業(yè)級,經(jīng)螞蟻內(nèi)部 3000+ 項目以及阿里、優(yōu)酷、網(wǎng)易、飛豬、口碑等公司項目的驗證,值得信賴。
  •   🚀 大量自研,包含微前端、組件打包、文檔工具、請求庫、hooks 庫、數(shù)據(jù)流等,滿足日常項目的周邊需求。
  •   🌴 完備路由,同時支持配置式路由和約定式路由,同時保持功能的完備性,比如動態(tài)路由、嵌套路由、權(quán)限路由等等。
  •   🚄 面向未來,在滿足需求的同時,我們也不會停止對新技術(shù)的探索。比如 dll 提速、modern mode、webpack@5、自動化 external、bundler less 等等。

什么時候不用 umi?

如果你,

  •   需要支持 IE 8 或更低版本的瀏覽器
  •   需要支持 React 16.8.0 以下的 React
  •   需要跑在 Node 10 以下的環(huán)境中
  •   有很強(qiáng)的 webpack 自定義需求和主觀意愿
  •   需要選擇不同的路由方案

Umi 可能不適合你。

為什么不是?

create-react-app

create-react-app 是基于 webpack 的打包層方案,包含 build、dev、lint 等,他在打包層把體驗做到了極致,但是不包含路由,不是框架,也不支持配置。所以,如果大家想基于他修改部分配置,或者希望在打包層之外也做技術(shù)收斂時,就會遇到困難。

next.js

next.js 是個很好的選擇,Umi 很多功能是參考 next.js 做的。要說有哪些地方不如 Umi,我覺得可能是不夠貼近業(yè)務(wù),不夠接地氣。比如 antd、dva 的深度整合,比如國際化、權(quán)限、數(shù)據(jù)流、配置式路由、補(bǔ)丁方案、自動化 external 方面等等一線開發(fā)者才會遇到的問題。

umi3項目初始化

環(huán)境準(zhǔn)備

首先得有 node,并確保 node 版本是 10.13 或以上。

推薦使用 yarn 管理 npm 依賴

本項目使用的版本為 node v14.17.5  yarn 1.22.15

腳手架

桌面新建umi3文件夾, 用vscode打開, 打開vscode終端,

執(zhí)行 yarn create @umijs/umi-app 創(chuàng)建項目

安裝依賴 yarn

啟動項目 yarn start

配置 prettier,eslint, stylelint

umi 維護(hù)了一個 prettier,eslint,stylelint 的配置文件合集 umi-fabric 

  1. yarn add @umijs/fabric -D 

根目錄新建下面三個文件,刪除.prettierrc文件

.eslintrc.js、.prettierrc.js、.stylelintrc.js

配置如下 

  1. //.eslintrc.js 配置  
  2. module.exports = {  
  3.   extends: [require.resolve('@umijs/fabric/dist/eslint')],  
  4.   // in antd-design-pro  
  5.   globals: {  
  6.     ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true,  
  7.     page: true,  
  8.   }, 
  9.   rules: {  
  10.     // your rules  
  11.     'prefer-const': 0,  
  12.   },  
  13. };  
  14. //.prettierrc.js 配置  
  15. const fabric = require('@umijs/fabric')  
  16. module.exports = {  
  17.   ...fabric.prettier,  
  18.   semi: false,  
  19.  
  20. //.stylelintrc.js 配置  
  21. const fabric = require('@umijs/fabric')  
  22. module.exports = {  
  23.   ...fabric.stylelint,  

根目錄新建eslint忽略文件  .eslintignore 

  1. .eslintrc.js  
  2. node_modules 

在package.json 里面的lint-staged 新增 "eslint --fix"

最后你的 vscode 要安裝這三個同名擴(kuò)展插件,這時候分別去更改 js、less 文件,會發(fā)現(xiàn)已經(jīng)有風(fēng)格校驗了。

驗證

修改src/paegs文件夾下的index.tsx文件,新增一個a變量,有eslint錯誤提示,說明eslint生效了

然后再單獨提交index.tsx這一個文件

會提示有錯誤,無法提交,說明pre-commmit 鉤子生效

保存時自動格式化代碼

在vscode設(shè)置 文本編輯器的格式化里面  勾選Format on Save

我的eslint,或者prettier 不生效?

去到終端里的輸出,找到eslint或者prettier 看他們的輸出日志,是否正常。如果有報錯,根據(jù)報錯信息處理問題

檢查步驟:

  •  確保安裝umi-fabric
  •  檢查配置文件是否存在
  •  vscode 得eslint 和prettier 插件是否下載
  •  確認(rèn)輸出日志,是否有報錯

pre-commit時的lint-staged 不生效

在package.json中 我們配置了如下得代碼

意思是 在代碼commit之前 執(zhí)行prettier格式化代碼和eslint fix 如果你在提交代碼的時候沒有生效,請執(zhí)行

  1. yarn install --force 

執(zhí)行這個命令重新拉取依賴

不生效的原因?

自己剛開始也是各種google,查看文檔,也沒有找出原因,最后在umi2的一個issue里面,自己找到了答案。

原因在于我們初始化git倉庫的順序,如果我們先初始化git倉庫 然后再創(chuàng)建項目,再拉取依賴。是沒有任何問題的。

如果我們先創(chuàng)建了umi項目,拉去依賴,最后初始化git,提交代碼到git倉庫,當(dāng)我們拉去依賴時, 這是就還沒有.git 就沒有生成相關(guān)的pre-commit,所以就沒有生效。所以這時我們就只需要在重新拉取下依賴就可以了。

配置css初始化代碼

為什么要初始化css

建站老手都知道,這是為了考慮到瀏覽器的兼容問題,其實不同瀏覽器對有些標(biāo)簽的默認(rèn)值是不同的,如果沒對CSS初始化往往會出現(xiàn)瀏覽器之間的頁面差異。當(dāng)然,初始化樣式會對SEO有一定的影響,但魚和熊掌不可兼得,但力求影響最小的情況下初始化。

最簡單的初始化方法就是:* {padding: 0; margin: 0;} 。有很多人也是這樣寫的。這確實很簡單,但有人就會感到疑問:*號這樣一個通用符在編寫代碼的時候是快,但如果網(wǎng)站很大,CSS樣式表文件很大,這樣寫的話,他會把所有的標(biāo)簽都初始化一遍,這樣就大大的加強(qiáng)了網(wǎng)站運(yùn)行的負(fù)載,會使網(wǎng)站加載的時候需要很長一段時間。

CSS初始化是指重設(shè)瀏覽器的樣式。不同的瀏覽器默認(rèn)的樣式可能不盡相同,所以開發(fā)時的第一件事可能就是如何把它們統(tǒng)一。如果沒對CSS初始化往往會出現(xiàn)瀏覽器之間的頁面差異。每次新開發(fā)網(wǎng)站或新網(wǎng)頁時候通過初始化CSS樣式的屬性,為我們將用到的CSS或html標(biāo)簽更加方便準(zhǔn)確,使得我們開發(fā)網(wǎng)頁內(nèi)容時更加方便簡潔,同時減少CSS代碼量,節(jié)約網(wǎng)頁下載時間。

Umi 中約定 src/global.css 為全局樣式,如果存在此文件,會被自動引入到入口文件最前面。

src下面新建global.css,代碼如下 

  1. body,  
  2. ol,  
  3. ul,  
  4. h1,  
  5. h2,  
  6. h3,  
  7. h4,  
  8. h5,  
  9. h6,  
  10. p,  
  11. th,  
  12. td,  
  13. dl,  
  14. dd,  
  15. form,  
  16. fieldset,  
  17. legend,  
  18. input,  
  19. textarea,  
  20. select,  
  21. figure,  
  22. figcaption {  
  23.   margin: 0;  
  24.   padding: 0;  
  25. li {  
  26.   list-style-type: none;  
  27.  
  28. a {  
  29.   text-decoration: none;  
  30.  
  31. a:hover {  
  32.   text-decoration: underline;  
  33.  
  34. img {  
  35.   border: none;  
  36.  
  37. input {  
  38.   outline: none;  

配置文件

Umi 在 .umirc.ts 或 config/config.ts 中配置項目和插件,支持 es6。

如果項目的配置不復(fù)雜,推薦在 .umirc.ts 中寫配置;如果項目的配置比較復(fù)雜,可以將配置寫在 config/config.ts 中,并把配置的一部分拆分出去,比如路由配置可以拆分成單獨的 routes.ts

推薦兩種配置方式二選一,.umirc.ts 優(yōu)先級更高。

我們采用config的方式,刪除.umirc.ts,根目錄新建config文件夾, 在里面新建config.ts

默認(rèn)內(nèi)容如下 

  1. import { defineConfig } from 'umi';  
  2. export default defineConfig({ 
  3.   nodeModulesTransform: {  
  4.     type: 'none',  
  5.   },  
  6.   routes: [  
  7.     { path: '/', component: '@/pages/index' },  
  8.   ],  
  9.   fastRefresh: {},  
  10. }); 

多環(huán)境多配置文件

可以通過環(huán)境變量 UMI_ENV 區(qū)分不同環(huán)境來指定配置。

為了兼容性,可借助三方工具 cross-env來設(shè)置環(huán)境變量 

  1. yarn add cross-env --dev 

在package.json中的script中   

  1. "start": "cross-env UMI_ENV=dev umi dev",  
  2.    "start:test": "cross-env UMI_ENV=test umi dev",  
  3.    "start:prd": "cross-env UMI_ENV=prd umi dev",  
  4.    "build": "cross-env UMI_ENV=dev umi build",  
  5.    "build:test": "cross-env UMI_ENV=test umi build",  
  6.    "build:prd": "cross-env UMI_ENV=prd umi build", 

然后再config文件夾下 新建

config.dev.ts,config.test.ts,config.prd.ts

代表開發(fā)環(huán)境,測試環(huán)境,生產(chǎn)環(huán)境的配置文件.

config.dev.ts 

  1. import { defineConfig } from 'umi';  
  2. export default defineConfig({ 
  3.   define: {  
  4.     CurrentEnvironment: 'dev',  
  5.   }, 
  6. }); 

config.test.ts 

  1. import { defineConfig } from 'umi';  
  2. export default defineConfig({  
  3.   define: {  
  4.     CurrentEnvironment: 'test',  
  5.   },  
  6. }); 

config.prd.ts 

  1. import { defineConfig } from 'umi';  
  2. export default defineConfig({  
  3.   define: {  
  4.     CurrentEnvironment: 'prd',  
  5.   },  
  6. }); 

CurrentEnvironment 變量代表當(dāng)前的環(huán)境,后面根據(jù)不同的環(huán)境配置不同的請求地址會用到

用于提供給代碼中可用的變量,定義的變量可以全局拿到

這時 執(zhí)行 yarn start:prd,然后去到pages的index.tsx打印CurrentEnvironment.

這時需要去到根目錄的 typings.d.ts 添加 

  1. // 聲明當(dāng)前的環(huán)境  
  2. declare const CurrentEnvironment: 'dev' | 'test' | 'prd';  

然后報錯消失 控制臺打印如下

這時 重新執(zhí)行yanr start:test 控制臺打印如下

環(huán)境變量和多環(huán)境多配置 成功

**注意點**:

config.ts作為配置文件時,記得刪除.umirc.ts 不然config.ts不會生效。

自定義環(huán)境變量

如果我們想自定義一個環(huán)境變量,REACT_APP_ENV. 同樣我們可以在package.json里面設(shè)置

然后我們要這樣拿到這個變量呢?

首先 我們要在config.ts 的 define 配置 

  1. define: {  
  2.     REACT_APP_ENV: process.env.REACT_APP_ENV,  
  3. }, 

然后再在根目錄的 typings.d.ts 定義

  1. declare const REACT_APP_ENV: string; 

這樣就可以以在全局中拿到和使用 REACT_APP_ENV這個環(huán)境變量了.

可以在任意組件 直接打印

  1. console.log('自定義環(huán)境變量', REACT_APP_ENV); 

系統(tǒng)自帶的環(huán)境變量

官方提供的環(huán)境變量

怎么使用?

在根目錄新建.env 環(huán)境變量配置文件

然后寫入 

  1. PORT=3000  // 表示啟動的端口號為3000  
  2. COMPRESS = none  // 不壓縮 CSS 和 JS 

還有一些環(huán)境變量 不能配在 .env 中,只能在命令行里添加

比如 FORK_TS_CHECKER 默認(rèn)不開啟 TypeScript 類型檢查,值為 1 時啟用。 

  1. "start": "cross-env FORK_TS_CHECKER=1 UMI_ENV=dev umi dev", 

請求的封裝

src文件夾下新建 request文件夾 新建request.ts

request.ts 

  1. /**  
  2.  * 網(wǎng)絡(luò)請求工具 封裝umi-request  
  3.  * 更詳細(xì)的 api 文檔: https://github.com/umijs/umi-request  
  4.  */  
  5. import { extend } from 'umi-request';  
  6. import type { RequestOptionsInit } from 'umi-request';  
  7. import { notification } from 'antd';  
  8. // codeMessage僅供參考 具體根據(jù)和后端協(xié)商,在詳細(xì)定義.  
  9. const codeMessage = {  
  10.   200: '服務(wù)器成功返回請求的數(shù)據(jù)。',  
  11.   400: '發(fā)出的請求有錯誤,服務(wù)器沒有進(jìn)行新建或修改數(shù)據(jù)的操作。',  
  12.   500: '服務(wù)器發(fā)生錯誤,請檢查服務(wù)器。',  
  13. };  
  14. type mapCode = 200 | 400 | 500;   
  15. /**  
  16.  * 錯誤異常處理程序  
  17.  */  
  18. const errorHandler = (error: { response: Response }): Response => {  
  19.   const { response } = error;  
  20.   if (response && response.status) {  
  21.     let errorText = codeMessage[response.status as mapCode] || response.statusText;  
  22.     const { status, url } = response;  
  23.     response  
  24.       ?.clone()  
  25.       ?.json()  
  26.       ?.then((res) => {  
  27.         // 后端返回錯誤信息,就用后端傳回的  
  28.         errorText = res.msg ? res.msg : errorText;  
  29.         notification.error({  
  30.           message: `請求錯誤 ${status}: ${url}`,  
  31.           description: errorText,  
  32.         });  
  33.       });  
  34.   } else if (!response) {  
  35.     notification.error({  
  36.       description: '您的網(wǎng)絡(luò)發(fā)生異常,無法連接服務(wù)器', 
  37.       message: '網(wǎng)絡(luò)異常',  
  38.     });  
  39.   }  
  40.   return response;  
  41. };  
  42. /**  
  43.  * 配置request請求時的默認(rèn)參數(shù)  
  44.  */  
  45. const request = extend({  
  46.   errorHandler, // 默認(rèn)錯誤處理  
  47.   credentials: 'include', // 默認(rèn)請求是否帶上cookie  
  48. });  
  49. // 根據(jù)不同的開發(fā)環(huán)境,配置請求前綴  
  50. interface ApiPrefix {  
  51.   dev: string;  
  52.   test: string;  
  53.   prd: string;  
  54.  
  55. const apiPreFix: ApiPrefix = {  
  56.   dev: 'http://120.55.193.14:3030/',  
  57.   test: 'http://120.55.193.14:3030/',  
  58.   prd: 'http://120.55.193.14:3030/',  
  59. };  
  60. // request攔截器, 攜帶token,以及根據(jù)環(huán)境,配置不同的請求前綴  
  61. request.interceptors.request.use((url: string, options: RequestOptionsInit) => {  
  62.   // 不攜帶token的請求數(shù)組  
  63.   let notCarryTokenArr: string[] = [];  
  64.   if (notCarryTokenArr.includes(url)) {  
  65.     return {  
  66.       url: `${apiPreFix[CurrentEnvironment]}${url}`,  
  67.       options,  
  68.     };  
  69.   }  
  70.   // 給每個請求帶上token  
  71.   let token = localStorage.getItem('tokens') || '';  
  72.   let headers = {  
  73.     Authorization: `Bearer ${token}`,  
  74.   };  
  75.   return {  
  76.     url: `${apiPreFix[CurrentEnvironment]}${url}`,  
  77.     options: { ...options, interceptors: true, headers },  
  78.   };  
  79. });  
  80. /**  
  81.  * @url 請求的url  
  82.  * @parameter 上傳的參數(shù)  
  83.  */  
  84. // 封裝的get,post.put,delete請求  
  85. const get = async (url: string, parameter?: Record<string, unknown>): Promise<any> => {  
  86.   try { 
  87.     const res = await request(url, { method: 'get', params: parameter });  
  88.     return res;  
  89.   } catch (error) {  
  90.     console.error(error);  
  91.   }  
  92. };  
  93. const deletes = async (url: string, parameter?: Record<string, unknown>): Promise<any> => {  
  94.   try {  
  95.     const res = await request(url, { method: 'delete', params: parameter });  
  96.     return res;  
  97.   } catch (error) {  
  98.     console.error(error);  
  99.   }  
  100. };  
  101. const post = async (url: string, parameter?: Record<string, unknown>): Promise<any> => {  
  102.   try {  
  103.     const res = await request(url, { method: 'post', data: parameter });  
  104.     return res;  
  105.   } catch (error) {  
  106.     console.error(error);  
  107.   }  
  108. };  
  109. const put = async (url: string, parameter?: Record<string, unknown>): Promise<any> => {  
  110.   try {  
  111.     const res = await request(url, { method: 'put', data: parameter });  
  112.     return res;  
  113.   } catch (error) {  
  114.     console.error(error);  
  115.   }  
  116. };  
  117. export default {  
  118.   get,  
  119.   post,  
  120.   put,  
  121.   deletes,  
  122. }; 

這里封裝了umi-request,統(tǒng)一處理了接口錯誤,請求攔截器攜帶token等.最后在配合useRequest 非常的好用.

umi中使用dva

介紹

包含以下功能,

  •  內(nèi)置 dva,默認(rèn)版本是 ^2.6.0-beta.20,如果項目中有依賴,會優(yōu)先使用項目中依賴的版本。
  •  約定式的 model 組織方式,不用手動注冊 model
  •  文件名即 namespace,model 內(nèi)如果沒有聲明 namespace,會以文件名作為 namespace
  •  內(nèi)置 dva-loading,直接 connect loading 字段使用即可
  •  支持 immer,通過配置 immer 開啟

約定式的 model 組織方式

符合以下規(guī)則的文件會被認(rèn)為是 model 文件,

  •  src/models 下的文件
  •  src/pages 下,子目錄中 models 目錄下的文件
  •  src/pages 下,所有 model.ts 文件(不區(qū)分任何字母大小寫)

實際使用

比如在src下新建 models文件夾,里面新建test.ts

test.ts 

  1. import type { Effect, Reducer, Subscription } from 'umi'; // 映入umi 定義好的ts類型  
  2. import axios from '../request/request'; // 引入封裝好的網(wǎng)絡(luò)請求  
  3. // state 接口  
  4. export interface TextModelState { 
  5.   name?: string;  
  6.   testData?: string;  
  7. // test model接口  
  8. export interface TextModelType {  
  9.   namespace: 'testModel';  
  10.   state: TextModelState;  
  11.   effects: {  
  12.     query: Effect;  
  13.   };  
  14.   reducers: {  
  15.     save: Reducer<TextModelState> 
  16.     msg: Reducer<TextModelState> 
  17.   };  
  18.   subscriptions?: { setup: Subscription };  
  19.  
  20. const IndexModel: TextModelType = {  
  21.   namespace: 'testModel',  
  22.   state: {  
  23.     name: '初始名字',  
  24.     testData: '初始testData',  
  25.   },  
  26.   effects: {  
  27.     *query(action, { call, put }) {  
  28.       const getDataTest = async () => {  
  29.         const data = await axios.get('test'); 
  30.         return data;  
  31.       };  
  32.       let testData = yield call(getDataTest); 
  33.       yield put({  
  34.         type: 'msg',  
  35.         data: { testData: testData?.msg },  
  36.       });  
  37.     },  
  38.   },  
  39.   reducers: {  
  40.     save(state) {  
  41.       return {  
  42.         ...state,  
  43.         name: 'jimmy',  
  44.       };  
  45.     },  
  46.     msg(state, action) {  
  47.       return {  
  48.         ...state,  
  49.         testData: action?.data?.testData,  
  50.         testData2: action?.data?.testData2,  
  51.       };  
  52.     },  
  53.   },  
  54. };  
  55. export default IndexModel; 

在src/pages下的index.tsx中使用

index.tsx 

  1. import type { Effect, Reducer, Subscription } from 'umi'; // 引入umi 定義好的ts類型  
  2. import axios from '../request/request'; // 引入封裝好的網(wǎng)絡(luò)請求  
  3. // state 接口  
  4. export interface TextModelState {  
  5.   name?: string;  
  6.   testData?: string;  
  7.  
  8. // test model接口  
  9. export interface TextModelType {  
  10.   namespace: 'testModel';  
  11.   state: TextModelState;  
  12.   effects: {  
  13.     query: Effect;  
  14.   };  
  15.   reducers: {  
  16.     save: Reducer<TextModelState> 
  17.     msg: Reducer<TextModelState> 
  18.   };  
  19.   subscriptions?: { setup: Subscription };  
  20.  
  21. const IndexModel: TextModelType = {  
  22.   namespace: 'testModel',  
  23.   state: {  
  24.     name: '初始名字',  
  25.     testData: '初始testData',  
  26.   },  
  27.   effects: {  
  28.     *query(action, { call, put }) {  
  29.       const getDataTest = async () => {  
  30.         const data = await axios.get('test');  
  31.         return data;  
  32.       };  
  33.       let testData = yield call(getDataTest); 
  34.       yield put({  
  35.         type: 'msg',  
  36.         data: { testData: testData?.msg },  
  37.       });  
  38.     },  
  39.   },  
  40.   reducers: {  
  41.     save(state) {  
  42.       return {  
  43.         ...state,  
  44.         name: 'jimmy',  
  45.       };  
  46.     },  
  47.     msg(state, action) {  
  48.       return {  
  49.         ...state,  
  50.         testData: action?.data?.testData,  
  51.         testData2: action?.data?.testData2,  
  52.       };  
  53.     },  
  54.   },  
  55. };  
  56. export default IndexModel; 

mfsu

啟用 mfsu 后,熱啟動得到 **10 倍** 提升;熱更新提升 **50%** 以上!

如何啟用

在 config/config.ts 中添加 mfsu:{}

項目源代碼

請點擊我

和兩個小伙伴一起,會根據(jù)實際運(yùn)用中出現(xiàn)的問題或者沒有考慮完善的地方,持續(xù)的更新迭代.如有問題,歡迎提Issue或者在評論區(qū)留言

FAQ

umi 不是內(nèi)部或外部命令

解決辦法

執(zhí)行 yarn global bin 拿到 bin 路徑。然后把這個路徑添加到環(huán)境變量里面的系統(tǒng)變量的path里面

如果還是不行,執(zhí)行 

  1. yarn global add umi 

如遇到更多問題,請查考

官方FAQ

官方倉庫的issue 

 

責(zé)任編輯:龐桂玉 來源: 前端大全
相關(guān)推薦

2022-07-06 07:57:37

Zookeeper分布式服務(wù)框架

2018-11-01 13:20:05

Python爬蟲編程語言

2020-01-13 13:10:29

技術(shù)研發(fā)運(yùn)維

2021-05-11 09:31:31

kustomizeoperator kubernetes

2021-05-08 09:02:48

KubeBuilderOperatork8s

2021-09-18 07:43:33

ApolloJava配置中心

2021-10-14 09:58:24

消息中間件ActiveMQ Java

2021-09-15 19:05:16

數(shù)據(jù)開源項目

2021-07-12 06:11:14

SkyWalking 儀表板UI篇

2022-12-19 08:14:30

注解開發(fā)配置

2022-10-26 07:39:36

MVCC數(shù)據(jù)庫RR

2022-01-02 08:43:46

Python

2022-06-30 22:53:18

數(shù)據(jù)結(jié)構(gòu)算法

2021-08-01 07:19:16

語言OpenrestyNginx

2021-08-11 07:02:21

npm包管理器工具

2022-02-07 11:01:23

ZooKeeper

2021-05-20 06:57:16

RabbitMQ開源消息

2023-04-20 08:00:00

ES搜索引擎MySQL

2021-10-26 10:40:26

代理模式虛擬

2021-12-04 22:05:02

Linux
點贊
收藏

51CTO技術(shù)棧公眾號