Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境

Posted 凯小默:树上的男爵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境相关的知识,希望对你有一定的参考价值。

项目地址

源码:kaimo-cost-h5

环境准备

兼容性注意:Vite 需要 Node.js 版本 >= 12.0.0。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。

我的 node 版本是 v12.13.0,npm 版本是 6.12.0

1、初始化 Vite + React 项目

直接用官方提供的模板,一键生成项目:项目命名为 kaimo-cost-h5

# npm 6.x
npm init @vitejs/app kaimo-cost-h5 --template react


然后进入项目安装依赖,就可以启动服务了

cd kaimo-cost-h5
npm install
npm run dev

2、添加 react-router-dom 路由

安装依赖

执行下面命令安装依赖

npm i react-router-dom -S

添加页面组件

在项目 src 目录下新增 container 目录用于放置页面组件,再在 container 下新增两个目录分别是 IndexAbout

About/index.jsx 添加如下内容:

import React from 'react'

export default function Index() 
  return <div>
    kaimo 的 about 页面
  </div>

Index/index.jsx 添加如下内容:

import React from 'react'

export default function Index() 
  return <div>
    kaimo 的 index 页面
  </div>

添加路由数组

新建 src/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 里的代码,引入路由配置,实现切换浏览器路径,显示相应的组件:

import React from 'react'
import  BrowserRouter, Routes, Route  from 'react-router-dom'

import routes from '../src/router'

function App() 
  return <BrowserRouter>
    <Routes>
      
        routes.map(route => <Route key=route.path path=route.path element=<route.component />></Route>)
      
    </Routes>
  </BrowserRouter>


export default App

这里记得包裹一层 BrowserRouter,不然会报错 useRoutes() may be used only in the context of a <Router> component.

我们测试一下:

首先我们访问:http://localhost:3000/,没有问题

然后访问:http://localhost:3000/about,也没问题

3、添加 Zarm UI 组件库

安装依赖

npm install zarm -S

使用

Zarm 快速上手

下面我们在 App.jsx 里添加代码:

import React from 'react'
import  BrowserRouter, Routes, Route  from 'react-router-dom'

import  ConfigProvider  from 'zarm';
import zhCN from 'zarm/lib/config-provider/locale/zh_CN';
import 'zarm/dist/zarm.css';

import routes from '../src/router'

function App() 
  return <BrowserRouter>
    <ConfigProvider locale=zhCN>
      <Routes>
        
          routes.map(route => <Route key=route.path path=route.path element=<route.component />></Route>)
        
      </Routes>
    </ConfigProvider>
  </BrowserRouter>


export default App

然后在 /container/Index/index.jsx 里添加按钮 Button 组件:

import React from 'react'

import  Button  from 'zarm';

export default function Index() 
  return <div>
    kaimo 的 index 页面

    <h3>
      按钮 Button 基本用法
    </h3>

    <Button>default</Button>
    <Button theme="primary">primary</Button>
  </div>

按需引入

我们执行 npm run build 打包时,发现 css 文件过于太大,有必要进行按需引入。

我们使用插件vite-plugin-style-import:按需导入组件库样式

注意:这里我们用 1.0.1 的版本,我试了一下 2.0.0 的发现报错。

npm i vite-plugin-style-import@1.0.1 -D

安装好之后,我们修改 vite.config.js

import  defineConfig  from 'vite'
import react from '@vitejs/plugin-react'

import styleImport from 'vite-plugin-style-import'

// https://vitejs.dev/config/
export default defineConfig(
  plugins: [
    react(),
    styleImport(
      libs: [
        
          libraryName: 'zarm',
          esModule: true,
          resolveStyle: (name) => 
            return `zarm/es/$name/style/css`;
          
        
      ]
    )
  ]
)

再修改 App.jsx 里,去掉样式全局引入

import React from 'react'
import  BrowserRouter, Routes, Route  from 'react-router-dom'

import  ConfigProvider  from 'zarm';

import routes from '../src/router'

function App() 
  return <BrowserRouter>
    <ConfigProvider>
      <Routes>
        
          routes.map(route => <Route key=route.path path=route.path element=<route.component />></Route>)
        
      </Routes>
    </ConfigProvider>
  </BrowserRouter>


export default App

然后我们在打包 npm run build,我们发现 css 打包后的体积少了很多。

4、配置 CSS 预处理器 Less

安装依赖

npm i less -D

配置 css 属性

更多请参考:postcss-modules

导出类名的样式,json 中的键。

NameTypeDescription
camelCaseString类名将被骆驼化,原始类名不会从本地中删除
camelCaseOnlyString类名将被驼峰化,原来的类名将从本地中删除
dashesString只有类名中的破折号会被驼峰化
dashesOnlyString类名中的破折号将被驼峰化,原始类名将从本地中删除

