【voice-ui】完善webpack配置,loader等

40 篇文章 2 订阅
8 篇文章 0 订阅
本文介绍了在React项目中,如何使用webpack配置处理SVG图标,包括安装svg-sprite-loader和解决TS对SVG的支持问题。此外,还详细阐述了创建Icon组件、配置CSS样式(特别是webpack对SCSS的配置)、添加组件事件处理和className属性,以及测试环节中遇到的挑战和解决方案,如使用enzyme进行测试,并处理由于node-sass依赖导致的问题。
摘要由CSDN通过智能技术生成

第一个组件Icon

iconfont下载svg

在阿里的iconfont网站下载想要的图片,目的是通过svg内置于组件,但是,就目前的配置来说,webpack并不支持svg,所以又需要下载新的loader,来处理svg了。

webpack配置svg

配置 loader,使用svg-sprite-loader

            {
                // 处理svg图标
                test: /\.svg$/,
                // 这个loader会把所有svg弄到index.html最上面,root的div之前
                loader:'svg-sprite-loader',
            }

接着引入svg,发现ts报警告,ts不支持svg,所以又得给ts配置一下
在这里插入图片描述

ts配置svg

为了后续的组件类型也得变化,建立一个types文件夹,新建custom.d.ts文件,

// 意思是,声明 所有的svg格式,类型都是any,因为ts就只认识那几种格式的文件
// 给svg文件加了一个默认导出,不然不能用import xx from './xxx.svg'
// 只能import './xxx.svg' ,有当做一个模块xx来使用的目的的时候,就需要有导出,但是svg文件没有,所以需要外部加上
declare module '*.svg' {
    const content: any
    export default content
}

在这里插入图片描述
本来是放在根目录的,但是在配置tsconfig的include的时候,却无法配置成功,不知道为什么include只能识别lib,我家types也没用,在引用的时候还是会报错,所以把types文件夹移入lib文件夹下,就不报错了

以下是tsconfig配置

    // ts-loader会报错,要把include入口处定义一下,咱们要转译的就是lib下的所有ts文件
    // types文件也得加入,因为要引入这下面的比如svg格式进组件,相当于ts也得识别他们
    // 但是加入也没效果,反而是把types放进lib里面就行了
    // 总之,ts涉及到的文件夹都应该放入include
    "include": [
        "lib/**/*",
        // "types/**/*",
    ],

配置Icon组件

要用到svg标签,和use标签

import React from 'react'
import '../icons/wechat.svg'
import '../icons/alipay.svg'
import '../icons/qq.svg'
import '../icons/baidu.svg'
import '../icons/csdn.svg'



// 声明Icon组件接收的类型
interface IconProps {
    name: string;
}

// 最好用箭头函数的形式,方便ts进行声明
const Icon: React.FunctionComponent<IconProps> = (props) => {
    return (
        <span>
            <svg>
                {/* 这里的wechat是icons文件夹下svg文件的文件名 */}
                <use xlinkHref={`#${props.name}`}/>
            </svg>
        </span>
    )
}

export default Icon

这样需要手动添加所有的svg文件,下面配置如何自动添加
新建importIcons.js , 不用ts是这段代码不需要声明,但是ts会多写很多不必要的声明,很麻烦

let importAll = (requireContext) => requireContext.keys().forEach(requireContext )

try{
    importAll(require.context('./icons',true,/\.svg$/))
}catch(error){
    console.log(error);
}

再引入即可

import React from 'react'
import './importIcons'
// import '../icons/wechat.svg'
// import '../icons/alipay.svg'
// import '../icons/qq.svg'
// import '../icons/baidu.svg'
// import '../icons/csdn.svg'


配置css样式

webpack配置scss的loader

配置sass

            {
                // scss的loader,支持scss或sass
                // test:/\.s([ac])ss$/,
                test:/\.s[ac]ss$/,
                // 使用顺序是从右往左,pop出去的,先sass-loader
                use:['style-loader','css-loader','sass-loader']
            }

