如何创建一个React + ts + less + webpack项目

265 阅读5分钟

写在前面

这是一篇工具类的文档,没有过多的废话,仅仅分享一下如何快速新建一个基础的的React项目,话不多说,直接进入主题

1. 创建react项目

npx create-react-app <object name> --template typescript

2. 安装webpack脚手架

npm install webpack webpack-cli

3. 安装babel

npm install babel-loader @babel/core @babel/preset-env @babel/preset-react

4. 安装 css-loader、less-loader、file-loader、url-loader

npm install css-loader style-loader less-loader file-loader url-loader

5. 安装 html-webpack-plugin

这一步可以忽略(html-webpack-plugin是用于简化 HTML 文件,具体是什么可以自己去查)

npm install html-webpack-plugin

6. 配置webpack.config.js

resolve.alias中的别名配置是个人习惯,代码拷贝后自行修改

// webpack.config.js

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 可选,用于清理构建目录
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  mode: process.env.NODE_ENV || 'development',
  entry: {
    main: resolve(__dirname, 'src', 'index.tsx')
  },
  output: {
    filename: "[name].[contenthash].js",
    path: resolve(__dirname, 'dist')
  },
  resolve: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
    alias: {
      // 添加别名
      images: resolve(__dirname, 'src/assets/images/'),
      '@': resolve(__dirname, 'src/'),
    },
  },
  module: {
    rules: [
      {
        test: /\.tsx?/,
        use: [
          'babel-loader'
        ],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192, // 小于8KB的图片将会被转换为 base64
              name: 'images/[name].[ext]', // 输出文件的路径和名称
            },
          },
        ],
      },
      // 添加用于处理视频文件的加载器规则
      {
        test: /\.(mp4|webm)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: 'videos/[name].[hash:8].[ext]',
            },
          },
        ],
      },
    ]
  },
  plugins: [
    new CleanWebpackPlugin(), // 可选,用于清理构建目录
    // 设置每次构建之前清理 build 文件夹
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: ['build'],
    }),
    new HtmlWebpackPlugin({
      template: resolve(__dirname, 'public', 'index.html'),
      inject: 'body'
    }),
  ],
  devServer: {
    port: 3000,
  }
}

7. 配置 .babelrc

.babelrc 是 Babel 的配置文件,用于指定 Babel 编译器的行为和选项。Babel 是一个 JavaScript 编译器,通常用于将 ECMAScript 2015+ (ES6+) 的代码转换为向后兼容的 JavaScript 版本,以便在当前和旧版的浏览器或环境中运行。

.babelrc 文件允许你配置 Babel 的转换规则、插件和预设(presets)。通过配置 .babelrc,你可以指定:

  1. 转换规则(Transformations) :定义哪些语法或功能应该被转换,例如箭头函数、模板字符串等。
  2. 插件(Plugins) :自定义的转换插件,用于进行更复杂或个性化的转换操作。
  3. 预设(Presets) :一组预先定义好的插件集合,用于简化配置,通常针对特定的转换任务或环境。

以下是我项目中的配置:

// .babelrc

{
  "presets": [
      "@babel/preset-env", // 使用 @babel/preset-env 预设,根据目标环境自动转换 JavaScript 语法和功能
      "@babel/preset-typescript", // 使用 @babel/preset-typescript 预设,用于处理 TypeScript 代码
      [
          "@babel/preset-react", // 使用 @babel/preset-react 预设,用于转换 React JSX 语法
          {
              "runtime": "automatic" // 使用 React 的自动运行时,以便支持 JSX 转换
          }
      ]
  ],
  "plugins": [
      "@babel/plugin-proposal-object-rest-spread", // 使用 @babel/plugin-proposal-object-rest-spread 插件,以支持对象扩展运算符
      "@babel/plugin-proposal-class-properties" // 使用 @babel/plugin-proposal-class-properties 插件,以支持类属性语法
  ],
  "env": {
    "production": { // 配置针对生产环境的特定设置
      "plugins": ["transform-remove-console"] // 在生产环境下使用 transform-remove-console 插件,用于移除控制台输出语句
    }
  }
}