vite.config.js 里面添加配置:这里我们用 dashesOnly

import  defineConfig  from 'vite'
import react from '@vitejs/plugin-react'

import styleImport from 'vite-plugin-style-import'

// https://vitejs.dev/config/
export default defineConfig(
  css: 
    // css模块化,文件以.module.[css|less|scss]结尾,否则不生效的
    modules: 
      /**
       * 配置 CSS modules 的行为。选项将被传递给 postcss-modules。
       * 默认:'camelCaseOnly'。
       * 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly'
       * */ 
      localsConvention: 'dashesOnly'
    ,
    // 指定传递给 CSS 预处理器的选项。
    preprocessorOptions: 
      // 预编译支持 less
      less: 
        // 支持内联 javascript
        javascriptEnabled: true,
      
    
  ,
  plugins: [
    react(),
    styleImport(
      libs: [
        
          libraryName: 'zarm',
          esModule: true,
          resolveStyle: (name) => 
            return `zarm/es/$name/style/css`;
          
        
      ]
    )
  ]
)

新建 container/Index/style.module.less 文件,里面添加代码:

.kaimo-index 
  h3 
    color: green;
  

.kaimo_index 
  h3 
    color: red;
  

然后在 container/Index/index.jsx 里面引入使用

import React from 'react'

import  Button  from 'zarm';

import k from './style.module.less'

console.log('style.module.less', k)

export default function Index() 
  return <div className=k.kaimoIndex>
    kaimo 的 index 页面

    <h3>
      按钮 Button 基本用法
    </h3>

    <Button>default</Button>
    <Button theme="primary">primary</Button>
  </div>

我们可以看到在 dashesOnly 下,类名中的破折号被驼峰化了。并且添加了 css modules 配置,自定义样式重名的风险也避免了。

我们可以修改一下在 camelCaseOnly 下,类名中都被驼峰化了。并且被覆盖了,样式变红了。

5、移动端项目适配 rem

安装依赖

  • postcss-pxtorem:它的作用是在你编写完 css 后,将你的单位自动转化为 rem 单位。
  • lib-flexible:可伸缩布局方案。
npm i postcss-pxtorem lib-flexible -s

使用 flexible

main.jsx 中引入它:

import React from 'react'
import ReactDOM from 'react-dom'

import 'lib-flexible/flexible'

import './index.css'
import App from './App'

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

引入之后就会出现下面的 font-size 的设置,页面的大小变化就会让 htmlfont-size 随之变化,从而形成可伸缩布局。

配置 postcss-pxtorem

更多配置参考:postcss-pxtorem

一些默认配置:


    rootValue: 16, //  (Number | Function) 表示根元素字体大小或根据输入参数返回根元素字体大小
    unitPrecision: 5, //  (Number) 允许 REM 单位增长到的十进制数字。
    propList: ['font', 'font-size', 'line-height', 'letter-spacing'], // (Array)可以从 px 更改为 rem 的属性。
    selectorBlackList: [], // (Array)要忽略并保留为 px 的选择器。
	...

根据文档,我们先在根目录新建一个 postcss.config.js 文件,里面添加配置信息:

/**
 * 具体配置可以去 postcss-pxtorem 仓库看看文档
 * 默认配置
    rootValue: 16,
    unitPrecision: 5,
    propList: ['font', 'font-size', 'line-height', 'letter-spacing'],
    selectorBlackList: [],
    replace: true,
    mediaQuery: false,
    minPixelValue: 0,
    exclude: /node_modules/i
 * */ 
module.exports = 
  "plugins": [
    require("postcss-pxtorem")(
      rootValue: 37.5,
      propList: ['*'],
      selectorBlackList: ['norem'] // 过滤掉 .norem 开头的 class,不进行 rem 转换,比如:['body'] will match .body-class
    )
  ]

我们来测试一下:

先修改 container/Index/style.module.less 文件,里面添加代码:

.kaimo-index 
  h3 
    width: 100px;
    background-color: pink;
    color: green;
  
  .norem-kaimo 
    width: 200px;
  

然后修改 container/Index/index.jsx 里面的代码:

import React from 'react'

import  Button  from 'zarm';

import k from './style.module.less'

console.log('style.module.less', k)

export default function Index() 
  return <div className=k.kaimoIndex>
    kaimo 的 index 页面

    <h3>
      按钮 Button 基本用法
    </h3>

    <Button>default</Button>
    <Button theme="primary">primary</Button>

    <h3 className=k.noremKaimo>
      按钮 Button 基本用法 norem
    </h3>
  </div>

