-
-
- );
- }
+const EditForm = ({
+ visible,
+ onCancel,
+ onOk,
+ form,
+ confirmLoading,
+ currentRowData,
+}) => {
+
+ const { id, author, date, readings, star, status, title } = currentRowData;
+ const formItemLayout = {
+ labelCol: {
+ sm: { span: 4 },
+ },
+ wrapperCol: {
+ sm: { span: 16 },
+ },
+ };
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
}
-export default Form.create({ name: "EditForm" })(EditForm);
+export default EditForm;
+
+
+
+
diff --git a/src/views/table/index.jsx b/src/views/table/index.jsx
index 9554fd9..db9e1d9 100644
--- a/src/views/table/index.jsx
+++ b/src/views/table/index.jsx
@@ -1,4 +1,4 @@
-import React, { Component } from "react";
+import React, { useState, useEffect, useRef } from "react";
import {
Table,
Tag,
@@ -11,13 +11,21 @@ import {
message,
Select
} from "antd";
-import { tableList, deleteItem,editItem } from "@/api/table";
+
+import Icon from '@ant-design/icons'
+import * as icons from '@ant-design/icons';
+
+import { tableList, deleteItem, editItem } from "@/api/table";
import EditForm from "./forms/editForm"
const { Column } = Table;
const { Panel } = Collapse;
-class TableComponent extends Component {
- _isMounted = false; // 这个变量是用来标志当前组件是否挂载
- state = {
+const TableComponent = (props) => {
+ const titleInputRef = useRef(null);
+ const statusSelectRef = useRef(null);
+ const starSelectRef = useRef(null);
+
+
+ const [state, setState] = useState({
list: [],
loading: false,
total: 0,
@@ -26,7 +34,7 @@ class TableComponent extends Component {
pageSize: 10,
title: "",
star: "",
- status:""
+ status: ""
},
editModalVisible: false,
editModalLoading: false,
@@ -39,207 +47,228 @@ class TableComponent extends Component {
status: "published",
title: ""
}
- };
- fetchData = () => {
- this.setState({ loading: true });
- tableList(this.state.listQuery).then((response) => {
- this.setState({ loading: false });
+ });
+
+ useEffect(() => {
+ fetchData();
+ }, [state.listQuery, state.editModalVisible]);
+
+ const fetchData = () => {
+ setState({ ...state, loading: true });
+ tableList(state.listQuery).then((response) => {
+
+ setState({ ...state, loading: false });
const list = response.data.data.items;
const total = response.data.data.total;
- if (this._isMounted) {
- this.setState({ list, total });
- }
+
+ const resStr = JSON.stringify(response);
+
+ setState({ ...state, list, total });
});
};
- componentDidMount() {
- this._isMounted = true;
- this.fetchData();
- }
- componentWillUnmount() {
- this._isMounted = false;
- }
- filterTitleChange = (e) => {
+
+ // function stringify(obj) {
+ // let cache = [];
+ // let str = JSON.stringify(obj, function (key, value) {
+ // if (typeof value === "object" && value !== null) {
+ // if (cache.indexOf(value) !== -1) {
+ // // Circular reference found, discard key
+ // return;
+ // }
+ // // Store value in our collection
+ // cache.push(value);
+ // }
+ // return value;
+ // });
+ // cache = null; // reset the cache
+ // return str;
+ // }
+
+
+
+ const filterTitleChange = (e) => {
let value = e.target.value
- this.setState((state) => ({
+ setState({
+ ...state,
listQuery: {
...state.listQuery,
- title:value,
+ pageNumber: 1,
+ title: value,
}
- }));
+ });
};
- filterStatusChange = (value) => {
- this.setState((state) => ({
+ const filterStatusChange = (value) => {
+ setState({
+ ...state,
listQuery: {
...state.listQuery,
- status:value,
+ pageNumber: 1,
+ status: value,
}
- }));
+ });
};
- filterStarChange = (value) => {
- this.setState((state) => ({
+ const filterStarChange = (value) => {
+ setState({
+ ...state,
listQuery: {
...state.listQuery,
- star:value,
+ pageNumber: 1,
+ star: value,
}
- }));
+ });
};
- changePage = (pageNumber, pageSize) => {
- this.setState(
- (state) => ({
- listQuery: {
- ...state.listQuery,
- pageNumber,
- },
- }),
- () => {
- this.fetchData();
- }
- );
+ const changePage = (pageNumber, pageSize) => {
+ setState({
+ ...state,
+ listQuery: {
+ ...state.listQuery,
+ pageNumber,
+ },
+ });
+
+ // fetchData();
};
- changePageSize = (current, pageSize) => {
- this.setState(
- (state) => ({
- listQuery: {
- ...state.listQuery,
- pageNumber: 1,
- pageSize,
- },
- }),
- () => {
- this.fetchData();
- }
- );
+ const changePageSize = (current, pageSize) => {
+ setState({
+ ...state,
+ listQuery: {
+ ...state.listQuery,
+ pageNumber: 1,
+ pageSize,
+ },
+ });
+
+ // fetchData();
};
- handleDelete = (row) => {
- deleteItem({id:row.id}).then(res => {
+ const handleDelete = (row) => {
+ deleteItem({ id: row.id }).then(res => {
message.success("删除成功")
- this.fetchData();
+ fetchData();
})
}
- handleEdit = (row) => {
- this.setState({
- currentRowData:Object.assign({}, row),
+ const handleEdit = (row) => {
+ setState({
+ ...state,
+ currentRowData: Object.assign({}, row),
editModalVisible: true,
});
};
- handleOk = _ => {
- const { form } = this.formRef.props;
- form.validateFields((err, fieldsValue) => {
- if (err) {
- return;
- }
+ const handleOk = _ => {
+ const { form } = formRef.props;
+ form.validateFields().then((fieldsValue) => {
+
const values = {
...fieldsValue,
'star': "".padStart(fieldsValue['star'], '★'),
'date': fieldsValue['date'].format('YYYY-MM-DD HH:mm:ss'),
};
- this.setState({ editModalLoading: true, });
+ setState({ ...state, editModalLoading: true, });
editItem(values).then((response) => {
form.resetFields();
- this.setState({ editModalVisible: false, editModalLoading: false });
+ setState({ ...state, editModalVisible: false, editModalLoading: false });
message.success("编辑成功!")
- this.fetchData()
+ // fetchData()
}).catch(e => {
message.success("编辑失败,请重试!")
})
-
+
});
};
- handleCancel = _ => {
- this.setState({
+ const handleCancel = _ => {
+ setState({
+ ...state,
editModalVisible: false,
});
};
- render() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
record.id}
- dataSource={this.state.list}
- loading={this.state.loading}
- pagination={false}
- >
- a.id - b.id}/>
-
-
-
-
- {
- let color =
- status === "published" ? "green" : status === "deleted" ? "red" : "";
- return (
-
- {status}
-
- );
- }}/>
-
- (
-
-
- )}/>
-
-
-
`共${total}条数据`}
- onChange={this.changePage}
- current={this.state.listQuery.pageNumber}
- onShowSizeChange={this.changePageSize}
- showSizeChanger
- showQuickJumper
- hideOnSinglePage={true}
- />
- this.formRef = formRef}
- visible={this.state.editModalVisible}
- confirmLoading={this.state.editModalLoading}
- onCancel={this.handleCancel}
- onOk={this.handleOk}
- />
-
- );
- }
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+
+
+
+
record.id}
+ dataSource={state.list}
+ loading={state.loading}
+ pagination={false}
+ >
+ a.id - b.id} />
+
+
+
+
+ {
+ let color =
+ status === "published" ? "green" : status === "deleted" ? "red" : "";
+ return (
+
+ {status}
+
+ );
+ }} />
+
+ (
+
+ } title="编辑" onClick={handleEdit.bind(null, row)} />
+
+ } title="删除" onClick={handleDelete.bind(null, row)} />
+
+ )} />
+
+
+
`共${total}条数据`}
+ onChange={changePage}
+ current={state.listQuery.pageNumber}
+ onShowSizeChange={changePageSize}
+ showSizeChanger
+ showQuickJumper
+ hideOnSinglePage={true}
+ />
+ formRef = formRef}
+ visible={state.editModalVisible}
+ confirmLoading={state.editModalLoading}
+ onCancel={handleCancel}
+ onOk={handleOk}
+ />
+
+ );
}
export default TableComponent;
diff --git a/src/views/user/forms/add-user-form.jsx b/src/views/user/forms/add-user-form.jsx
index 2482b09..ddc5c2c 100644
--- a/src/views/user/forms/add-user-form.jsx
+++ b/src/views/user/forms/add-user-form.jsx
@@ -1,9 +1,12 @@
-import React, { Component } from "react";
+import React from "react";
import { Form, Input, Select, Modal } from "antd";
import { reqValidatUserID } from "@/api/user";
const { TextArea } = Input;
-class AddUserForm extends Component {
- validatUserID = async (rule, value, callback) => {
+const AddUserForm = ({ visible, onCancel, onOk, formRef, confirmLoading }) => {
+
+ const [form] = Form.useForm();
+
+ const validatUserID = async (rule, value, callback) => {
if (value) {
if (!/^[a-zA-Z0-9]{1,6}$/.test(value)) {
callback("用户ID必须为1-6位数字或字母组合");
@@ -18,54 +21,43 @@ class AddUserForm extends Component {
}
callback();
};
- render() {
- const { visible, onCancel, onOk, form, confirmLoading } = this.props;
- const { getFieldDecorator } = form;
- const formItemLayout = {
- labelCol: {
- sm: { span: 4 },
- },
- wrapperCol: {
- sm: { span: 16 },
- },
- };
- return (
-
-
- {getFieldDecorator("id", {
- rules: [{ required: true, validator: this.validatUserID }],
- })()}
-
-
- {getFieldDecorator("name", {
- rules: [{ required: true, message: "请输入用户名称!" }],
- })()}
-
-
- {getFieldDecorator("role", {
- initialValue: "admin",
- })(
-
- )}
-
-
- {getFieldDecorator("description", {
- })()}
-
-
-
- );
- }
+ const formItemLayout = {
+ labelCol: {
+ sm: { span: 4 },
+ },
+ wrapperCol: {
+ sm: { span: 16 },
+ },
+ };
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
}
-export default Form.create({ name: "AddUserForm" })(AddUserForm);
+export default AddUserForm;
diff --git a/src/views/user/forms/edit-user-form.jsx b/src/views/user/forms/edit-user-form.jsx
index 16becc8..4831243 100644
--- a/src/views/user/forms/edit-user-form.jsx
+++ b/src/views/user/forms/edit-user-form.jsx
@@ -1,66 +1,59 @@
import React, { Component } from "react";
import { Form, Input, Select, Modal } from "antd";
const { TextArea } = Input;
-class EditUserForm extends Component {
- render() {
- const {
- visible,
- onCancel,
- onOk,
- form,
- confirmLoading,
- currentRowData,
- } = this.props;
- const { getFieldDecorator } = form;
- const { id, name, role, description } = currentRowData;
- const formItemLayout = {
- labelCol: {
- sm: { span: 4 },
- },
- wrapperCol: {
- sm: { span: 16 },
- },
- };
- return (
-
-
- {getFieldDecorator("id", {
- initialValue: id,
- })()}
-
-
- {getFieldDecorator("name", {
- rules: [{ required: true, message: "请输入用户名称!" }],
- initialValue: name,
- })()}
-
-
- {getFieldDecorator("role", {
- initialValue: role,
- })(
-
- )}
-
-
- {getFieldDecorator("description", {
- initialValue: description,
- })()}
-
-
-
- );
- }
+const EditUserForm = ({
+ visible,
+ onCancel,
+ onOk,
+ confirmLoading,
+ currentRowData,
+ formRef,
+}) => {
+
+ const { id, name, role, description } = currentRowData;
+
+ const [form] = Form.useForm();
+
+ const formItemLayout = {
+ labelCol: {
+ sm: { span: 4 },
+ },
+ wrapperCol: {
+ sm: { span: 16 },
+ },
+ };
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+
}
-export default Form.create({ name: "EditUserForm" })(EditUserForm);
+export default EditUserForm;
+
diff --git a/src/views/user/index.jsx b/src/views/user/index.jsx
index f82aa30..a12eee8 100644
--- a/src/views/user/index.jsx
+++ b/src/views/user/index.jsx
@@ -1,144 +1,171 @@
-import React, { Component } from "react";
+import React, { useState, useEffect, useRef } from "react";
import { Card, Button, Table, message, Divider } from "antd";
+import Icon from '@ant-design/icons'
+import * as icons from '@ant-design/icons';
+
import { getUsers, deleteUser, editUser, addUser } from "@/api/user";
import TypingCard from '@/components/TypingCard'
import EditUserForm from "./forms/edit-user-form"
import AddUserForm from "./forms/add-user-form"
const { Column } = Table;
-class User extends Component {
- state = {
+const User = (props) => {
+
+ const editUserFormRef = useRef(null);
+ const addUserFormRef = useRef(null);
+
+ const [state, setState] = useState({
users: [],
editUserModalVisible: false,
editUserModalLoading: false,
currentRowData: {},
addUserModalVisible: false,
addUserModalLoading: false,
- };
- getUsers = async () => {
+ });
+
+
+
+ useEffect(() => {
+ fetchData();
+ }, [state.addUserModalVisible, state.editUserModalVisible]);
+
+ const fetchData = async () => {
const result = await getUsers()
const { users, status } = result.data
if (status === 0) {
- this.setState({
+
+ setState({
+ ...state,
users
})
}
}
- handleEditUser = (row) => {
- this.setState({
- currentRowData:Object.assign({}, row),
+
+ const handleAddUser = (row) => {
+ setState({
+ ...state,
+ addUserModalVisible: true,
+ });
+ };
+
+ const handleCancel = _ => {
+ setState({
+ ...state,
+ editUserModalVisible: false,
+ addUserModalVisible: false,
+ });
+ };
+
+
+ const handleEditUser = (row) => {
+ setState({
+ ...state,
+ currentRowData: Object.assign({}, row),
editUserModalVisible: true,
});
};
- handleDeleteUser = (row) => {
+ const handleDeleteUser = (row) => {
const { id } = row
if (id === "admin") {
message.error("不能删除管理员用户!")
return
}
- deleteUser({id}).then(res => {
+ deleteUser({ id }).then(res => {
message.success("删除成功")
- this.getUsers();
+ fetchData();
})
}
-
- handleEditUserOk = _ => {
- const { form } = this.editUserFormRef.props;
- form.validateFields((err, values) => {
- if (err) {
- return;
- }
- this.setState({ editModalLoading: true, });
- editUser(values).then((response) => {
+
+ const handleAddUserOk = _ => {
+ const form = addUserFormRef.current;
+
+ form && form.validateFields().then((values) => {
+
+ setState({ ...state, addUserModalLoading: true, });
+ addUser(values).then((response) => {
form.resetFields();
- this.setState({ editUserModalVisible: false, editUserModalLoading: false });
- message.success("编辑成功!")
- this.getUsers()
+ setState({ ...state, addUserModalVisible: false, addUserModalLoading: false });
+ message.success("添加成功!")
+
}).catch(e => {
- message.success("编辑失败,请重试!")
+ message.success("添加失败,请重试!")
})
-
- });
- };
- handleCancel = _ => {
- this.setState({
- editUserModalVisible: false,
- addUserModalVisible: false,
+ // fetchData();
});
};
- handleAddUser = (row) => {
- this.setState({
- addUserModalVisible: true,
- });
- };
+ const handleEditUserOk = _ => {
+ const form = editUserFormRef.current;
- handleAddUserOk = _ => {
- const { form } = this.addUserFormRef.props;
- form.validateFields((err, values) => {
- if (err) {
- return;
- }
- this.setState({ addUserModalLoading: true, });
- addUser(values).then((response) => {
+ form && form.validateFields().then((values) => {
+ setState({ ...state, editModalLoading: true, });
+ editUser(values).then((response) => {
form.resetFields();
- this.setState({ addUserModalVisible: false, addUserModalLoading: false });
- message.success("添加成功!")
- this.getUsers()
+ setState({ ...state, editUserModalVisible: false, editUserModalLoading: false });
+ message.success("编辑成功!")
+
}).catch(e => {
- message.success("添加失败,请重试!")
+ message.success("编辑失败,请重试!")
})
+
+ // fetchData();
+
});
};
- componentDidMount() {
- this.getUsers()
- }
- render() {
- const { users } = this.state
- const title = (
-
- 添加用户
-
- )
- const cardContent = `在这里,你可以对系统中的用户进行管理,例如添加一个新用户,或者修改系统中已经存在的用户。`
- return (
-
-
-
-
-
-
-
-
-
- (
-
-
-
-
-
- )}/>
-
-
-
this.editUserFormRef = formRef}
- visible={this.state.editUserModalVisible}
- confirmLoading={this.state.editUserModalLoading}
- onCancel={this.handleCancel}
- onOk={this.handleEditUserOk}
- />
- this.addUserFormRef = formRef}
- visible={this.state.addUserModalVisible}
- confirmLoading={this.state.addUserModalLoading}
- onCancel={this.handleCancel}
- onOk={this.handleAddUserOk}
- />
-
- );
- }
+
+
+
+
+
+
+
+
+ const { users } = state
+ const title = (
+
+ 添加用户
+
+ )
+ const cardContent = `在这里,你可以对系统中的用户进行管理,例如添加一个新用户,或者修改系统中已经存在的用户。`
+ return (
+
+
+
+
+
+
+
+
+
+ (
+
+ } title="编辑" onClick={handleEditUser.bind(null, row)} />
+
+ } title="删除" onClick={handleDeleteUser.bind(null, row)} />
+
+ )} />
+
+
+
editUserFormRef = formRef}
+ formRef={editUserFormRef}
+ visible={state.editUserModalVisible}
+ confirmLoading={state.editUserModalLoading}
+ onCancel={handleCancel}
+ onOk={handleEditUserOk}
+ />
+ addUserFormRef = formRef}
+ formRef={addUserFormRef}
+ visible={state.addUserModalVisible}
+ confirmLoading={state.addUserModalLoading}
+ onCancel={handleCancel}
+ onOk={handleAddUserOk}
+ />
+
+ );
}
export default User;
diff --git a/src/views/zip/index.jsx b/src/views/zip/index.jsx
index 1c37eff..976977f 100644
--- a/src/views/zip/index.jsx
+++ b/src/views/zip/index.jsx
@@ -1,5 +1,8 @@
-import React, { Component } from "react";
-import { Table, Tag, Form, Icon, Button, Input, message, Collapse } from "antd";
+import React, { useState, useEffect } from "react";
+import { Table, Tag, Form, Button, Input, message, Collapse } from "antd";
+import Icon from '@ant-design/icons'
+import * as icons from '@ant-design/icons';
+
import { excelList } from "@/api/excel";
const { Panel } = Collapse;
const columns = [
@@ -40,122 +43,127 @@ const columns = [
align: "center",
},
];
-class Zip extends Component {
- _isMounted = false; // 这个变量是用来标志当前组件是否挂载
- state = {
+const Zip = (props) => {
+
+ const [isMounted, setMounted] = useState(false);
+ const [state, setState] = useState({
list: [],
filename: "file",
downloadLoading: false,
selectedRows: [],
selectedRowKeys: [],
- };
- fetchData = () => {
+ });
+
+ const fetchData = () => {
excelList().then((response) => {
const list = response.data.data.items;
- if (this._isMounted) {
- this.setState({ list });
+ if (isMounted) {
+ setState({ list });
}
});
};
- componentDidMount() {
- this._isMounted = true;
- this.fetchData();
- }
- componentWillUnmount() {
- this._isMounted = false;
- }
- onSelectChange = (selectedRowKeys, selectedRows) => {
- this.setState({ selectedRows, selectedRowKeys });
+
+ useEffect(() => {
+ setMounted(true);
+ fetchData();
+ return () => {
+ setMounted(false);
+ };
+ }, []);
+
+ const onSelectChange = (selectedRowKeys, selectedRows) => {
+ setState({ ...state, selectedRows, selectedRowKeys });
};
- handleDownload = (type) => {
- if (type === "selected" && this.state.selectedRowKeys.length === 0) {
+ const handleDownload = (type) => {
+ if (type === "selected" && state.selectedRowKeys.length === 0) {
message.error("至少选择一项进行导出");
return;
}
- this.setState({
+ setState({
+ ...state,
downloadLoading: true,
});
import("@/lib/Export2Zip").then((zip) => {
const tHeader = ["Id", "Title", "Author", "Readings", "Date"];
const filterVal = ["id", "title", "author", "readings", "date"];
- const list = type === "all" ? this.state.list : this.state.selectedRows;
- const data = this.formatJson(filterVal, list);
+ const list = type === "all" ? state.list : state.selectedRows;
+ const data = formatJson(filterVal, list);
zip.export_txt_to_zip(
tHeader,
data,
- this.state.filename,
- this.state.filename
+ state.filename,
+ state.filename
);
- this.setState({
+ setState({
+ ...state,
selectedRowKeys: [], // 导出完成后将多选框清空
downloadLoading: false,
});
});
};
- formatJson(filterVal, jsonData) {
+ const formatJson = (filterVal, jsonData) => {
return jsonData.map((v) => filterVal.map((j) => v[j]));
}
- filenameChange = (e) => {
- this.setState({
+ const filenameChange = (e) => {
+ setState({
+ ...state,
filename: e.target.value,
});
};
- render() {
- const { selectedRowKeys } = this.state;
- const rowSelection = {
- selectedRowKeys,
- onChange: this.onSelectChange,
- };
- return (
-
-
-
-
-
- }
- placeholder="请输入文件名(默认file)"
- onChange={this.filenameChange}
- />
-
-
-
- 全部导出
-
-
-
-
- 导出已选择项
-
-
-
-
-
-
-
record.id}
- dataSource={this.state.list}
- pagination={false}
- rowSelection={rowSelection}
- loading={this.state.downloadLoading}
- />
-
- );
- }
+ const { selectedRowKeys } = state;
+ const rowSelection = {
+ selectedRowKeys,
+ onChange: onSelectChange,
+ };
+ return (
+
+
+
+
+
+ }
+ placeholder="请输入文件名(默认file)"
+ onChange={filenameChange}
+ />
+
+
+ }
+ onClick={handleDownload.bind(null, "all")}
+ >
+ 全部导出
+
+
+
+ }
+ onClick={handleDownload.bind(null, "selected")}
+ >
+ 导出已选择项
+
+
+
+
+
+
+
record.id}
+ dataSource={state.list}
+ pagination={false}
+ rowSelection={rowSelection}
+ loading={state.downloadLoading}
+ />
+
+ );
}
export default Zip;
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..5d446cf
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,80 @@
+import { defineConfig} from 'vite'
+import react from '@vitejs/plugin-react'
+import commonjs from 'vite-plugin-commonjs';
+import visualizer from 'rollup-plugin-visualizer';
+import path from 'path'
+
+import fs from 'fs/promises'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ define: {
+ 'process.env': process.env,
+ global: 'window',
+ },
+ // 静态资源引用路径,默认为"/"
+ base: './',
+ build: {
+ // build目录名称,默认为"dist"
+ outDir: 'build',
+ // 静态资源存放目录名称,默认为"assets"
+ assetsDir: 'static',
+ commonjsOptions: {
+ transformMixedEsModules: true, // 轉換兼容 commonjs
+ },
+ },
+ server: {
+ // 支持IP访问
+ host: true,
+ port: 3000,
+ // 设置反向代理
+ proxy: {
+ // 以下示例表示:请求URL中含有"/api",则反向代理到http://localhost
+ // 例如: http://localhost:3000/api/login -> http://localhost/api/login
+ '/api': {
+ target: 'http: //localhost/',
+ changeOrigin: true,
+ },
+ },
+ open: '/',
+ hmr: { timeout: 30000, overlay: false
+ },
+ watch: { usePolling: true
+ },
+ },
+ esbuild: {
+ loader: 'jsx',
+ include: /src\/.*\.jsx?$/,
+ exclude: [],
+ },
+ optimizeDeps: {
+ esbuildOptions: {
+ plugins: [
+ {
+ name: 'load-js-files-as-jsx',
+ setup(build) {
+ build.onLoad(
+ { filter: /src\/.*\.js$/
+ },
+ async (args) => ({
+ loader: 'jsx',
+ contents: await fs.readFile(args.path, 'utf8'),
+ })
+ )
+ },
+ },
+ ],
+ },
+ },
+
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, 'src'),
+ }
+ },
+ plugins: [
+ react(),
+ commonjs(),
+ visualizer(),
+ ],
+})