<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>

          Vite 2.0 + React + Ant Design 4.0 搭建開發(fā)環(huán)境

          共 15750字,需瀏覽 32分鐘

           ·

          2021-03-20 16:24


          關(guān)注公眾號(hào) 前端人,回復(fù)“加群

          添加無(wú)廣告優(yōu)質(zhì)學(xué)習(xí)群

          前言

          最近公司要做一個(gè)小項(xiàng)目,我問老大能不能用 Vue 寫,因?yàn)楣疽恢庇?React, 主要是想嘗試一下 ViteVite 又是祖師爺出的,所以我想試試用 Vue 作為技術(shù)棧。老大問我:“屎吃不吃。” 我隱約覺得老大是在罵祖師爺,但又沒法反駁,于是就嘗試用 Vite + React 的形式整一個(gè)項(xiàng)目架子。

          這里默認(rèn)大家都裝了 Node 環(huán)境了。

          知識(shí)點(diǎn)

          • Vite 初始化 React 項(xiàng)目
          • 引入路由插件 react-router-dom
          • 引入 Ant Design 組件庫(kù)
          • 配置 Ant Design 按需引入
          • 配置 Ant Design 主題色
          • 配置打包時(shí)和運(yùn)行時(shí)的環(huán)境變量 env
          • axios 二次封裝
          • 打包靜態(tài)資源的路徑
          • Vite 的一些配置如開發(fā)端口、 proxy 代理、 alias 別名等

          開動(dòng)

          初始化 Vite + React 項(xiàng)目

          這里不得不感慨,年前還是 Vite 1.x,年后就變成 2.x 了。說(shuō)明兩個(gè)問題,祖師爺對(duì)這個(gè)項(xiàng)目很積極,還有就是不確定因素比較多。但這不妨礙我們?nèi)W(xué)習(xí)它,因?yàn)檎娴挠窒阌挚臁7艂€(gè)官方中文文檔,有興趣的可以看看文檔。

          Vite 官方提供兩種初始化項(xiàng)目的方式,一種是:

          npm init @vitejs/app 

          可以自由選擇配置。還有一種是直接用官方提供的模板,一鍵生成:

          # npm 6.x
          npm init @vitejs/app vite-react-app --template react

          # npm 7+, 需要額外的雙橫線:
          npm init @vitejs/app vite-react-app -- --template react 

          本教程采用第二種形式,生成項(xiàng)目如下:

          按照上述步驟,進(jìn)入 vite-react-app ,安裝完包之后,啟動(dòng)項(xiàng)目:

          image.png

          此時(shí)你已經(jīng)成功搭建出 Vite + React 的開發(fā)環(huán)境。?? ?? ??

          引入路由插件 react-router-dom

          首選安裝 react-router-dom,指令如下:

          npm i react-router-dom -S 

          在項(xiàng)目 src 目錄下新增 container 目錄用于放置頁(yè)面組件,再在 container 下新增兩個(gè)目錄分別是 Index 和 About ,添加如下內(nèi)容:

          // Index/index.jsx
          import React from 'react'

          export default function Index({
            return <div>
              Index
            </div>

          }

          // About/index.jsx
          import React from 'react'

          export default function About({
            return <div>
              About
            </div>


          image.png

          再來(lái)新建 src/router/index.js 配置路由數(shù)組,添加如下內(nèi)容:

          // router/index.js
          import Index from '../container/Index'
          import About from '../container/About'

          const routes = [
            {
              path"/",
              component: Index
            },
            {
              path"/about",
              component: About
            }
          ];

          export default routes 

          App.jsx 引入路由配置,實(shí)現(xiàn)切換瀏覽器路徑,顯示相應(yīng)的組件:

          // App.jsx
          import React, { useState } from 'react'
          import {
            BrowserRouter as Router,
            Switch,
            Route
          from "react-router-dom"
          import routes from '../src/router'
          function App({
            return <Router>
              <Switch>
                {
                  routes.map(route => <Route exact key={route.path} path={route.path}>
                    <route.component />
                  </Route>)
                }
              </Switch>
            </Router>

          }

          export default App 

          啟動(dòng)項(xiàng)目 npm run dev,如下圖所示:

          引入 Ant Design UI 組件庫(kù)

          Ant Design 的官網(wǎng)沒有給出 Vite 的配置方法,這邊是我自己摸索的。首先我們下載安裝包:

          npm i antd @ant-design/icons -S 

          目前最新版本 icon 包是分開的,所以這邊順帶就把 @ant-design/icons 也安裝了。

          安裝成功之后,我們先通過(guò)全局引入的方式,測(cè)試是否能成功跑通。打開 main.jsx 添加樣式:

          ...
          import 'antd/dist/antd.css'
          ... 

          再回到 Index/index.jsx 修改如下:

          import React from 'react'
          import { Button } from 'antd'

          export default function Index({
            return <div>
              <Button type='primary'>Index</Button>
            </div>


          重新啟動(dòng)項(xiàng)目,瀏覽器如下所示,代表引入 Ant Design 成功:

          image.png

          此時(shí)我們可以嘗試著做一些優(yōu)化,我們先看看,就目前現(xiàn)在這個(gè)情況,打完包之后,靜態(tài)資源有多大。運(yùn)行指令 npm run build ,如下所示:

          image.png

          腚眼一看,全局引入樣式的形式,直接打完包, css 靜態(tài)資源就 587.96k 了,我們嘗試 按需加載 樣式。

          首先我們安裝一個(gè)插件:

          npm i vite-plugin-imp -D 

          然后在 vite.config.js 配置文件內(nèi)添加如下內(nèi)容:

          import { defineConfig } from 'vite'
          import reactRefresh from '@vitejs/plugin-react-refresh'
          import vitePluginImp from 'vite-plugin-imp'

          // https://vitejs.dev/config/
          export default defineConfig({
            plugins: [
              reactRefresh(),
              vitePluginImp({
                libList: [
                  {
                    libName"antd",
                    style(name) => `antd/lib/${name}/style/index.less`,
                  },
                ],
              })
            ],
            css: {
              preprocessorOptions: {
                less: {
                  // 支持內(nèi)聯(lián) JavaScript
                  javascriptEnabledtrue,
                }
              }
            },
          }) 

          再安裝 less 插件包, npm i less -D,因?yàn)樯鲜雠渲梦覀兪褂玫氖?less,并且我們需要配置 javascriptEnabled 為 true,支持 less 內(nèi)聯(lián) JS

          這里我們將 main.jsx 的 import 'antd/dist/antd.css' 去掉,再次啟動(dòng) npm run dev,你會(huì)發(fā)現(xiàn)樣式被按需引入了。我們看看插件 vite-plugin-imp 做了什么工作:

          image.png

          嚯喔~,這邊在 index.jsx 內(nèi)單獨(dú)引入了按鈕的樣式組件。我們?cè)倏纯创虬蟮撵o態(tài)資源大小:

          image.png

          css 樣式包直接變成 40.29kb,好香啊~~

          有些同學(xué)可能會(huì)擔(dān)心,在不同的頁(yè)面都引入了 Button 組件,那么樣式會(huì)不會(huì)重復(fù)引入。答案是不會(huì)的,打包構(gòu)建的時(shí)候,會(huì)合并同類項(xiàng),所以最后只會(huì)引入一次 Button 的樣式文件。

          自定義 Ant Design 主題色

          開發(fā)時(shí),會(huì)按照項(xiàng)目的需要,設(shè)計(jì)師的設(shè)計(jì)(瞎畫),來(lái)定制一套主題樣式,包括邊距、文字大小、borderColor等等規(guī)則。可能以前用 webpack 那套的同學(xué)知道怎么玩,但是現(xiàn)在用 Vite,我們需要做如下操作。

          首先打開 vite.config.js,添加如下代碼:

          ...
          import path from 'path'
          import fs from 'fs'
          import lessToJS from 'less-vars-to-js'

          const themeVariables = lessToJS(
            fs.readFileSync(path.resolve(__dirname, './config/variables.less'), 'utf8')
          )

          ...
          css: {
            preprocessorOptions: {
              less: {
                // 支持內(nèi)聯(lián) JavaScript
                javascriptEnabledtrue,
                // 重寫 less 變量,定制樣式
                modifyVars: themeVariables
              }
            }
          }
          ... 

          less-vars-to-js 是將 less 樣式轉(zhuǎn)化為 json 鍵值對(duì)的形式,當(dāng)然你也可以直接在 modifyVars 屬性后寫 json 鍵值對(duì)。

          然后在根目錄新建 config 目錄,添加 variables.less 內(nèi)容如下:

          // 自定義覆蓋 =============================================================
          @primary-color: green; // 全局主色
          // 下面你可以各種寫一些覆蓋的樣式,這里就簡(jiǎn)單覆蓋一個(gè)主題色的樣式,我們改為綠色 

          重新運(yùn)行下面如下所示:

          image.png

          這樣主題色就改造好了。

          環(huán)境變量如何獲取

          我搜了很多資料,但是以目前 Vite 的生態(tài),還是沒能找到我需要的答案,我把最后的希望寄托在 Vite 的倉(cāng)庫(kù) issue,還真搜出了一些東西。這里插一句題外話,有什么問題,先自己解決,去相應(yīng)的倉(cāng)庫(kù)里瞅瞅,有沒有已經(jīng)解決掉的類似問題。不要?jiǎng)硬粍?dòng)就去群里問大佬,大佬不忙啊,免費(fèi)給你解決問題?

          好,我們圓規(guī)正轉(zhuǎn)。咱們平時(shí)開發(fā)項(xiàng)目的時(shí)候,基本上有三個(gè)環(huán)境,開發(fā)環(huán)境、測(cè)試環(huán)境、正式環(huán)境,這三個(gè)環(huán)境需要配置三種不同的資源,如圖片、接口地址、埋點(diǎn)、百度統(tǒng)計(jì)等等。

          打包時(shí) 那么我們?nèi)绾卧诖虬鼤r(shí),在 vite.config.js 中拿到環(huán)境變量呢?首先我們先修改 package.json 的 scripts 屬性,如下所示:

          scripts: {
           "dev""vite --mode development",
            "build:beta""vite build --mode beta",
            "build:release""vite build --mode release",
            "serve""vite preview"

          --mode 后代表的是各個(gè)環(huán)境對(duì)應(yīng)的環(huán)境變量值,這里為什么一定要用 --mode 呢?官方定的,后續(xù)可以在頁(yè)面中拿到這個(gè)變量值。

          我們?cè)?vite.config.js 打印如下所示:

          console.log('process:::env', process.argv) 

          重新運(yùn)行 npm run dev 如下所示:

          image.png

          最后一個(gè)參數(shù),便是我們?cè)O(shè)置好的環(huán)境變量。所以我們可以通過(guò)如下獲取環(huán)境變量:

          const env = process.argv[process.argv.length - 1] 

          我們可以在 vite.config.js 里配置 index.html 內(nèi),靜態(tài)資源的路徑前綴。改動(dòng)如下:

          ...
          const env = process.argv[process.argv.length - 1]
          const base = config[env]
          ...
          export default defineConfig({
           base: base.cdn
          }) 

          在根目錄的 config 目錄內(nèi),添加 index.js 文件,添加如下內(nèi)容:

          export default {
            development: {
              cdn'./',
              apiBaseUrl'/api' // 開發(fā)環(huán)境接口請(qǐng)求,后用于 proxy 代理配置
            },
            beta: {
              cdn'//s.xxx.com/vite-react-app/beta'// 測(cè)試環(huán)境 cdn 路徑
              apiBaseUrl'//www.beta.xxx.com/v1' // 測(cè)試環(huán)境接口地址
            },
            release: {
              cdn'//s.xxx.com/vite-react-app/release'// 正式環(huán)境 cdn 路徑
              apiBaseUrl'//www.xxx.com/v1' // 正式環(huán)境接口地址
            }

          我們來(lái)打個(gè)測(cè)試包試試,運(yùn)行如下指令:

          npm run build:beta 

          結(jié)果如下所示: 同理可得正式環(huán)境的鳥樣。

          運(yùn)行時(shí) 那么運(yùn)行代碼的時(shí)候,我們?nèi)绾潍@取到相應(yīng)的環(huán)境變量呢?答案是 import.meta.env 。我們?cè)?Index/index.jsx 里打印一下便可知曉:

          import React from 'react'
          import { Button } from 'antd'

          export default function Index({
            console.log('import.meta.env'import.meta.env)
            return <div>
              <Button type='primary'>Index</Button>
            </div>


          image.png

          返回了一個(gè)對(duì)象,對(duì)象內(nèi)分別是相應(yīng)的參數(shù),我們這里我們需要的是 MODE 屬性對(duì)應(yīng)的參數(shù),便是我們要的當(dāng)前環(huán)境變量。

          二次封裝 axios

          開發(fā)項(xiàng)目時(shí),服務(wù)端會(huì)為我們提供測(cè)試接口和正式接口,這里我們需要配置相應(yīng)的變量來(lái)動(dòng)態(tài)的獲取請(qǐng)求地址。首先我們先安裝 axios 和 qs :

          npm i axios qs -S 

          然后在 src 目錄下新建 utils 目錄,專門用于存放各種工具方法。在 utils 下新建 index.js,添加如下代碼:

          import axios from 'axios'
          import { message } from 'antd'
          import { stringify } from 'qs'
          import config from '../../config'

          const MODE = import.meta.env.MODE // 環(huán)境變量

          const getRequest = (method) => {
            return (url, data, options = {}) => {
              let base = config[MODE] // 獲取環(huán)境變量相對(duì)應(yīng)的屬性值
              return axios({
                baseURL: base.apiBaseUrl, // 請(qǐng)求域名地址
                method,
                url,
                ...(method === 'POST'
                  ? {
                      data: options.string ? stringify(data) : data,
                    }
                  : {}),
                params: method === 'GET' ? data : options.params,
                headers: {
                  'X-Requested-With''XMLHttpRequest',
                  'Content-Type': options.string
                    ? 'application/x-www-form-urlencoded'
                    : 'application/json',
                  ...options.headers,
                },
                withCredentialstrue,
              })
                .then((res) => {
                  if (typeof res.data !== 'object') {
                    console.error('數(shù)據(jù)格式響應(yīng)錯(cuò)誤:', res.data)
                    message.error('前方擁擠,請(qǐng)刷新再試')
                    return Promise.reject(res)
                  }

                  if (res.data.errcode) {
                    if (res.data.errcode == 401) {
                      window.location.href = 'login' // 登錄失效跳轉(zhuǎn)登錄頁(yè)
                      return
                    }
                    // silent 選項(xiàng),錯(cuò)誤不提示
                    if (res.data.message && !options.silent)
                      message.error(res.data.message)
                    return Promise.reject(res.data)
                  }

                  return res.data
                })
                .catch((err) => {
                  message.error('系統(tǒng)錯(cuò)誤'2)
                  return Promise.reject(err)
                })
            }
          }

          export const get = getRequest('GET')

          export const post = getRequest('POST') 

          這里通過(guò) config[MODE] 獲取開發(fā)、測(cè)試、正式相對(duì)應(yīng)的屬性值,從而拿到 apiBaseUrl 變量值。

          順帶我們把開發(fā)環(huán)境的請(qǐng)求代理也添加一下,我們打開 vite.config.js ,添加如下屬性:

          ...
          export default defineConfig({
           ...
           server: {
              port3001// 開發(fā)環(huán)境啟動(dòng)的端口
              proxy: {
                '/api': {
                  // 當(dāng)遇到 /api 路徑時(shí),將其轉(zhuǎn)換成 target 的值,這里我們?yōu)榱藴y(cè)試,寫了新蜂商城的請(qǐng)求地址
                  target'http://47.99.134.126:28019/api/v1',
                  changeOrigintrue,
                  rewritepath => path.replace(/^\/api/''// 將 /api 重寫為空
                }
              }
            }
          }) 

          測(cè)試接口是否請(qǐng)求成功,我們?cè)?Index/index.jsx 內(nèi)添加如下代碼:

          import React, { useEffect } from 'react'
          import { Button } from 'antd'
          import { get } from '../../utils'

          export default function Index() {
            useEffect(() => {
              get('/index-infos').then(() => {
                
              })
            }, [])
            return <div>
              <Button type='primary'>Index</Button>
            </div>


          重新啟動(dòng)項(xiàng)目,結(jié)果如下圖所示:

          image.png

          resolve.alias 別名設(shè)置

          和大多數(shù)的配置項(xiàng)類似,別名的配置也在 vite.config.js 中,我們打開它,添加如下代碼:

          export default defineConfig({
           ...
            resolve: {
              alias: {
                '~': path.resolve(__dirname, './'), // 根路徑
                '@': path.resolve(__dirname, 'src'// src 路徑
              }
            }
            ...
          }) 

          配置完后,我們重寫上述代碼中的一些路徑如下:

          // router/index.js
          import Index from '@/container/Index'
          import About from '@/container/About'

          // utils/index.js
          import config from '~/config'

          // App.jsx
          import routes from '@/router' 

          方便又簡(jiǎn)介,后續(xù)還能繼續(xù)增加一些路徑,少些幾個(gè)字,提高開發(fā)效率。

          總結(jié)

          這篇文章到此就告一段落了。什么?你還要 TSCSS ModuleEslint,別鬧了,自己去倉(cāng)庫(kù)下載代碼,慢慢玩耍吧,我都寫吐了,求贊啊兄弟萌~~~。破 500 贊,我再碼一篇 Vite + Vue + element-plus 的。溜溜球~~~

          原文地址:juejin.cn/user/4019470243991799


          • 回復(fù)資料包領(lǐng)取我整理的進(jìn)階資料包
          • 回復(fù)加群,加入前端進(jìn)階群
          • console.log("點(diǎn)贊===點(diǎn)看===你我都快樂")
          • Bug離我更遠(yuǎn)了,下班離我更近了


          瀏覽 67
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  国产18在线 | 经典三级久久 | 国产卡一卡二视频 | 欧美亚洲在线观看 | 97人人澡人人妻人人少妇 |