Webpack对Tsx和TypeScript的支持及本地服务器

621 阅读7分钟

Webpack对jsx支持

在我们编写react代码时,react使用的语法是jsx, jsx是可以直接使用babel来转换的。

对react jsx代码进行处理需要如”下的插件:

  • @babel/plugin-syntax-jsx
  • @babel/plugin-transform-react-jsx
  • @babel/plugin-transform-react-display-name

但是开发中,我们并不需要一个个去安装这些插件,我们依然可以使用preset来配置:

npm install @babel/preset-react -D

更改一下webpack.config.js

  module: {
    rules: [
      // 针对jsx?代码进行babel处理
      {
        test: /.jsx?$/, // x?:标识0或者1
        use: {
          loader: "babel-loader"
        }
      },
      ]
  }

再去babel.config.js中使用就可以了

  presets: [
    ["@babel/preset-env", {
      // 在开发中针对babel的浏览器兼容查询使用browserslist工具,而不是设置target
      // 因为browserslist工具,可以在多个前端工具之间进行共享浏览器兼容性(postcss/babel)
      // targets: ">0.5%"
      // corejs: 3,
      // false 不使用我们的polyfill进行填充
      // useBuiltIns: "entry"
    }],
    // 对react代码进行处理
    ["@babel/preset-react"]
    ]

Webpack对TypeScript支持

在项目开发中,我们会使用TypeScript来开发,那么TypeScript代码是 需要转换成JavaScript代码。 可以通过TypeScript的compiler来转换成JavaScript:

npm install typescript -D

另外TypeScript的编译配置信息我们通常会编写一个tsconfig.json文件:

tsc --init

生成文件如下

image-20230111231219299

之后我们可以运行npx tsc来编译自己的ts代码

使用ts-loader

如果我们希望在webpack中使用TypeScript,那么我们可以使用ts-loader来处理ts文件:

npm install ts-loader -D

配置ts-loader:

      // 针对ts代码进行处理
      {
        test: /.ts$/,
        use: "ts-loader"
      }

之后,我们通过npm run build打包即可。

使用babel-loader

除了可以使用TypeScript Compiler来编译TypeScript之外,我们也可以使用Babel:

  • Babel是有对TypeScript进行支持;
  • 我们可以使用插件: @babel/tranform-typescript; .
  • 但是更推荐直接使用preset: @babel/preset-typescript;

我们来安装@babel/preset-typescript:

npm install @babel/ preset-typescript -D
  presets: [
    ["@babel/preset-env", {
      // 在开发中针对babel的浏览器兼容查询使用browserslist工具,而不是设置target
      // 因为browserslist工具,可以在多个前端工具之间进行共享浏览器兼容性(postcss/babel)
      // targets: ">0.5%"
      // corejs: 3,
      // false 不使用我们的polyfill进行填充
      // useBuiltIns: "entry"
    }],
    ["@babel/preset-react"],
    // 对ts进行babel处理
    ["@babel/preset-typescript", {      corejs: 3,      useBuiltIns: "usage"    }]
  ]

ts-loader和babel-loader选择

那么我们在开发中应该选择ts-loader还是babel-loader呢?

使用ts-loader (TypeScript Compiler)

  • 来直接编译TypeScript,那么只能将ts转换成js;
  • 如果我们还希望在这个过程中添加对应的polyfill,那么ts-loader是无能为力的; .
  • 我们需要借助于babel来完成polyill的填充功能;

使用babel-loader (Babel)

  • 来直接编译TypeScript,也可以将ts转换成js, 并且可以实现polyill的功能;
  • 但是babel-loader在编译的过程中,不会对类型错误进行检测;

最佳实践

image-20230112002514381

也就是说我们使用Babel来完成代码的转换,使用tsc来进行类型的检查

但是,如何可以使用tsc来进行类型的检查呢?

  • 在这里,我在scripts中添加了两个脚本,用于类型检查;
  • 我们执行npm run type-check可以对ts代码的类型进行检测;
  • 我们执行npm run type-check-watch可以实时的检测类型错误;

image-20230112002928452

就可以检测到类型错误的地方

image-20230112003010053

Webpack本地服务器

本地服务器server

为什么我们需要搭建本地服务器?

目前我们开发的代码,为了运行需要有两个操作:

  • 操作一: npm run build,编译相关的代码;
  • 操作二:通过live server或者直接通过浏览器,打开index.htmI代码, 查看效果;

这个过程经常操作会影响我们的开发效率,我们希望可以做到,当文件发生变化时,可以自动的完成编译和展示; .

为了完成自动编译,webpack提供了几种可选的方式:

  • webpack watch mode
  • webpack-dev-server (常用)
  • webpack-dev-middleware

webpack-dev-server

上面的方式可以监听到文件的变化,但是事实上它本身是没有自动刷新浏览器的功能的:

  • 当然,目前我们可以在VSCode中使用live-server来完成这样的功能;
  • 但是,我们希望在不适用live-server的情况下,可以具备live reloading (实时重新加载)的功能;

安装webpack-dev-server

npm install webpack-dev-server -D

修改配置文件,启动时可以加上参数

  "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "build": "webpack ",
    "serve":"webpack serve",
  },

webpack-dev-server在编译之后不会写入到任何输出文件,而是将bundle文件保留在内存中:

  • 事实上webpack- dev-server使用了-个库叫memfs (memory-fs webpack自己写的)

