从零开始搭建react+typescript+antd+redux+less+vw自适应项目

简介: 从零开始搭建react+typescript+antd+redux+less+vw自适应项目


步骤1:通过create-react-app脚手架创建项目

npx create-react-app react-template --template typescript

在vscode中打开项目,可以看到顺利生成了react项目且组件的后缀为tsx,此时说明成功创建了react+typescript项目的雏形

在项目根目录下,运行npm run start,成功启动项目

npm run start

步骤2:引入antd

npm install antd -S

安装完成之后,再次运行npm run start启动项目,发现报错了,提示Could not find a declaration file for module 'react'.

这实际上是create-react-app 4.x版本的bug

解决方案如下:

  1. 在项目根目录创建react-app-env.d.ts文件
/// <reference types="react-scripts" />
/// <reference types="node" />
/// <reference types="react" />
/// <reference types="react-dom" />
declare namespace NodeJS {
  interface ProcessEnv {
    readonly NODE_ENV: 'development' | 'production' | 'test';
    readonly PUBLIC_URL: string;
  }
}
declare module '*.bmp' {
  const src: string;
  export default src;
}
declare module '*.gif' {
  const src: string;
  export default src;
}
declare module '*.jpg' {
  const src: string;
  export default src;
}
declare module '*.jpeg' {
  const src: string;
  export default src;
}
declare module '*.png' {
  const src: string;
  export default src;
}
declare module '*.webp' {
    const src: string;
    export default src;
}
declare module '*.svg' {
  import * as React from 'react';
  export const ReactComponent: React.FunctionComponent<React.SVGProps<
    SVGSVGElement
  > & { title?: string }>;
  const src: string;
  export default src;
}
declare module '*.module.css' {
  const classes: { readonly [key: string]: string };
  export default classes;
}
declare module '*.module.scss' {
  const classes: { readonly [key: string]: string };
  export default classes;
}
declare module '*.module.sass' {
  const classes: { readonly [key: string]: string };
  export default classes;
}
// declare module 'react-imageview';
  1. 删除node_modules文件夹,并重新执行npm install
  2. 重新执行npm run start,项目成功运行

接下来我们继续引入antd

在App.tsx中添加import 'antd/dist/antd.css';,同时引入所需要的antd组件,如Button

import React from 'react';
import './App.css';
import 'antd/dist/antd.css';
import { Button } from 'antd';
function App() {
  return (
    <div className="App">
      <Button type="primary">Button</Button>
    </div>
  );
}
export default App;

可以看到效果:

此时antd就引入完成了

步骤3:配置不同环境的打包命令,如测试环境、生产环境

  1. 安装cross-env
npm i cross-env -D
  1. 配置package.json命令
"scripts": {
    "serve": "cross-env REACT_APP_ENV=development node scripts/start.js",
    "build": "cross-env REACT_APP_ENV=production node scripts/build.js",
    "uat": "cross-env REACT_APP_ENV=uat node scripts/build.js",
    "sit": "cross-env REACT_APP_ENV=sit node scripts/build.js"
  },
  1. 创建.env ,.env.development ,.env.production ,.env.uat ,.env.sit,
    .env
REACT_APP_ENV=development
  1. .env.development
REACT_APP_ENV=development
  1. .env.production
REACT_APP_ENV=production
  1. .env.uat
REACT_APP_ENV=uat
  1. .env.sit
REACT_APP_ENV=sit
  1. 项目中获取当前环境变量
console.log(process.env.REACT_APP_ENV)

步骤4:配置路由

  1. 安装react-router-dom@types/react-router-dom
npm i react-router-dom @types/react-router-dom -S
  1. src目录下创建views文件夹,views内创建页面组件,如Index

  2. src目录下创建router文件夹,文件夹下配置各个功能模块的路由,同时创建index.tsx,对各个功能模块的路由做统一的引入和暴露
    功能模块CommonRouter.tsx:
import { lazy } from "react";
const Index = lazy(() => import("../views/Index/Index"));
const CommonRouter: any = [
  {
    path: "/",
    component: Index,
    exact: true,
    title: "首页",
  },
];
export default CommonRouter;

  1. index.tsx引入所有的功能模块路由配置,做统一暴露