中途会需要安装node-sass,
但是node-sass一直出错,是真的烦这个,

gyp verb `which` failed     at F (D:\workspace\fun-ui\node_modules\which\which.js:68:19)
gyp verb `which` failed     at E (D:\workspace\fun-ui\node_modules\which\which.js:80:29)
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\which\which.js:89:16   
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\isexe\index.js:42:5    
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\isexe\windows.js:36:5  
gyp verb `which` failed     at FSReqCallback.oncomplete (fs.js:183:21)
gyp verb `which` failed  python2 Error: not found: python2
gyp verb `which` failed     at getNotFoundError (D:\workspace\fun-ui\node_modules\which\which.js:13:12)
gyp verb `which` failed     at F (D:\workspace\fun-ui\node_modules\which\which.js:68:19)
gyp verb `which` failed     at E (D:\workspace\fun-ui\node_modules\which\which.js:80:29)
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\which\which.js:89:16   
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\isexe\index.js:42:5    
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\isexe\windows.js:36:5  
gyp verb `which` failed     at FSReqCallback.oncomplete (fs.js:183:21) {
gyp verb `which` failed   code: 'ENOENT'
gyp verb `which` failed }
gyp verb check python checking for Python executable "python" in the PATH
gyp verb `which` succeeded python C:\Users\AS\AppData\Local\Programs\Python\Python37\python.EXE
gyp ERR! configure error
gyp ERR! stack Error: Command failed: C:\Users\AS\AppData\Local\Programs\Python\Python3gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                                ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:308:12)
gyp ERR! stack     at ChildProcess.emit (events.js:315:20)
gyp ERR! stack  

找遍了终于找到了可以用的办法
首先版本如下,不能下错了,比如node-sass下4.9.4就一直下不下来

"node-sass": "^4.14.1",
"css-loader": "1.0.0",
"sass-loader": "7.1.0",
"style-loader": "0.23.1",

其他三个loader yarn add --dev就行
node-sass要用如下命令参考1 参考2

npm i node-sass@4.14.1 --save-dev --sass_binary_site=https://npm.taobao.org/mirrors/node-sass@4.14.1/

配置组件的点击事件以及className等属性

需要非静态添加所有dom事件,比如onClick,onMouseEnter等
还需要解构props,分离className,name等

import React from 'react'
import './importIcons'
// import '../icons/wechat.svg'
// import '../icons/alipay.svg'
// import '../icons/qq.svg'
// import '../icons/baidu.svg'
// import '../icons/csdn.svg'

import classes from './helper/classes'
import './icon.scss'


// 声明Icon组件接收的类型
// 这个继承的含义是 继承于React内置的SVGAttributes,
// 然后这个SVGAttributes可以有onClick等一系列事件,并且接收一个参数
// 这个参数就是指定什么元素能响应这些事件,所以就不需要单独每个写onClick事件了
interface IconProps extends React.SVGAttributes<SVGElement> {
    // icon的名字
    name: string;
    // onClick是鼠标点击svg标签的事件
    // onClick: React.MouseEventHandler<SVGElement>
    // onClick:(e:React.MouseEvent)=>void
}

// 最好用箭头函数的形式,方便ts进行声明
const Icon: React.FunctionComponent<IconProps> = ({
    className,
    name,
    ...restProps
}) => {

    // 分离出className和其余props,可以直接写到括号里面
    return (
        <svg
            className={classes('fun-ui-icon', className)}
            // {}是表示用js语法
            {...restProps}

        // onClick={props.onClick}
        // onMouseLeave={props.onMouseLeave}
        // onMouseEnter={props.onMouseEnter}
        >
            {/* 这里的wechat是icons文件夹下svg文件的文件名 */}
            <use xlinkHref={`#${name}`} />
        </svg>
    )
}

export default Icon

测试className

需要安装babel-preset-react-app@6.1.0
然后又遇到报错gyp这种,又只能像上面那样用npm taobao来下载安装