重启项目 npm run dev,我们可以发现加了 norem 前缀的类名的 px 不会转化为 rem。

6、resolve.alias 别名设置

打开 vite.config.js,添加配置如下:

import path from "path";

export default defineConfig(
  resolve: 
    alias: 
      '@': path.resolve(__dirname, 'src'), // src 路径
    
  ,

配置好之后,我们就可以使用:

import Index from '@/container/Index'
import About from '@/container/About'

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

export default routes

7、进行 axios 封装配置

安装依赖

npm i axios -S

知识点

环境变量

Vite:环境变量

Vite 在一个特殊的 import.meta.env 对象上暴露环境变量。这里有一些在所有情况下都可以使用的内建变量:

  • import.meta.env.MODE: string 应用运行的模式。
  • import.meta.env.BASE_URL: string 部署应用时的基本 URL。他由 base 配置项决定。
  • import.meta.env.PROD: boolean 应用是否运行在生产环境。
  • import.meta.env.DEV: boolean 应用是否运行在开发环境 (永远与 import.meta.env.PROD 相反)。

X-Requested-With

X-Requested-With 用于区分 ajax 请求还是传统请求。如果 requestedWith 为 null,则为同步请求。如果 requestedWithXMLHttpRequest 则为 Ajax 请求。

XMLHttpRequest.withCredentials

XMLHttpRequest.withCredentials 属性是一个 Boolean 类型,它指示了是否该使用类似 cookies,authorization headers (头部授权)或者 TLS 客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。在同一个站点下使用 withCredentials 属性是无效的。

代理配置

我们启动之前的后端项目 kaimo-cost-server,地址是:http://127.0.0.1:7001

然后我们打开 vite.config.js,添加代理配置,代码如下:

export default defineConfig(
  server: 
    proxy: 
      '/api': 
        // 当遇到 /api 路径时,将其转换成 target 的值
        target: 'http://127.0.0.1:7001',
        changeOrigin: true,
      
    
  ,
)

封装处理

下面我们新建 src/utils/axios.js 文件,里面添加代码:

import axios from "axios";
// 引入 zarm 的 Toast 组件用于提示
import  Toast  from "zarm";

// 设置接口响应时间 30s
axios.defaults.timeout = 3000;
/**
 * @description 添加请求拦截器
 *  1. config中的一些信息不符合服务器的要求,这里可以做一些修改
 *  2. 每次发送网络请求时,都希望在界面中显示一个请求的图标(然后再响应拦截中取消显示)
 *  3. 某些网络请求必须携带一些特殊的信息(如登录token),如果没有携带就可以拦截并作响应提示
*/
axios.interceptors.request.use(config => 
  // 看知识点 XMLHttpRequest.withCredentials
  config.withCredentials = true;
  // 看知识点 X-Requested-With
  config.headers['X-Requested-With'] = 'XMLHttpRequest';
  // Authorization 用于服务端鉴权,token 存于 localStorage
  config.headers['Authorization'] = `$localStorage.getItem('token') || null`;
  console.log('进入请求拦截器-->config:', config);
  return config;
, err => 
  // 请求未成功发出,如:没有网络...
  console.log('进入请求拦截器-->err:', err);
  Toast.show("请求失败");
  return Promise.reject(err);
)

// 添加响应拦截器
axios.interceptors.response.use(response => 
  // 成功响应的拦截
  console.log('进入响应拦截器-->response:', response);
  return Promise.resolve(response.data)
, err =>
  // 失败响应的拦截
  console.log('进入响应拦截器-->err:', err);
  Toast.show("服务器响应失败");
  if(err.response)
    // 失败响应的status需要在response中获得
    console.log(err.response)
    switch(err.response.status)
      // 对得到的状态码的处理,具体的设置视自己的情况而定
      case 401:
        console.log('未登录')
        window.location.href='/login';
        break
      case 404:
        console.log('没有找到该方法');
        break
      case 405:
        console.log('不支持的方法');
        break
      default:
        console.log('其他错误');
        break
    
  
  // 注意这里应该return promise.reject(),
  // 因为如果直接return err则在调用此实例时,响应失败了也会进入then(res=>)而不是reject或catch方法
  return Promise.reject以上是关于Vite 2.x + React + Zarm + Less + React Router v6 + Axios + flexible.js 搭建前端 H5 开发环境的主要内容,如果未能解决你的问题,请参考以下文章

react + zarm + react-captcha-code + classnames 实现登录注册页面

react + zarm 实现账单列表展示页

react + zarm 实现账单列表类型以及时间条件弹窗封装

react + zarm 实现底部导航栏

react + zarm 实现账单详情页以及编辑删除功能

react + zarm + antV F2 实现账单数据统计饼图效果