server的静态资源

devServer的static

devServer中static对于我们直接访问打包后的资源其实并没有太大的作用,它的主要作用是如果我们打包后的资源,又依赖于其他的一些静态资源,那么就需要指定从哪里来查找这个内容:

  • 比如在index.html中,我们需要依赖一-个abc.js文件,这个文件我们存放在public文件中;

  • 在index.htmI中,我们应该如何去引入这个文件呢?

    • 比如代码是这样的: < script src="./public/abc.js"> < /script>;
    • 但是这样打包后浏览器是无法通过相对路径去找到这个文件夹的;
    • 所以代码是这样的: < script src= "/abc.js"> < /script>;
    • 但是我们如何让它去查找到这个文件的存在呢?设置static即可;
  // webpack服务器配置
  devServer: {
    // 静态文件配置 默认为public 可以自定义文件夹
    static: ['public', 'content']
  },

需要使用时就直接./xxx就可以用

 <link rel="icon" href="./icon.png">

server的其他配置

host配置

host设置主机地址:

  • 默认值是localhost;
  • 如果希望其他地方也可以访问,可以设置为0.0.0.0;

localhost和0.0.0.0的区别:

  • localhost:本质上是一个域名,通常情况下会被解析成127.0.0.1;

  • 127.0.0.1:回环地址(Loop Back Address),表达的意思其实是我们主机自己发出去的包,直接被自己接收;

    • 正常的数据库包经常应用层-传输层-网络层-数据链路层-物理层;
    • 而回环地址,是在网络层直接就被获取到了,是不会经常数据链路层和物理层的;
    • 比如我们监听127.0.0.1时,在同一个网段下的主机中,通过ip地址是不能访问的;
  • 0.0.0.0:监听IPV4. 上所有的地址,再根据端口找到不同的应用程序;

    • 比如我们监听0.0.0.0时,在同一一个网段下的主机中,通过ip地址是可以访问的;

port

port设置监听的端口,默认情况下是8080

open

open是否打开浏览器:

  • 默认值是false,设置为true会打开浏览器;
  • 也可以设置为类似于Google Chrome等值;

compress

compress是否为静态文件开启gzip compression:

  • 默认值是false,可以设置为true;

image-20230112011413281

  // webpack服务器配置
  devServer: {
    // 静态文件配置 默认为public
    static: ['public', 'content'],
    // 网关地址
    host: '0.0.0.0',
    // 端口号
    port: 8080,
    // 是否自动打开
    open: true,
    // 是否开启本地服务器代码压缩
    compress: true
  },

server的proxy代理

proxy是我们开发中非常常用的一个配置选项,它的目的设置代理来解决跨域访问的问题:

  • 比如我们的一-个api请求是http://ocalhost:8888,但是本地启动服务器的域名是http://ocalhost:8080,这个时候发送网络请求就会出现跨域的问题;
  • 那么我们可以将请求先发送到-个代理服务器,代理服务器和API服务器没有跨域的问题,就可以解决我们的跨域问题了;

我们可以进行如下的设置:

  • target:表示的是代理到的目标地址,比如/apihy/moment会被代理到htp://localhost:8888/api-hy/moment;
  • pathRewrite:默认情况下,我们的/api-hy也会被写入到URL中,如果希望删除,可以使用pathRewrite;
  • changeOrigin:它表示是否更新代理后请求的headers中host地址;
  // webpack服务器配置
  devServer: {
    // 本地服务代理
    proxy: {
      // 将目标前缀为/api 代理成需要的地址
      '/api': {
        target: "http://localhost:9000",
        // 重写请求地址
        pathRewrite: {
          "^/api": ""
        },
        changeOrigin: true
      }
    }
  },

发送网络请求

// 8.发送网络请求获取数据
import axios from "axios";
​
axios.get('/api/users/list').then(res => {
  console.log(res.data);
})

image-20230112013137501

changeOrigin作用

  • 如果后端没有做校验,无论什么地址都可以拿到数据
  • 如果做好了校验,那么可能只能是同地址才可以拿到数据
  • 所以changeOrigin作用就是修改我们去哪数据时的请求地址,让服务器认为是同地址发送的请求

image-20230112013853479

服务器接收请求图

没有开启changeOrigin

image-20230112014217756

开启changeOrigin

image-20230112014342736

changeOrigin的解析

这个changeOrigin官方说的非常模糊,通过查看源码我发现其实是要修改代理请求中的headers中的host属性:

  • 因为我们真实的请求,其实是需要通过http://localhost:8888来请求的;
  • 但是因为使用了代码,默认情况下它的值时http://localhost:8000;
  • 如果我们需要修改,那么可以将changeOrigin设置为true即可;

image-20230112014603192

historyApiFallback

historyApiFallback是开发中一个非常常见的属性,它主要的作用是解决SPA页面在路由跳转之后,进行页面刷新时,返回404的错误。

boolean值:默认是false

  • 如果设置为true,那么在刷新时,返回404错误时,会自动返回index.html 的内容;

object类型的值,可以配置rewrites属性:

  • 可以配置from来匹配路径,决定要跳转到哪一个页面;

事实上devServer中实现historyApiFallback功能是通过connect-history-api-fallback库的:

  // webpack服务器配置
  devServer: {
    // 刷新路由转跳处理
    historyApiFallback: true
  },