import CommonRouter from "./CommonRouter";
const routerConfig: any = [...CommonRouter]
export default routerConfig;
  1. App.tsx中引入Route和自定义的路由配置
import React, { Suspense, Component, Fragment } from "react";
import { Route, Switch, Redirect, withRouter as realWithRouter } from "react-router-dom";
// 这里的是路由配置文件
import routes from "./router/index";
import 'antd/dist/antd.css';
type StateType = {
  [propName: string]: any;
};
type PropType = {
  [propName: string]: any;
};
interface App {
  state: StateType;
  props: PropType;
}
// 获取路由信息
const withRouter: any = realWithRouter;
@withRouter
class App extends Component {
  render() {
    return (
      <Fragment>
        <Suspense fallback={<div></div>}>
          <Switch>
            {routes.length > 0 &&
              routes.map((route: any) => {
                //遍历路由数组
                const { path, component: C, exact } = route;
                return (
                  <Route
                    exact={exact}
                    key={path}
                    path={path}
                    render={(props: any) => {
                      return <C {...props} />;
                    }}
                  />
                );
              })}
            {/* 默认进入/时自动匹配到/ */}
            <Redirect exact from="/" to={"/"} />
            {/* 默认无效路径时自动匹配到首页 */}
            <Redirect to="/" />
          </Switch>
        </Suspense>
      </Fragment>
    );
  }
}
export default App;
  1. 根目录index.tsx中这样定义
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter as Router } from "react-router-dom";
ReactDOM.render(
  <React.StrictMode>
    <Router>
      <App />
    </Router>
  </React.StrictMode>,
  document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

  1. 至此,路由配置就完成了

步骤5:配置less

  1. 暴露配置
npm run eject
  1. 此时项目多出了config文件夹
  2. 安装lessless-loader@5.0.0 (less-loader必须安装指定版本5.0.0)
npm install less less-loader@5.0.0 -S
  1. 仿照sass修改config目录下的webpack.config.js
    ①搜索 cssRegex ,找到后添加两行代码,添加less相关正则
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
  1. ②修改 getStyleLoaders 函数,添加代码
{
  loader: require.resolve('less-loader'),
  options: lessOptions,
},
  1. ③搜索 cssRegex ,在 css 配置下添加 less 配置
// Opt-in support for LESS (using .less extensions).
// By default we support LESS Modules with the
// extensions .module.less
{
  test: lessRegex,
  exclude: lessModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 1,
      sourceMap: isEnvProduction
        ? shouldUseSourceMap
        : isEnvDevelopment,
    },
    'less-loader'
  ),
  // Don't consider CSS imports dead code even if the
  // containing package claims to have no side effects.
  // Remove this when webpack adds a warning or an error for this.
  // See https://github.com/webpack/webpack/issues/6571
  sideEffects: true,
},
// Adds support for CSS Modules, but using LESS
// using the extension .module.less
{
  test: lessModuleRegex,
  use: getStyleLoaders(
    {
      importLoaders: 1,
      sourceMap: isEnvProduction
        ? shouldUseSourceMap
        : isEnvDevelopment,
      modules: {
        getLocalIdent: getCSSModuleLocalIdent,
      },
    },
    'less-loader'
  ),
},
  1. 重新启动项目,创建less文件并引入


    样式生效,说明less配置成功

步骤6:配置sass

通过create-react-app创建的react项目,其实是默认已经配置好sass的,所以我们先尝试在项目中引入sass文件

样式生效,说明sass配置成功

步骤7:配置react-redux

  1. 安装react-redux@types/react-reduxredux-thunk@types/redux-thunk
npm install react-redux @types/react-redux redux-thunk @types/redux-thunk -S
  1. 创建redux核心模块
    如以下示例:
├── src
│   └── redux
│       ├── action
│       │   ├── TestAction.tsx
│       └── asyncAction
│       │   ├── AsyncTestAction.tsx
│       └── reducer
│       │   ├── reducer.tsx
│       │   └── TestReducer.tsx
│       └── store.tsx

  1. reducer~TestReducer.tsx // 创建TestReducer
