likes
comments
collection
share

使用webpack配置react+ts+eslint项目

作者站长头像
站长
· 阅读数 17

这篇文章是记录自己无聊使用webpack来配置react项目中遇到的问题,以及自己是怎么去解决的。解决办法不一定正确,但确确实实是解决我想要的效果,如果你也遇到类似问题,可以参考参考。

ps:我会把我使用这个配置开发项目遇到的问题写在最后或评论区(持续更新),如果有大佬在评论区指点一二那再好不过了(希望各位大佬不吝赐教哈)。我是萌新,勿嫌弃

项目简单介绍

react18.2.0 + ts4.8.4 + eslint8.26.0(基本上我安装的都是最新版,重要的我就标注下版本)

使用webpack配置react+ts+eslint项目

初始化项目

创建一个空的文件夹 mkdir webpack-react-ts-eslint  cd webpack-react-ts-eslint
然后初始化 npm init -y

新建react相关内容

  1. 安装react18
    yarn add react@18.2.0 react-dom@18.2.0 react-router-dom@6.4.2
    yarn add @types/react@18.0.21 @types/react-dom@18.0.6 @types/react-router-dom@5.3.3
  1. 最外层新建src文件夹(该文件夹中新建App.tsx, index.tsx文件)
App.tsx

import React from 'react';

const App = () => {
  return <div>app</div>
}

export default App

ps: react18更换了下面的渲染方式

index.tsx

import React from 'react'
import { createRoot } from 'react-dom/client';
import App from './App'

const domContainer = document.getElementById('root');
const root = createRoot(domContainer);
root.render(<App />);

  1. 最外层新建public文件夹(index.html)
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>
    555
  </title>
</head>

<body>
  <div id="root"></div>
</body>

</html>

安装ts

我比较喜欢yarn

yarn add typescript@4.8.4 ts-loader --save-dev

在最外层新建一个tsconfig.js文件. ps: 然后先简单的写点配置(后续写项目的添加)

{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true
  }
}

安装eslint

yarn add eslint@8.26.0

然后在最外层新建.eslintrc.json。 因为该配置使用了typescript-eslint @typescript-eslint/parser插件,所以需要下载这个plugin

yarn add @typescript-eslint/eslint-plugin @typescript-eslint/parser
{
    "parser":  "@typescript-eslint/parser",
    "extends": [
        "plugin:react/recommended",
        "plugin:@typescript-eslint/recommended"
    ],                              //使用推荐的React代码检测规范
    "plugins": ["@typescript-eslint"],
    "env":{                         
        "browser": true,
        "node": true
    },
    "settings": {             //自动发现React的版本,从而进行规范react代码
        "react": {
            "pragma": "React",
            "version": "detect"
        }
    }, 
    "parserOptions": {        //指定ESLint可以解析JSX语法
        "ecmaVersion": 2019,
        "sourceType": "module",
        "ecmaFeatures":{
            "jsx":true
        }
    },
    "rules": {
    }
}

ps:前几个只是配置了简单的ts,eslint,react。后续在配置webpack的时候会有报错,我们根据报错来解决问题

安装babel

babel是针对JavaScript的编译器,可以将你写的一些js高级语什么的统一转成浏览器(我们项目跑在浏览器)等可以识别的语法,同时也可以解析jsx语法

yarn add babel-loader babel-plugin-import @babel/cli @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript --dev

在项目最外层新建.babelrc文件

    "presets": [
      "@babel/preset-env",
      "@babel/preset-react"
    ],
    "plugins": [
      [
        "@babel/plugin-transform-runtime",
        {
          "regenerator": true
        }
      ]
    ]
}

新建生产和开发环境配置文件

由于webpack只有处理js类的文件,所以我们需要下载plugin/loader来处理其他格式的文件

下载这几个配置(plugin) // webpack的包

yarn add webpack webpack-cli 

// 因为我们分开发环境和生产环境,且两个环境都差不多,可以在创建一个base文件,然后使用webpack-merge合起来

yarn add webpack-merge  

// 安装这个插件,是webpack构建完成之后生成html文件,同时构建好入js引入到生成的html文件中

yarn add html-webpack-plugin

