「使用 webpack5从0到1搭建React+TypeScript 项目环境」1. React 与 TypeScript 集成

简介: 「使用 webpack5从0到1搭建React+TypeScript 项目环境」1. React 与 TypeScript 集成

「使用 webpack 5 从0到1搭建React + TypeScript 项目环境」1. React 与 TypeScript 集成

本篇文章会带大家使用 webpack 5集成 ReactTypeScript,同时为了提高我们的代码质量,我们会在构建中添加类型检查和代码规范校验。

创建项目结构

首先我们新建一个项目,结构如下:

b3814a544f111b94986578f4ba3bafa6.png

由于很多配置在「生产环境」「开发环境」中存在不一致的情况,比如开发环境没有必要设置缓存,生产环境还需要设置公共路径等等。所以这里我们分开发环境和生产环境,让打包更灵活。

  • webpack.config.common.js (开发环境和生产环境的共同配置)
  • webpack.config.dev.js(开发环境配置)
  • webpack.config.prod.js (生产环境配置)
  • webpack.config.js (对不同环境下的配置文件进行整合)

初始内容

webpack.config.common.js

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  // webpack 配置
  // 入口起点
  entry: './src/index.tsx',
  // 输出
  output: {
    // 输出文件名
    filename: 'scripts/[name].[contenthash].js',
    // 输出路径
    path: resolve(__dirname, '../dist'),
    clean: true, // 打包前清理 dist 文件夹
  },
  // loader 配置
  module: {
    rules: [
    ]
  },
  resolve: {
    extensions: [ '.tsx', '.ts', '.jsx', '.js'], 
  },
  // plugins 的配置
  plugins: [
    // 功能:默认会创建一个空的html文件,自动引入打包输出的所有资源(js/css)
    new HtmlWebpackPlugin({
      // 增加一个配置
      // 复制 '../index.html' 文件,并自动引入打包输出的所有资源(js/css)
      template: '../index.html',
      // 压缩html资源
      // minify: {
      //   collapseWhitespace: true, //去空格
      //   removeComments: true // 去注释
      // }
    }),
  ],
}

「【注】」 插件html-webpack-plugin 需要我们通过 yarn add html-webpack-plugin -D 下载,详情请看 html-webpack-plugin

webpack.config.dev.js

const Package = require('../package.json')
const proxy = Package.proxy ?? {} // 获取 package.json 中的 代理配置
module.exports = {
  module: {
    rules: [
    ]
  },
  devtool: 'eval-cheap-module-source-map',
  mode: 'development',
  devServer: {
    static: '../dist', // 将 ../dist 目录下的文件作为 web 服务的根目录。
    compress: true,
    port : 3000, // 设置端口号
    open : true, // 自动打开本地默认浏览器
    hot: true, // 开启热更新
    proxy,
    historyApiFallback: true
  }
}
  • 为了我们开发调式,这里设置了devtool: 'eval-cheap-module-source-map',关于 sourcemap的详情请看:一文了解source-map
  • compress 是否选择开启gzips压缩功能,对应静态资源请求的响应头里的  Content-Encoding: gzip
  • historyApiFallback :如果我们的应用是个 SPA (单页面应用),当路由到/some时(可以直接在地址栏里输入),会发现此时刷新页面后,控制台会报错:GET http://localhost:3000/some 404 (Not Found)。此时打network,刷新并查看,就会发现问题所在———浏览器把这个路由当作了静态资源地址去请求,然而我们并没有打包出/some这样的资源,所以这个访问无疑是404的。如何解决它?这种时候,我们可以通过配置来提供页面代替任何404的静态资源响应。详情请看:DevServer | webpack 中文文档 (docschina.org)
  • proxy 开启代理:
  • 我们打包出的 jsbundle 里有时会含有一些对特定接口的网络请求(ajax/fetch).要注意,此时客户端地址是在 http://localhost:3000/ 下,假设我们的接口来自http://localhost:4001/ ,那么毫无疑问,此时控制台里会报错并提示你跨域。如何解决这个问题?在开发环境下,我们可以使用devServer自带的proxy功能:
