自己搭建react + antd + less + ts项目


在这里插入图片描述

第一步 通过官方的create-react-app,找个喜欢的目录,执行:

/** 最后面是项目根目录的名称 */
npx create-react-app react-app

第二步 暴露配置的文件,执行:

npm run eject

第三步 支持less

npm install less less-loader --save-dev
或
yarn add less less-loader

但安装完以后发现还是报错 TypeError: this.getOptions is not a function,这是因为less-loader的最新版本,与vue的less-loader配置不兼容

npm uninstall less-loader
npm install less-loader@5.0.0
或
yarn remove  less-loader
yarn add less-loader@5.0.0

找到config/webpack.config.js

    // 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$/;
    ...()
    // Opt-in support for SASS (using .scss or .sass extensions).
    // By default we support SASS Modules with the
    // extensions .module.scss or .module.sass
    {
        test: sassRegex,
        exclude: sassModuleRegex,
        use: getStyleLoaders(
            {
                importLoaders: 3,
                sourceMap: isEnvProduction && shouldUseSourceMap,
            },
            'sass-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 SASS
    // using the extension .module.scss or .module.sass
    {
        test: sassModuleRegex,
        use: getStyleLoaders(
            {
                importLoaders: 3,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: {
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
            },
            'sass-loader'
        ),
    },
    // 以下这里仿照上面sass的代码,配置下less。
 {
              test: lessRegex,
              exclude: lessModuleRegex,
              use: getStyleLoaders({
                importLoaders: 2,
                sourceMap: isEnvProduction && shouldUseSourceMap,
              }, '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 (https://github.com/css-modules/css-modules)
            // using the extension .module.css
            {
              test: lessModuleRegex,
              use: getStyleLoaders({
                importLoaders: 2,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: true,
                getLocalIdent: getCSSModuleLocalIdent,
              },'less-loader'),
            },
            {
              test: lessModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                  modules: {
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
                },
                "less-loader"
              ),
            },

第四步 创建路由

npm install react-router-dom --save
或
yarn add react-router-dom

在app.js使用路由

import React, { Fragment } from "react";
import { HashRouter, Route, Switch, Redirect } from "react-router-dom";
import Login from './pages/Login';
import Home from './pages/Home';
import "./App.less";

function App() {
  return (
    <Fragment>
      <HashRouter>
        <Switch>
          <Route path="/login" component={Login} />
          <Route path="/home" component={Home} />
          <Route exact path="/" component={Home} />
          <Redirect to={"/home"} />
        </Switch>
      </HashRouter>
    </Fragment>
  );
}

export default App;

这里说明一下的属性:

path表示路径,这个很好理解。
component表示绑定的组件。
exact表示是否精确匹配。

第五步 解决跨域问题

npm install http-proxy-middleware --save-dev
或
yarn add http-proxy-middleware

在src下创建setupProxy.js,代码如下:

const proxy = require('http-proxy-middleware');
module.exports = function (app) {
    app.use(
        '^/mock',
        proxy({
            target: 'http://192.168.0.1:3000',
            changeOrigin: true,
            pathRewrite: { '^/mock': '' }
        })
    )
}

这代码的意思就是,只要请求地址是以"/mock"开头,那就反向代理到http://192.168.0.1:3000域名下,跨域问题解决!大家可以根据实际需求进行修改。

第六步 实现mockjs分离式开发

npm install mockjs --save
或
yarn add mockjs 

在src下创建mock文件夹,然后创建mock.js文件

import Mock from "mockjs";

// eslint-disable-next-line
Mock.mock('http://test123.com', {//这里的url地址其实可以换成一个字段,比如msg,下边请求时候对应就可以
  'name': '@cname',
  'age|1-10': 10
})
Mock.mock('http://myname.com','post', {//这里的url地址其实可以换成一个字段,比如msg,下边请求时候对应就可以
  'data|1-2':[{
    'title':'@title',
    'article':'@csentence'
    }]
})

mockjs官网 http://mockjs.com/

在src文件夹中找到index.js引入

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
+ import './mock/mock'

import './index.less';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </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();

mockjs会拦截axios请求,自动返回设置的随机数据

第七步 axios请求后台接口或mock接口

npm install axios --save
或
yarn add axios

在需要的组件中使用

import React, { useEffect } from "react";
import { Button } from "antd";
import PdfView from "../components/pdf-view";
import TestPdf from "../accessts/test.pdf";
import axios from "axios";

function Home(props) {
  useEffect(() => {
   /** mockjs只能拦截axios请求 */
    axios.get("http://test123.com").then((res) => {
      console.log(res);
      /** 结果是随机的,也有可能是其他值 */
    });
  }, []);

  return (
    <div>
      <Button
        type="primary"
        onClick={() => {
          props.history.push("/login");
        }}
      >
        "点击返回登录页"
      </Button>

      <PdfView url={TestPdf} />
    </div>
  );
}

export default Home;

axios官网http://www.axios-js.com/

第八步(可选):配置antd,及其按需加载

npm i antd --save
或
yarn add antd

npm i babel-plugin-import --save-dev
或
yarn add babel-plugin-import

修改package.json文件
将babel部分改为如下代码

"babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      ["import", { "libraryName": "antd", 
      "style": "css" 
      }] 
    ]
  }