// 安装clean-webpack-plugin 每次运行的时候删除已经打包好的资源,来减少磁盘空间的占用

yarn add clean-webpack-plugin

// 安装mini-css-extract-plugin 这个就是把css文件单独放在一个文件夹中

yarn add mini-css-extract-plugin

// 由于我们使用了eslint,所以还需要下载一个eslint-webpack-plugin,webpack5使用plugin,之前好像是使用eslint-loader。我们紧跟潮流,用plugin...

yarn add eslint-webpack-plugin

下载这几个loader

yarn add style-loader 把css插入到dom中(比如插入<style>标签,并将css写入到这个标签内)
yarn add css-loader 处理css文件
yarn add postcss-loader@5 postcss@7.0.1 autoprefixer postcss-preset-env 处理样式兼容性问题
yarn add less less-loader  // react我使用less

现在可以写webpack配置了

使用webpack配置react+ts+eslint项目

在最外层新建config文件夹,然后里面新建三个文件夹。第一个是基础的,第二个是开发环境,第三个是生产环境。虽然我记不到有哪些该放到生产环境,但是后面肯定会懂的,哈哈!!!

webpack.config.base.js

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 用来在运行时检测格式错误
const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  entry: {
    app: './src/index.tsx',
  },
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].[hash].js',
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx'],
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader', 'postcss-loader']
      },
      {
        test: /\.less$/i,
        use: [
          // compiles Less to CSS
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
      { test: /\.(js|jsx)$/, loader: 'babel-loader', exclude: /node_modules/ },
      { test: /\.(ts|tsx)$/, loader: 'ts-loader', exclude: /node_modules/ },
      {
        test: /\.(jpe?g|png|gif|svg|woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
      },
    ],
  },
  plugins: [
    // 生产html5文件
    new HtmlWebpackPlugin({
      title: '5555',
      template: path.resolve(__dirname, '../public/index.html'),
      filename: 'index.html',
    }),
    new CleanWebpackPlugin(),
    new ESLintPlugin({
      context: 'src/',
      extensions: ['js', 'jsx', 'ts', 'tsx']
    })
  ],
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename]
    },
    name: 'development-cache'
  }
}

webpack.config.dev.js

const webpackMerge = require('webpack-merge');
const baseConfig = require('./webpack.config.base');

const devServer = {
  hot: true,
  port: 5555,
  host: 'localhost',
  compress: true,
  open: false,
}


const devConfig = {
  mode: 'development',
  devServer: devServer
}

module.exports = webpackMerge.merge(baseConfig, devConfig)

webpack.config.prod.js

const webpackMerge = require('webpack-merge')
const baseConfig = require('./webpack.config.base')

const prodConfig = {
    mode: 'production',
}
  
module.exports = webpackMerge.merge(baseConfig, prodConfig)

配置完这些的话,基本上算是配置完最基础的,但是我们如何去启动项目,那就需要配置开发服务器

配置启动服务器

yarn add webpack-dev-server --dev

安装完成之后,一般我们启动项目都是npm run start/yarn start啥的,我们也需要配置一下。 在package.json中添加启动命令

"scripts": {
    "start": "webpack serve --config ./config/webpack.config.dev.js",
    "build": "webpack --mode=production --config ./config/webpack.config.prod.js"
}

如果安装以上步骤来,应该就没啥问题了。

所遇问题

我刚开始配置的时候也是按照其他大佬文章来写的,但是在配置的时候还是遇到了问题的. 文章主要内容算是完成了,但也只是最基础的,还有很多配置并没有加上去。后面我会继续完善,并且使用这个项目开发,如果遇到问题会写在评论里面,或者更新新文章。同时也欢迎各位大佬指点!!! 下一期,更新运行代码时控制台样式更改。 ps: 修改配置之后,大家记得重新跑下项目哦!!!!

使用webpack配置react+ts+eslint项目

评论区添加问题的话比较麻烦,不容易复现,所以我就全部放到问题中来。原意也是为了记录自己使用webpack中遇到的问题。

1. 原本我在文章中使用了mini-css-extract-plugin,但是我把它放到了webpack.config.base.js中,导致开发环境,改变xxx.css文件的样式时,页面样式不会重新刷新。所以这个还是得放到生产环境,哈哈,终于区分了一个生产和开发的条件。