proxy: { "/api": "http://localhost:4001" }
  • 详情请看:DevServer | webpack 中文文档 (docschina.org)

webpack.config.prod.js

module.exports = {
  output: {
    filename: 'scripts/[name].[contenthash].js'
  },
  module: {
    rules: [
    ]
  },
  plugins: [
  ],
  mode: 'production',
}

webpack.config.js

const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.config.common')
const productionConfig = require('./webpack.config.prod')
const developmentConfig = require('./webpack.config.dev')
module.exports = (env) => {
  switch(true) {
    case env.development:
      return merge(commonConfig, developmentConfig)
    case env.production:
      return merge(commonConfig, productionConfig)
    defult:
      return new Error('No matching configuration was found')
  }
}
  • 我们使用一个名为 webpack-merge 的工具。详情请看:survivejs/webpack-merge: Merge designed for webpack (github.com)
  • webpack 命令行 环境配置 的 --env 参数,可以允许你传入任意数量的环境变量。而在 webpack.config.js中可以访问到这些环境变量。例如, --env production。对于我们的 webpack配置,有一个必须要修改之处。通常, module.exports指向配置对象。要使用 env 变量,你必须将 module.exports转换成一个函数:

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>React App</title>
</head>
<body>
  <div id='root'></div>
</body>
</html>

这个 HTML 文件是Webpack 构建过程中的模板文件。目的是告诉 WebpackReact代码注入到 id="root"div 元素中,并在 HTML 中自动引入打包好的 JavaScriptCSS

npm 脚本

每次打包或启动服务时,都需要在命令行里输入一长串的命令。配置 npm 脚本来简化命令行的输入,这时可以省略 npx

// package.json
{
  ...,
  "scripts": {
    "start": "webpack serve -c ./config/webpack.config.js --env development",
    "build": "webpack -c ./config/webpack.config.js --env production"
  },
}

配置 React 和 TypeScript环境

安装 React 及其对应的类型库:

yarn add react react-dom
yarn add @types/react @types/react-dom -D

src/index.tsx 来编写 React 组件,此代码将会被展示到index.html 文件id="root"div 元素下:

import React from "react";
import ReactDOM from "react-dom";
const App = () => <h1>Hello World!</h1>;
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

「添加 Babel」

在项目中,我们需要使用 BabelReactTypeScript 代码转换为 JavaScript。接下来我们安装一些 Babel 工具

yarn add babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript @babel/plugin-transform-runtime @babel/runtime typescript -D
  • babel-loader通知 BabelReactTypeScript代码转换为 JavaScript
  • @babel/core: Babel 核心库
  • @babel/preset-env:让我们可以在不支持 JavaScript 最新特性的浏览器中使用 ES6+语法
  • @babel/preset-react:将 React代码转换为 JavaScript
  • @babel/preset-typescript:将 TypeScript 代码转换为 JavaScript
  • @babel/plugin-transform-runtime@babel/runtime:支持在低版本浏览器使用 ES6+语法,如 async/await

「Babel 配置」

我们通过.babelrc文件来进行 Babel 配置,在根目录创建此文件并加入以下内容

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

上面的配置是告诉 Babel 使用哪些插件

或者也可以直接写在webpack.config.common.jsrules中:

{
  test: /\.(ts|js)x?$/i,
  exclude: /node_modules/,
  use: {
    loader: "babel-loader",
    options: {
      presets: [
        "@babel/preset-env",
        "@babel/preset-react",
        "@babel/preset-typescript",
      ],
      plugins: [
        [
          "@babel/plugin-transform-runtime",
          {
            regenerator: true,
          },
        ],
      ],
    },
  },
}

相应的我们还需要配置 tsconfig.json

我们可以用ts自带的工具来自动化生成它。

npx tsc --init

我们发现生成了一个tsconfig.json,里面注释掉了绝大多数配置。现在,根据我们想要的效果来打开对应的配置。