修改webpack.config.js文件,找到 if (preProcessor) {}将里面的内容修改如下

if (preProcessor) {

      let preProcessorOptions = {
        sourceMap: true,
      };

      if (preProcessor === "less-loader") {
        preProcessorOptions = {
          sourceMap: true,

          //自定义主题

          modifyVars: {
            "primary-color": "#ff2d52", // 全局主色,
          },

          javascriptEnabled: true,
        };
      }

      loaders.push(
        {
          loader: require.resolve("resolve-url-loader"),

          options: {
            sourceMap: isEnvProduction && shouldUseSourceMap,
          },
        },

        {
          loader: require.resolve(preProcessor),

          options: preProcessorOptions,
        }
      );
    }

更多主题配置请查阅https://ant.design/docs/react/customize-theme-cn

将app.css改为app.less, 并引入antd.less

@import '~antd/dist/antd.less';

.App {
  text-align: center;
}

.App-logo {
  height: 40vmin;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

第九步 将项目改造为typescript

1、全局安装ts

npm i -g typescript

2、创建tsconfig.json

tsc --init

修改tsconfig.json,开启jsx和allowJs配置,

3、安装开发环境依赖

npm install --save-dev typescript @types/react @types/react-dom ts-loader
或
yarn add  typescript @types/react @types/react-dom ts-loader

改造项目,比如登录页面,将登录页面改为login.tsx

import React, { useEffect } from "react";
import { Input } from 'antd';
// import TestHtml from "../accessts/test.html";

const Login: React.FC = () => {
  useEffect(() => { }, []);

  return (
    <div>
      这是登录用的页面
      <Input placeholder="请输入密码" />

      <div id="html-content"></div>
    </div>
  );
};

export default Login;

app.js

import React, { Fragment } from "react";
import { HashRouter, Route, Switch, Redirect } from "react-router-dom";
import Login from './pages/Login.tsx';
import "./App.less";

const App = () => {
  return (
    <Fragment>
      <HashRouter>
        <Switch>
          <Route path="/login" component={Login} />
          <Redirect to={"/login"} />
        </Switch>
      </HashRouter>
    </Fragment>
  );
}

export default App;

可能会提示这样一个错误 除非提供了’–jsx’标志,否则无法使用JSX
解决的办法: 在tsconfig.json文件中compilerOptions中加上 “jsx”: “react”,

{
  "compilerOptions": {
    "jsx": "react",
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Basic Options */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    // "lib": [],                             /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    // "outDir": "./",                        /* Redirect output structure to the directory. */
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
    // "strictNullChecks": true,              /* Enable strict null checks. */
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    // "noUnusedLocals": true,                /* Report errors on unused locals. */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */

    /* Advanced Options */
    "skipLibCheck": true,                     /* Skip type checking of declaration files. */
    "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
  }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可缺不可滥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值