手动搭webpack + React Hooks + TypeScript + Antd(四)

641 阅读1分钟

前章见

手动搭webpack + React Hooks + TypeScript + Antd(一)
手动搭webpack + React Hooks + TypeScript + Antd(二)
手动搭webpack + React Hooks + TypeScript + Antd(三)

本章继续svg img 等引入

在src中新建assets文件夹

在Home页面中引入一个png,和引入less一样,webpack不能处理png需要加loader处理

安装 url-loader

yarn add url-loader -D

build/webpack.common.js

 module: {
   rules: [  
   ...

+    {
+        test: /\.(png|jpe?g|gif)$/i,
+        use: [
+          {
+            loader: 'url-loader',
+            options: {
+              limit: 8192, // 8k 1024为1kb
+              outputPath: 'images', // 打包到images文件夹下
+            },
+          },
+        ],
+      },

   ...
  ]
}
还是报错

在types里新建img声明文件img-modules.d.ts

types/img-modules.d.ts

declare module '*.png';
declare module '*.jpg';
declare module '*.jpeg';
declare module '*.gif';
declare module '*.svg';
但是页面中还是不能显示图片,编译还报错了

安装 file-loader

yarn add file-loader -D

图片已经正常显示, npm run build试试

跑起来发现引入错误

直接打开background中的链接

发现打包后的css内图片引用不正确

build/webpack.commom.js  修改option

{
    loader: 'url-loader',
    options: {
        limit: 8192, // 8k 1024为1kb
        outputPath: 'images', // 打包到images文件夹下
+       publicPath: '../images'
    },
},
build后最后查看打包文件

页面也正确显示

引入SVG

在assets下新建icons文件夹,放入一些svg文件,页面import一个svg文件

+ import peopleCountSvg from '@assets/icons/people-count.svg';
页面报错

所以还是需要处理svg的loader, 此处选择svg-sprite-loader

安装 svg-sprite-loader

yarn add svg-sprite-loader -D

build/webpack.commom.js

module: {
   rules: [  
   ...

+    {
+        test: /\.svg$/,
+        include: resolve('../src/assets/icons'),
+        use: [
+          {
+            loader: 'svg-sprite-loader',
+          },
+        ],
+    },

   ...
  ]
}
页面引入svg报错

改成,此处id是引入svg的id
<svg>
    {React.createElement('use', { href: id, 'xlink:href': id})}
</svg>
页面成功引入

但是报warning

`xlink:href `改成 `xlinkHref`,然后warning没有了
总结svg引入有两种方式

方式一

<svg>
    {React.createElement('use', { href: id, 'xlink:href': id})}
</svg>
方式二(推荐)
<svg>
    <use xlinkHref={`#${peopleCountSvg.id}`} />
</svg>

但是每次使用svg都需要引入,所以需要将svg Icon抽出做成组件

使用require.context 引入icons文件夹中所有的icon

参考 一张图带你了解webpack的require.context

src/components/Icon.tsx

有两种方法解决此报错

方法一

const request = (require as any)['context']('@assets/icons', false, /\.svg$/);
方法二(推荐)

需要安装@types/webpack-env (推荐,此处安装@types/webpack-env)报错即解决

安装@types/webpack-env

yarn add @types/webpack-env -D

可以打印request 发现是一个webpack上下文环境

点进去看

在文件夹下删除svg 这里面的map数据会实时删除

src/components/Icon.tsx    最终的Icon组件

import React, { CSSProperties } from 'react';

interface IconProps {
  id: string;
  width?: number | string;
  height?: number | string;
  className?: string;
  style?: CSSProperties;
}

// 引入所有的icons
const request = require.context("@assets/icons", true, /\.svg$/);
request.keys().map(request);

export default function Icon(props: IconProps) {
  const { id, ...reset } = props;
  return (
    <svg {...reset}>
      <use xlinkHref={`#${id}`} />
    </svg>
  )
}

引用SVG Icon组件

import Icon from '@components/Icon';
<Icon id={'nav-pay'} className={styles.icon} style={{ width: '15px', height: '15px' }}/>

后文

手动搭webpack + React Hooks + TypeScript + Antd(五)