interface StateType {
  name: string;
  age: number;
}
const commonState: StateType = {
  name: '',
  age: 0,
};
const TestReducer = (state = commonState, action: any): any => {
  switch (action.type) {
    case "CHANGE_NAME":
      return {
        ...state,
        name: action.payload.name,
      };
    case "CHANGE_AGE":
      return {
        ...state,
        age: action.payload.age,
      };
    case "ASYNC_CHANGE_NAME":
      return {
        ...state,
        addressObj: action.payload.name,
      };
    default:
      return state;
  }
};
export default TestReducer;
  1. reducer~reducer.tsx // 创建管理所有reducer的配置
import { combineReducers } from 'redux';
// 引入其他reducer
import TestReducer from './TestReducer';
// 将所有引入的reducer合并成一个reducers,暴露出去
export default combineReducers({
  TestReducer,
});
  1. action~TestAction.tsx // 创建同步更改state的方法
export const changeName = (name: string) => {
  return {
    type: 'CHANGE_NAME',
    payload: {
      name
    }
  }
}
export const changeAge = (age: number) => {
  return {
    type: 'CHANGE_AGE',
    payload: {
      age
    }
  }
}
  1. asyncAction~AsyncTestAction.tsx // 创建异步更改state的方法
export const asyncChangeName = () => {
  return async (dispatch: any) => {
    const countDown: Promise<any> = new Promise((resolve: any, reject: any) => {
      setTimeout(() => {
        resolve({
          name: '模拟网络请求获取到的name'
        })
      }, 1000)
    })
    const data: any = await countDown;
    const params: any = {
      type: 'ASYNC_CHANGE_NAME',
      payload: {
        name: data.name
      }
    };
    dispatch(params);
  }
}
  1. store.tsx // 配置store
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducer/reducer';
export default createStore(reducer, applyMiddleware(thunk));
  1. 入口文件index.tsx配置redux
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from 'react-redux';
import store from './redux/store';
ReactDOM.render(
  <Provider store={store}>
    <React.StrictMode>
      <Router>
        <App />
      </Router>
    </React.StrictMode>
  </Provider>,
  document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
  1. 组件中使用redux,如在App.tsx中使用redux:
import React, { Suspense, Component, Fragment } from "react";
// 这里的是路由配置文件
import { Route, Switch, Redirect, withRouter as realWithRouter } from "react-router-dom";
import routes from "./router/index";
// 公共样式
import 'antd/dist/antd.css';
import './assets/style/public.less';
// redux
import { changeName, changeAge } from "./redux/action/TestAction";
import { asyncChangeName } from "./redux/asyncAction/AsyncTestAction";
import { connect as realConnect } from "react-redux";
type StateType = {
  [propName: string]: any;
};
type PropType = {
  [propName: string]: any;
};
interface App {
  state: StateType;
  props: PropType;
}
// 获取redux
const mapStateToProps = (state: any) => {
  return {
    state,
  };
};
const connect: any = realConnect;
// 获取路由信息
const withRouter: any = realWithRouter;
@withRouter
@connect(mapStateToProps, { changeName, changeAge, asyncChangeName })
class App extends Component {
  componentDidMount() {
    // 调用redux中指定reducer的同步action和异步action方法
    this.props.changeName('张三');
    this.props.changeAge(25);
    this.props.asyncChangeName();
    // 获取redux中指定reducer的state
    console.log(this.props.state.TestReducer);
  }
  render() {
    return (
      <Fragment>
        <Suspense fallback={<div></div>}>
          <Switch>
            {routes.length > 0 &&
              routes.map((route: any) => {
                //遍历路由数组
                const { path, component: C, exact } = route;
                return (
                  <Route
                    exact={exact}
                    key={path}
                    path={path}
                    render={(props: any) => {
                      return <C {...props} />;
                    }}
                  />
                );
              })}
            {/* 默认进入/时自动匹配到/ */}
            <Redirect exact from="/" to={"/"} />
            {/* 默认无效路径时自动匹配到首页 */}
            <Redirect to="/" />
          </Switch>
        </Suspense>
      </Fragment>
    );
  }
}
export default App;

步骤8:自适应

如有配置自适应的需求,可参考这篇文章移动端自适应解决方案vw(以react为例)

至此,react项目创建和配置完成

文章参考

https://www.cnblogs.com/gqx-html/p/13219422.html

目录
相关文章
|
9天前
|
JavaScript 前端开发 IDE
TypeScript在前端项目的渐进式采用策略
该文介绍了渐进式采用TypeScript在前端项目中的策略。首先,通过将JS文件扩展名改为TS并添加类型注解,如在`utils.js`中添加类型。接着,配置`tsconfig.json`,包括目标版本、模块系统、输出目录等。高级配置涉及路径别名、JSON导入、库文件等。然后,集成TypeScript到构建流程,如Webpack,安装`ts-loader`并调整配置。利用类型定义,包括安装第三方库的类型定义包,自定义类型定义或使用社区定义。最后,逐步迁移其他模块至TypeScript,强化类型检查,并确保IDE支持。
9 0
|
12天前
|
监控 JavaScript 前端开发
【JavaScript与TypeScript技术专栏】TypeScript在JavaScript项目中的渐进式采用
【4月更文挑战第30天】TypeScript是JavaScript的超集,引入静态类型、接口等特性,提升代码安全性和可读性。在JavaScript项目中采用TypeScript可享受类型安全、社区支持及优秀工具集成等优势。渐进式采用策略包括评估项目现状、逐步引入新旧模块、编写类型定义文件、配置编译选项和编写测试用例,以提高项目质量和效率。
|
12天前
|
传感器 JavaScript 前端开发
【TypeScript技术专栏】TypeScript在大型项目中的实践与挑战
【4月更文挑战第30天】TypeScript在大型前端项目中日益流行,以其类型系统和ES6+支持提升代码安全与维护性。然而,采用 TypeScript 面临学习曲线、构建时间增加及类型推断挑战。通过最佳实践和成熟工具链(如 tsc、tslint 和 Visual Studio Code)可克服这些问题。案例如Angular、Basecamp和Slack已成功应用TypeScript。掌握TypeScript对提升开发者技能和市场竞争力至关重要。
|
12天前
|
JavaScript 前端开发 开发工具
【TypeScript 技术专栏】使用 TypeScript 重构 JavaScript 项目
【4月更文挑战第30天】TypeScript 在前端开发中日益流行,因其静态类型检查、增强代码可读性和更好的工具支持。本文讨论如何用 TypeScript 重构 JavaScript 项目,包括评估项目、安装 TypeScript 工具、逐步添加类型注解、处理兼容性问题以及解决重构中遇到的问题。重构后,代码质量、团队协作和可维护性均得到提升。通过实例分析,文章为 TypeScript 重构提供指导,助力构建更可靠的前端应用。
|
12天前
|
前端开发
【专栏】在 create-react-app 中集成 less/sass 预处理器和 react-css-modules 的方法
【4月更文挑战第29天】本文介绍了在 create-react-app 中集成 less/sass 预处理器和 react-css-modules 的方法。首先,通过 `npm` 安装 less 或 sass 依赖,然后修改 `config-overrides.js` 配置文件以支持 less/sass 编译。接着,详细阐述如何使用 less/sass 编写样式。再者,安装 react-css-modules 并配置 webpack,使能样式模块化。最后,展示了如何结合使用 less/sass 和 react-css-modules,以提升前端开发的效率和代码质量。
|
12天前
|
前端开发 JavaScript 定位技术
Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档
Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档
33 0
|
12天前
|
JavaScript 前端开发 IDE
TypeScript在大型前端项目中的价值与实践策略
【4月更文挑战第7天】本文探讨了TypeScript在大型前端项目中的价值和实践策略。 TypeScript通过静态类型检查、代码提示、接口与泛型提高代码质量和开发效率。在大型项目中,可采用逐步迁移策略,制定类型规范,利用IDE特性,并维护类型定义文件。通过CI/CD和培训分享,团队能充分发挥TypeScript优势,提升项目可维护性、可扩展性和开发效率。
26 0
|
12天前
|
运维 JavaScript 前端开发
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
|
12天前
|
存储 JSON 前端开发
react保姆级搭建新项目
此文主要以ts+vite+router6+antd 快速搭建一个react项目,适用于初学者,用于学习交流