如果你想在生产环境使用,那么进行下面操作

yarn add mini-css-extract-plugin

webpack.config.prod.js

const webpackMerge = require('webpack-merge')
const baseConfig = require('./webpack.config.base')
// 把css单独放到一个文件中
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const modules = {
    rules: [
        {
            test: /\.css$/i,
            use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']
        },
    ]
}

const plugins = [
    
    new MiniCssExtractPlugin({
        filename: 'css/[name].[hash].css',
    })
]
const prodConfig = {
    mode: 'production',
    module: modules,
    plugins: plugins
}
  
module.exports = webpackMerge.merge(baseConfig, prodConfig)

2. any报错

使用webpack配置react+ts+eslint项目 如果是报这个错,可以在.eslintrc.json文件夹中添加这个规则 "@typescript-eslint/no-explicit-any": ["off"]

3. 有时候项目经常使用‘@’来代替src文件夹,这到底是方便的使用webpack配置react+ts+eslint项目

如果需要配置的话,需要在webpack.config.base.js

resolve: {
    alias: {
      '@': path.resolve(__dirname, '../src')
    }
  }

在文件最外层新建tsconfig.extends.json,在该文件中

{
    "compilerOptions": {
        "baseUrl": "./",
        "paths": {
            "@/*": [
                "./src/*"
            ]
        }
    }
}

然后在tsconfig.json

"extends": "./tsconfig.extends.json"

4. 添加eslint,ts忽略文件以及最好git init下

最好还是添加下忽略文件,因为有些地方不需要去使用规则,并且还会影响编译速度

使用webpack配置react+ts+eslint项目 在最外层新建一个.eslintignore文件,然后,当然你也可以添加其他的忽略内容

node_modules/
dist/
\.eslintrc
config/

当然,我自己喜欢git init一下,然后每配置一个新的功能可以提交下代码,不至于某个步骤出错,搞得浪费很多时间,直接版本回退下就好。

5. 没有热更新,不知道大家发现没有

每次修改代码之后保存代码,页面都会重新刷新,并没有热更新。以前接触的项目很奇怪都没有热更新,所以用热更新反而很奇怪,在使用热更新项目的时候,甚至会傻愣愣等着页面刷新,以为页面没有更新,哈哈哈!!!不过还是可以配置的。 如果需要配置热更新,先下载这两个包

yarn add -D @pmmmwh/react-refresh-webpack-plugin react-refresh

因为热更新在开发环境起作用就行,所以在webpack.config.dev.js中添加这些配置,就可以体验热更新了,虽然我不喜欢

const ReactRefreshPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const modules = {
  rules: [
    {
      test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: [
          {
            loader: require.resolve('babel-loader'),
            options: {
              plugins: [require.resolve('react-refresh/babel')]
            },
          },
        ],
    }
  ]
}

const plugins = [
  new ReactRefreshPlugin()
]

const devConfig = {
  mode: 'development',
  devServer: devServer,
  plugins: plugins,
  module: modules
}

6.DevTools failed to load source map: Could not load content for...

这种问题一般就是缺少devtool,也分开发环境和生成环境。我们可以在webpack.config.dev.js(开发环境)中的devConfig中加入devtool: 'source-map'。然后webpack.config.prod.js(生产)中加入devtool: 'cheap-module-source-map'(可以调试,但不暴露源代码)。配置这个功能就是为了方便我们去调试代码,因为打包后的文件都是压缩的,经过处理的,如果直接去处理过的代码中找原来的代码就比较麻烦,加入source-map就可以追踪原来的代码。如图 开发环境

使用webpack配置react+ts+eslint项目 生产环境

使用webpack配置react+ts+eslint项目

配置antd4遇到的问题

因为主要是使用less,所以使用antd的时候也引入less包。但是当在app.less文件夹中按照antd官网引入@import '~antd/dist/antd.less';会报下面的错

使用webpack配置react+ts+eslint项目 这个时候你可以在webpack.config.dev.js中module的rules。因为使用的是webpack5所以以前那种直接在options中加入javascriptEable: true方法失效。

使用webpack配置react+ts+eslint项目