<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          值得收藏的UmiJS 教程

          共 12559字,需瀏覽 26分鐘

           ·

          2021-11-07 11:03

          點擊上方關(guān)注?前端技術(shù)江湖一起學(xué)習(xí),天天進(jìn)步



          前言

          網(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)境中
          • 有很強的 webpack 自定義需求和主觀意愿
          • 需要選擇不同的路由方案

          Umi 可能不適合你。

          為什么不是?

          [1]create-react-app[2]

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

          [3]next.js[4]

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

          umi3項目初始化

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

          首先得有?node[5],并確保 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[6]

          yarn?add?@umijs/fabric?-D
          復(fù)制代碼

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

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

          配置如下

          //.eslintrc.js?配置

          module.exports?=?{
          ??extends:?[require.resolve('@umijs/fabric/dist/eslint')],

          ??//?in?antd-design-pro
          ??globals:?{
          ????ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION:?true,
          ????page:?true,
          ??},

          ??rules:?{
          ????//?your?rules
          ????'prefer-const':?0,
          ??},
          };


          //.prettierrc.js?配置

          const?fabric?=?require('@umijs/fabric')

          module.exports?=?{
          ??...fabric.prettier,
          ??semi:?false,
          }


          //.stylelintrc.js?配置

          const?fabric?=?require('@umijs/fabric')

          module.exports?=?{
          ??...fabric.stylelint,
          }
          復(fù)制代碼

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

          .eslintrc.js
          node_modules
          復(fù)制代碼

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

          1634719305(1).png

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

          驗證

          7d684cab2e5ef8d167c81653582af15.jpg

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

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

          f87c265f5003a8899498b860baa64ce.png

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

          保存時自動格式化代碼

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

          1.png

          我的eslint,或者prettier 不生效?

          222.png

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

          檢查步驟:

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

          pre-commit時的lint-staged 不生效

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

          565.png

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

          yarn?install?--force
          復(fù)制代碼

          執(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)簽都初始化一遍,這樣就大大的加強了網(wǎng)站運行的負(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,代碼如下

          body,
          ol,
          ul,
          h1,
          h2,
          h3,
          h4,
          h5,
          h6,
          p,
          th,
          td,
          dl,
          dd,
          form,
          fieldset,
          legend,
          input,
          textarea,
          select,
          figure,
          figcaption?{
          ??margin:?0;
          ??padding:?0;
          }

          li?{
          ??list-style-type:?none;
          }
          a?{
          ??text-decoration:?none;
          }

          a:hover?{
          ??text-decoration:?underline;
          }
          img?{
          ??border:?none;
          }
          input?{
          ??outline:?none;
          }

          復(fù)制代碼

          配置文件

          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)容如下

          import?{?defineConfig?}?from?'umi';

          export?default?defineConfig({
          ??nodeModulesTransform:?{
          ????type:?'none',
          ??},
          ??routes:?[
          ????{?path:?'/',?component:?'@/pages/index'?},
          ??],
          ??fastRefresh:?{},
          });
          復(fù)制代碼

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

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

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

          yarn?add?cross-env?--dev
          復(fù)制代碼

          在package.json中的script

          ????"start":?"cross-env?UMI_ENV=dev?umi?dev",
          ????"start:test":?"cross-env?UMI_ENV=test?umi?dev",
          ????"start:prd":?"cross-env?UMI_ENV=prd?umi?dev",
          ????"build":?"cross-env?UMI_ENV=dev?umi?build",
          ????"build:test":?"cross-env?UMI_ENV=test?umi?build",
          ????"build:prd":?"cross-env?UMI_ENV=prd?umi?build",
          復(fù)制代碼

          然后再config文件夾下 新建

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

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

          config.dev.ts

          import?{?defineConfig?}?from?'umi';
          export?default?defineConfig({
          ??define:?{
          ????CurrentEnvironment:?'dev',
          ??},
          });

          復(fù)制代碼

          config.test.ts

          import?{?defineConfig?}?from?'umi';
          export?default?defineConfig({
          ??define:?{
          ????CurrentEnvironment:?'test',
          ??},
          });

          復(fù)制代碼

          config.prd.ts

          import?{?defineConfig?}?from?'umi';
          export?default?defineConfig({
          ??define:?{
          ????CurrentEnvironment:?'prd',
          ??},
          });

          復(fù)制代碼

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

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

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

          b49bd8611d5c6403479a1547ba4bbc6.png

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

          //?聲明當(dāng)前的環(huán)境
          declare?const?CurrentEnvironment:?'dev'?|?'test'?|?'prd';
          復(fù)制代碼

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

          1634721237(1).png

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

          11.png

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

          **注意點**:

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

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

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

          1634783299(1).png

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

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

          define:?{
          ????REACT_APP_ENV:?process.env.REACT_APP_ENV,
          },
          復(fù)制代碼

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

          declare?const?REACT_APP_ENV:?string;
          復(fù)制代碼

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

          可以在任意組件 直接打印

          ?console.log('自定義環(huán)境變量',?REACT_APP_ENV);
          復(fù)制代碼

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

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

          怎么使用?

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

          然后寫入

          PORT=3000??//?表示啟動的端口號為3000
          COMPRESS?=?none??//?不壓縮?CSS?和?JS
          復(fù)制代碼

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

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

          "start":?"cross-env?FORK_TS_CHECKER=1?UMI_ENV=dev?umi?dev",
          復(fù)制代碼

          請求的封裝

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

          request.ts

          /**
          ?*?網(wǎng)絡(luò)請求工具?封裝umi-request
          ?*?更詳細(xì)的?api?文檔:?https://github.com/umijs/umi-request
          ?*/


          import?{?extend?}?from?'umi-request';
          import?type?{?RequestOptionsInit?}?from?'umi-request';
          import?{?notification?}?from?'antd';

          //?codeMessage僅供參考?具體根據(jù)和后端協(xié)商,在詳細(xì)定義.
          const?codeMessage?=?{
          ??200:?'服務(wù)器成功返回請求的數(shù)據(jù)。',
          ??400:?'發(fā)出的請求有錯誤,服務(wù)器沒有進(jìn)行新建或修改數(shù)據(jù)的操作。',
          ??500:?'服務(wù)器發(fā)生錯誤,請檢查服務(wù)器。',
          };
          type?mapCode?=?200?|?400?|?500;

          /**
          ?*?錯誤異常處理程序
          ?*/

          const?errorHandler?=?(error:?{?response:?Response?}):?Response?=>?{
          ??const?{?response?}?=?error;
          ??if?(response?&&?response.status)?{
          ????let?errorText?=?codeMessage[response.status?as?mapCode]?||?response.statusText;
          ????const?{?status,?url?}?=?response;
          ????response
          ???????.clone()
          ???????.json()
          ???????.then((res)?=>?{
          ????????//?后端返回錯誤信息,就用后端傳回的
          ????????errorText?=?res.msg???res.msg?:?errorText;
          ????????notification.error({
          ??????????message:?`請求錯誤?${status}:?${url}`,
          ??????????description:?errorText,
          ????????});
          ??????});
          ??}?else?if?(!response)?{
          ????notification.error({
          ??????description:?'您的網(wǎng)絡(luò)發(fā)生異常,無法連接服務(wù)器',
          ??????message:?'網(wǎng)絡(luò)異常',
          ????});
          ??}
          ??return?response;
          };

          /**
          ?*?配置request請求時的默認(rèn)參數(shù)
          ?*/

          const?request?=?extend({
          ??errorHandler,?//?默認(rèn)錯誤處理
          ??credentials:?'include',?//?默認(rèn)請求是否帶上cookie
          });

          //?根據(jù)不同的開發(fā)環(huán)境,配置請求前綴
          interface?ApiPrefix?{
          ??dev:?string;
          ??test:?string;
          ??prd:?string;
          }
          const?apiPreFix:?ApiPrefix?=?{
          ??dev:?'http://120.55.193.14:3030/',
          ??test:?'http://120.55.193.14:3030/',
          ??prd:?'http://120.55.193.14:3030/',
          };
          //?request攔截器,?攜帶token,以及根據(jù)環(huán)境,配置不同的請求前綴
          request.interceptors.request.use((url:?string,?options:?RequestOptionsInit)?=>?{
          ??//?不攜帶token的請求數(shù)組
          ??let?notCarryTokenArr:?string[]?=?[];
          ??if?(notCarryTokenArr.includes(url))?{
          ????return?{
          ??????url:?`${apiPreFix[CurrentEnvironment]}${url}`,
          ??????options,
          ????};
          ??}
          ??//?給每個請求帶上token
          ??let?token?=?localStorage.getItem('tokens')?||?'';
          ??let?headers?=?{
          ????Authorization:?`Bearer?${token}`,
          ??};
          ??return?{
          ????url:?`${apiPreFix[CurrentEnvironment]}${url}`,
          ????options:?{?...options,?interceptors:?true,?headers?},
          ??};
          });

          /**
          ?*?@url?請求的url
          ?*?@parameter?上傳的參數(shù)
          ?*/


          //?封裝的get,post.put,delete請求
          const?get?=?async?(url:?string,?parameter?:?Record):?Promise?=>?{
          ??try?{
          ????const?res?=?await?request(url,?{?method:?'get',?params:?parameter?});
          ????return?res;
          ??}?catch?(error)?{
          ????console.error(error);
          ??}
          };
          const?deletes?=?async?(url:?string,?parameter?:?Record):?Promise?=>?{
          ??try?{
          ????const?res?=?await?request(url,?{?method:?'delete',?params:?parameter?});
          ????return?res;
          ??}?catch?(error)?{
          ????console.error(error);
          ??}
          };
          const?post?=?async?(url:?string,?parameter?:?Record):?Promise?=>?{
          ??try?{
          ????const?res?=?await?request(url,?{?method:?'post',?data:?parameter?});
          ????return?res;
          ??}?catch?(error)?{
          ????console.error(error);
          ??}
          };
          const?put?=?async?(url:?string,?parameter?:?Record):?Promise?=>?{
          ??try?{
          ????const?res?=?await?request(url,?{?method:?'put',?data:?parameter?});
          ????return?res;
          ??}?catch?(error)?{
          ????console.error(error);
          ??}
          };

          export?default?{
          ??get,
          ??post,
          ??put,
          ??deletes,
          };
          復(fù)制代碼

          這里封裝了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

          import?type?{?Effect,?Reducer,?Subscription?}?from?'umi';?//?映入umi?定義好的ts類型
          import?axios?from?'../request/request';?//?引入封裝好的網(wǎng)絡(luò)請求

          //?state?接口
          export?interface?TextModelState?{
          ??name?:?string;
          ??testData?:?string;
          }

          //?test?model接口
          export?interface?TextModelType?{
          ??namespace:?'testModel';
          ??state:?TextModelState;
          ??effects:?{
          ????query:?Effect;
          ??};
          ??reducers:?{
          ????save:?Reducer;
          ????msg:?Reducer;
          ??};
          ??subscriptions?:?{?setup:?Subscription?};
          }

          const?IndexModel:?TextModelType?=?{
          ??namespace:?'testModel',
          ??state:?{
          ????name:?'初始名字',
          ????testData:?'初始testData',
          ??},
          ??effects:?{
          ????*query(action,?{?call,?put?})?{
          ??????const?getDataTest?=?async?()?=>?{
          ????????const?data?=?await?axios.get('test');
          ????????return?data;
          ??????};
          ??????let?testData?=?yield?call(getDataTest);
          ??????yield?put({
          ????????type:?'msg',
          ????????data:?{?testData:?testData?.msg?},
          ??????});
          ????},
          ??},

          ??reducers:?{
          ????save(state)?{
          ??????return?{
          ????????...state,
          ????????name:?'jimmy',
          ??????};
          ????},
          ????msg(state,?action)?{
          ??????return?{
          ????????...state,
          ????????testData:?action?.data?.testData,
          ????????testData2:?action?.data?.testData2,
          ??????};
          ????},
          ??},
          };
          export?default?IndexModel;

          復(fù)制代碼

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

          index.tsx

          import?type?{?Effect,?Reducer,?Subscription?}?from?'umi';?//?引入umi?定義好的ts類型
          import?axios?from?'../request/request';?//?引入封裝好的網(wǎng)絡(luò)請求

          //?state?接口
          export?interface?TextModelState?{
          ??name?:?string;
          ??testData?:?string;
          }

          //?test?model接口
          export?interface?TextModelType?{
          ??namespace:?'testModel';
          ??state:?TextModelState;
          ??effects:?{
          ????query:?Effect;
          ??};
          ??reducers:?{
          ????save:?Reducer;
          ????msg:?Reducer;
          ??};
          ??subscriptions?:?{?setup:?Subscription?};
          }

          const?IndexModel:?TextModelType?=?{
          ??namespace:?'testModel',
          ??state:?{
          ????name:?'初始名字',
          ????testData:?'初始testData',
          ??},
          ??effects:?{
          ????*query(action,?{?call,?put?})?{
          ??????const?getDataTest?=?async?()?=>?{
          ????????const?data?=?await?axios.get('test');
          ????????return?data;
          ??????};
          ??????let?testData?=?yield?call(getDataTest);
          ??????yield?put({
          ????????type:?'msg',
          ????????data:?{?testData:?testData?.msg?},
          ??????});
          ????},
          ??},

          ??reducers:?{
          ????save(state)?{
          ??????return?{
          ????????...state,
          ????????name:?'jimmy',
          ??????};
          ????},
          ????msg(state,?action)?{
          ??????return?{
          ????????...state,
          ????????testData:?action?.data?.testData,
          ????????testData2:?action?.data?.testData2,
          ??????};
          ????},
          ??},
          };
          export?default?IndexModel;
          復(fù)制代碼

          mfsu

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

          如何啟用

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

          項目源代碼

          請點擊我[10]

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

          FAQ

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

          image.png

          解決辦法

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

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

          yarn?global?add?umi
          復(fù)制代碼

          如遇到更多問題,請查考

          官方FAQ[11]

          官方倉庫的issue[12]

          大家還是要把官方文檔看兩遍哦,一些基礎(chǔ),簡單的知識本文章沒有涉及.

          最后

          如果后續(xù)自己還踩了坑,會繼續(xù)更新,如果有什么錯誤或者建議,歡迎評論區(qū)留言,如果覺得文章對你有幫助,就點個贊支持一下唄。


          關(guān)于本文

          作者:Jimmy_kiwi

          https://juejin.cn/post/7021358536504393741

          The End

          歡迎自薦投稿到《前端技術(shù)江湖》,如果你覺得這篇內(nèi)容對你挺有啟發(fā),記得點個?「在看」


          點個『在看』支持下?


          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  可以看的免费黄色电影 | 天天综合色 | 三级视频网站在线观看 | 日韩综合一区 | 日本理论片一道本 |