{
  "compilerOptions": {
    "target": "es2016",                                
    "jsx": "preserve",                                /* Specify what JSX code is generated. */
    "module": "commonjs",                                /* Specify what module code is generated. */
    "rootDir": "./src/",                                  /* Specify the root folder within your source files. */
    "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
    "outDir": "./dist/",                                   /* Specify an output folder for all emitted files. */
    "removeComments": true,                           /* Disable emitting comments. */
    "esModuleInterop": true,                            
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
    "strict": true,                                      /* Enable all strict type-checking options. */
    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
  }
}

启动开发环境

「安装 webpack

yarn add webpack webpack-cli webpack-dev-server -D

src/index.tsx 中添加:

import React from "react";
import ReactDOM from "react-dom";
const App = () => <h1>Hello World!</h1>;
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

通过yarn start启动开发环境,,然后我们在浏览器中访问http://localhost:3000,可以看到:

99d8d26c071e5a58ad9659452a273a61.png

在 webpack 构建过程中添加类型检查

当我们把 src/index.tsx 修改如下:

import React from "react";
import ReactDOM from "react-dom";
const App = () => {
  console.log(a);
  return (
    <h1>Hello World!</h1>
  )
}
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

我们发现 webpack 还是能正常构建:

2a71fbe86728768ca4ef90d8e3d4e403.png

但是因为我们输出了一个为声明的变量a,所以浏览器的控制台上会报错:

0ff636fd56baab8cfbf313e042493ebc.png

为了开发的时候方便,我们希望在 webpack 构建过程中就能发现错误,我们可以使用fork-ts-checker-webpack-pluginwebpack 构建过程支持类型检查。这意味着 webpack 会通知我们任何类型相关的错误。

首先我们先安装依赖:

yarn add fork-ts-checker-webpack-plugin -D

webpack.config.dev.js中:

引用第三方库:

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

在插件配置中使用该插件:

plugins: [
    ...,
    new ForkTsCheckerWebpackPlugin({
     async: false
 }),
],

我们使用 async 标志来告诉 webpack 等待代码的类型检查结束,然后才提交代码进行编译。

接下来我们重新启动:

可以看到控制台报错:

28ef17b9d70f9d9807ea9d4936249073.png

同时,在浏览器中访问http://localhost:3000,可以看到:

f3a28dd3a528f84466053b051cffcb7e.png

如果想了解更多 fork-ts-checker-webpack-plugin 的相关配置,请看TypeStrong/fork-ts-checker-webpack-plugin:在单独的进程上运行typescript类型检查器的Webpack插件。(github.com)

在 webpack 构建过程中添加代码规范校验

webpack构建流程不会执行代码规范校验。我们可以使用ESLintPlugin来使 webpack构建过程能够使用 ESLint 进行代码规范校验。

下面我们来安装相应的依赖:

yarn add eslint-webpack-plugin eslint -D

配置eslint,只需要在根目录下添加一个.eslintrc文件(或者.eslintrc.json, .js等)。当然,我们可以使用eslint工具来自动生成它:

npx eslint --init

f0103ce313b9aaa8d6032403750c6d34.png

并生成了一个配置文件(.eslintrc.json),这样我们就完成了eslint的基本规则配置。

webpack.config.dev.js中:

引用第三方库:

const ESLintPlugin = require('eslint-webpack-plugin');

在插件配置中使用该插件:

plugins: [
    ...,
    new ESLintPlugin({
      extensions: ["js", "jsx", "ts", "tsx"],
    }),
],

src/index.tsx 中,添加一个未使用的变量:

import React from "react";
import ReactDOM from "react-dom";
const App = () => {
  const a = '';
  // console.log(a);
  return (
    <h1>Hello World!</h1>
  )
}
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

输入 yarn start 构建,可以看到警告:

e52432091f0000c037ccc2e14d657a99.png

启动生存环境打包

输入 yarn build 可以进行生产环境打包,我们可以看到输出了一个 dist 文件夹:

52dc6c81ba1d7360cd615fc4f2094088.png

最后

至此我们已经集成了 ReactTypeScript,下一篇文章是 「「使用 webpack 5 从0到1搭建React + TypeScript 项目环境」2. 集成 css、less 与 sass」

相关文章
|
6天前
|
设计模式 监控 JavaScript
TypeScript 在大型项目内网管理监控软件中的结构优化
本文探讨了 TypeScript 在大型项目内网管理监控软件中的结构优化,包括模块划分与组织、接口与抽象类的使用以及依赖注入与控制反转的设计模式,通过具体代码示例展示了这些技术的应用,提高了代码的可读性、可维护性和灵活性。
20 3
|
4天前
|
前端开发 JavaScript
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
|
11天前
|
JavaScript 前端开发 测试技术
JavaScript与TypeScript:为何TypeScript成为大型项目的首选
JavaScript与TypeScript:为何TypeScript成为大型项目的首选
19 1
|
2月前
|
前端开发 JavaScript 开发者
Express.js与前端框架的集成:React、Vue和Angular的示例与技巧
本文介绍了如何将简洁灵活的Node.js后端框架Express.js与三大流行前端框架——React、Vue及Angular进行集成,以提升开发效率与代码可维护性。文中提供了详细的示例代码和实用技巧,展示了如何利用Express.js处理路由和静态文件服务,同时在React、Vue和Angular中构建用户界面,帮助开发者快速掌握前后端分离的开发方法,实现高效、灵活的Web应用构建。
47 3
|
3月前
|
JavaScript 前端开发 测试技术
TypeScript逆袭!大型项目为何对它情有独钟?揭秘背后的真相!
【8月更文挑战第27天】随着前端领域的快速发展,JavaScript已成为Web开发的核心语言。然而,在处理大型项目时,其弱类型特性导致的维护困难和易错性等问题日益突出。为解决这些问题,TypeScript应运而生,逐渐成为大型项目的首选方案。
36 3
|
3月前
|
JavaScript 网络协议 API
【Azure API 管理】Azure APIM服务集成在内部虚拟网络后,在内部环境中打开APIM门户使用APIs中的TEST功能失败
【Azure API 管理】Azure APIM服务集成在内部虚拟网络后,在内部环境中打开APIM门户使用APIs中的TEST功能失败
|
3月前
|
jenkins Linux 持续交付
在Linux中,如何使用Jenkins和Ansible进行虚拟化环境的自动化和持续集成/持续部署(CI/CD)?
在Linux中,如何使用Jenkins和Ansible进行虚拟化环境的自动化和持续集成/持续部署(CI/CD)?
|
4月前
|
Linux Apache C++
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
该文介绍了如何在Windows环境下为FFmpeg集成SRT协议支持库libsrt。首先,需要安装Perl和Nasm,然后编译OpenSSL。接着,下载libsrt源码并使用CMake配置,生成VS工程并编译生成srt.dll和srt.lib。最后,将编译出的库文件和头文件按照特定目录结构放置,并更新环境变量,重新配置启用libsrt的FFmpeg并进行编译安装。该过程有助于优化直播推流的性能,减少卡顿问题。
102 2
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
|
3月前
|
JavaScript Linux API
【Azure 应用服务】NodeJS Express + MSAL 应用实现AAD集成登录并部署在App Service Linux环境中的实现步骤
【Azure 应用服务】NodeJS Express + MSAL 应用实现AAD集成登录并部署在App Service Linux环境中的实现步骤
|
3月前
|
Kubernetes 监控 Shell
在K8S中,我们公司用户反应pod连接数非常多,希望看一下这些连接都是什么信息?什么状态?怎么排查?容器里面没有集成bash环境、网络工具,怎么处理?
在K8S中,我们公司用户反应pod连接数非常多,希望看一下这些连接都是什么信息?什么状态?怎么排查?容器里面没有集成bash环境、网络工具,怎么处理?