gyp verb `which` failed     at F (D:\workspace\fun-ui\node_modules\which\which.js:68:19)
gyp verb `which` failed     at E (D:\workspace\fun-ui\node_modules\which\which.js:80:29)
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\which\which.js:89:16   
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\isexe\index.js:42:5    
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\isexe\windows.js:36:5  
gyp verb `which` failed     at FSReqCallback.oncomplete (fs.js:183:21)
gyp verb `which` failed  python2 Error: not found: python2
gyp verb `which` failed     at getNotFoundError (D:\workspace\fun-ui\node_modules\which\which.js:13:12)
gyp verb `which` failed     at F (D:\workspace\fun-ui\node_modules\which\which.js:68:19)
gyp verb `which` failed     at E (D:\workspace\fun-ui\node_modules\which\which.js:80:29)
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\which\which.js:89:16   
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\isexe\index.js:42:5    
gyp verb `which` failed     at D:\workspace\fun-ui\node_modules\isexe\windows.js:36:5  
gyp verb `which` failed     at FSReqCallback.oncomplete (fs.js:183:21) {
gyp verb `which` failed   code: 'ENOENT'
gyp verb `which` failed }
gyp verb check python checking for Python executable "python" in the PATH
gyp verb `which` succeeded python C:\Users\AS\AppData\Local\Programs\Python\Python37\python.EXE
gyp ERR! configure error
gyp ERR! stack Error: Command failed: C:\Users\AS\AppData\Local\Programs\Python\Python3gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                                ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:308:12)
gyp ERR! stack     at ChildProcess.emit (events.js:315:20)
gyp ERR! stack  

用下面命令,才可以

npm i babel-preset-react-app@6.1.0 --save-dev --sass_binary_site=https://npm.taobao.org/mirrors/babel-preset-react-app/

在这里插入图片描述
测试就能运行了

测试icon

哎哟这个是真的难配置,我吐了
此处只说最后结果,过程不再叙述,太漫长了
我发现测试用的依赖包,都得用npm 改到淘宝的办法下载,yarn根本不行,好像是跟那个node-sass有关的,都要调用本地c++库什么原因,
安装如下依赖,全部使用之前的命令
@wojtekmaj/enzyme-adapter-react-17
enzyme
jsdom
jsdom-global

npm i @wojtekmaj/enzyme-adapter-react-17 --save-dev --sass_binary_site=https://npm.taobao.org/mirrors/@wojtekmaj/enzyme-adapter-react-17/
npm i enzyme --save-dev --sass_binary_site=https://npm.taobao.org/mirrors/enzyme/
npm i jsdom --save-dev --sass_binary_site=https://npm.taobao.org/mirrors/jsdom/
npm i jsdom-global --save-dev --sass_binary_site=https://npm.taobao.org/mirrors/jsdom-global/

然后配置setup.Tests.js
在这里插入图片描述

// react17的配置
// 这个包也行,不过留一个用的多的就行了
// const Adapter = require('enzyme-adapter-react-17-updated')
const enzyme = require('enzyme')
const Adapter = require('@wojtekmaj/enzyme-adapter-react-17')

enzyme.configure({ adapter: new Adapter() });

icon的测试用例里面,头部要加jsdom,给他一个虚拟环境

import 'jsdom-global/register'
import React from 'react'
import renderer from 'react-test-renderer'
import Icon from '../icon'
import {mount} from 'enzyme'


describe('icon', () => {
    it('render successfully', () => {
        const json = renderer.create(<Icon name='alipay' />).toJSON()
        // 期望json符合快照
        expect(json).toMatchSnapshot()
    })
    it('onClick',()=>{
        const fn = jest.fn()
        const component = mount(<Icon name='alipay' onClick={fn}/>)
        component.find('svg').simulate('click')
        // expect(n).toEqual(2)
        expect(fn).toBeCalled()
    })
})

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值