8. 配置.d.ts 文件

.d.ts 文件扩展名表示 TypeScript 的声明文件。它们的作用是为 JavaScript 代码库提供类型信息,使得 TypeScript 编译器能够进行类型检查和提供智能提示。通常用于描述 JavaScript 库的类型信息,特别是在 TypeScript 项目中使用第三方 JavaScript 库时。

// xxx.d.ts

declare module '*.module.less' {
  const classes: { readonly [key: string]: string }
  export default classes
}

declare module '*.png' {
  const value: string;
  export default value;
}

declare module '*.gif' {
  const value: string;
  export default value;
}

declare module '*.mp4' {
  const value: string;
  export default value;
}

declare module '*svg' {
  const value: any;
  export default value;
}

declare module 'echarts/lib/echarts' {
  const echarts: any; // 使用 any 类型来避免类型检查错误
  export = echarts;
}

9. 配置 tsconfig.json

// tsconfig.json

{
  "compilerOptions": {
    "target": "es2015",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "paths": {
      "@/*": ["./src/*"],
      "images/*": ["./src/assets/images/*"]
    }
  },
  "include": [
    "src",
    "custom.d.ts"
  ]
}

10. 在src下新建config.js、config.dev.js、config.pord.js

这里是为了配置不同的环境变量,下文中有修改package.json中的startbuild命令,在webpack打包时,设置不同的NODE_ENV,然后在下面的文件中就可以自动识别当前的环境(最后的request.ts中演示了如何使用环境变量)

// config.js

let env = process.env.NODE_ENV;
env = env || 'development'

const config = {
  development: require('./config.dev'),
  production: require('./config.prod'),
};

module.exports = config[env];
// config.dev.js

module.exports = {
  value: '这是dev环境的变量',
  apiUrl: 'www.dev.com',
};
// config.prod.js

module.exports = {
  value: '这是生产环境的变量',
  apiUrl: 'www.prod.com',
};

11. 修改package.json中的start和build

// package.json

{
  "name": "react_ts",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
      ...
  },
  "scripts": {
    "start": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js",
    "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  ...

12. 安装cross-env

cross-env 是一个用于设置跨平台环境变量并运行命令的 Node.js 包,设置环境变量用的

npm install cross-env

13. 安装babel依赖

这里是我配置好准备启动项目的时候,才发现有俩依赖没装,装一下就好了

npm install @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread

14.最后再封装一个request请求方法吧,顺便演示一下环境变量怎么使用的

// request.ts
const config = require("./config");

export const usePrefix = config.apiUrl

// 封装 GET 请求
export const get = async (url: RequestInfo | URL, token?: string) =>{
  const local_token = window.localStorage.getItem('access_token') || ''
  const useToken = token ? token : local_token
  try {
    const response = await fetch(`${usePrefix}${url}`, {
      method: 'GET',
      headers: {
        Authorization: `Bearer ${useToken}`,
      },
    });
    const data = await response.json();
    const code = response.status
    // 用户信息有误,移除access_token
    if(data === 401){
      window.localStorage.removeItem('access_token')
    }
    return { data, code };
  } catch (error) {
    return error;
  }
}

// 封装 POST 请求
export const post = async (url: RequestInfo | URL, data: any) => {
  const local_token = window.localStorage.getItem('access_token') || ''
  try {
    const response = await fetch(`${usePrefix}${url}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${local_token}`,
      },
      body: JSON.stringify(data),
    });
    const responseData = await response.json();
    const code = response.status
    // 用户信息有误,移除access_token
    if(code === 401){
      window.localStorage.removeItem('access_token')
    }
    return { data: responseData, code };
  } catch (error) {
    return error;
  }
};

文件目录

image.png

关于作者

练习时长两年半的一名前端开发工程师,最近新建项目的次数比较多,第一次写博客,主要为了记录一下学习过程,并且能够提供一个简单的通用模板,有什么好的建议可以向我提出,有什么问题也可以及时反馈