mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-02 08:58:36 +02:00
improve relay settings
This commit is contained in:
parent
2a34b370cd
commit
b960f8c600
189
public/relays.json
Normal file
189
public/relays.json
Normal file
@ -0,0 +1,189 @@
|
||||
{
|
||||
"_": "Download from https://nostr.watch/",
|
||||
"relays": [
|
||||
"wss://nostr.p2sh.co",
|
||||
"wss://nostr.lnprivate.network",
|
||||
"wss://relay.nostr.vision",
|
||||
"wss://nostr-3.orba.ca",
|
||||
"wss://satstacker.cloud",
|
||||
"wss://freedom-relay.herokuapp.com/ws",
|
||||
"wss://nostr-relay.freeberty.net",
|
||||
"wss://nostr-relay.wlvs.space",
|
||||
"wss://nostr-relay-dev.wlvs.space",
|
||||
"wss://nostr.onsats.org",
|
||||
"wss://nostr-relay.untethr.me",
|
||||
"wss://nostr-relay.lnmarkets.com",
|
||||
"wss://nostr.unknown.place",
|
||||
"wss://nostr.semisol.dev",
|
||||
"wss://nostr-pub.semisol.dev",
|
||||
"wss://nostr-verified.wellorder.net",
|
||||
"wss://nostr.drss.io",
|
||||
"wss://nostr.rocks",
|
||||
"wss://nostr.bitcoiner.social",
|
||||
"wss://nostr.openchain.fr",
|
||||
"wss://nostr.delo.software",
|
||||
"wss://relay.nostr.info",
|
||||
"wss://relay.nostr.pro",
|
||||
"wss://relay.minds.com/nostr/v1/ws",
|
||||
"wss://relay.damus.io",
|
||||
"wss://nostr.zaprite.io",
|
||||
"wss://nostr.oxtr.dev",
|
||||
"wss://nostr.ono.re",
|
||||
"wss://relay.grunch.dev",
|
||||
"wss://relay.cynsar.foundation",
|
||||
"wss://nostr-pub.wellorder.net",
|
||||
"wss://relay.oldcity-bitcoiners.info",
|
||||
"wss://relay.bitid.nz",
|
||||
"wss://relay.nostr.xyz",
|
||||
"wss://relay.futohq.com",
|
||||
"wss://nostr.rdfriedl.com",
|
||||
"wss://relay.farscapian.com",
|
||||
"wss://astral.ninja",
|
||||
"wss://relay.sovereign-stack.org",
|
||||
"wss://nostr.sandwich.farm",
|
||||
"wss://nostr.zebedee.cloud",
|
||||
"wss://nostr-2.zebedee.cloud",
|
||||
"wss://nostr.shadownode.org",
|
||||
"wss://nostr.nymsrelay.com",
|
||||
"wss://expensive-relay.fiatjaf.com",
|
||||
"wss://relay.kronkltd.net",
|
||||
"wss://relay.r3d.red",
|
||||
"wss://relay.valireum.net",
|
||||
"wss://nostr.fmt.wiz.biz",
|
||||
"wss://nostr.v0l.io",
|
||||
"wss://relay.cryptocculture.com",
|
||||
"wss://nostr.fly.dev",
|
||||
"wss://nostr.nordlysln.net",
|
||||
"wss://nostr-relay.gkbrk.com",
|
||||
"wss://nostr.zerofeerouting.com",
|
||||
"wss://no.str.cr",
|
||||
"wss://relay.nostr.ch",
|
||||
"wss://rsslay.nostr.net",
|
||||
"wss://nostr.cercatrova.me",
|
||||
"wss://public.nostr.swissrouting.com",
|
||||
"wss://nostr-relay.nonce.academy",
|
||||
"wss://nostr.rewardsbunny.com",
|
||||
"wss://nostr.slothy.win",
|
||||
"wss://nostr-verif.slothy.win",
|
||||
"wss://nostr.coinos.io",
|
||||
"wss://relay.nostropolis.xyz/websocket",
|
||||
"wss://lv01.tater.ninja",
|
||||
"wss://nostr-2.orba.ca",
|
||||
"wss://nostr.orba.ca",
|
||||
"wss://nostr.supremestack.xyz",
|
||||
"wss://nostrrelay.com",
|
||||
"wss://nostr-01.bolt.observer",
|
||||
"wss://nostr.mom",
|
||||
"wss://relay.nostr.au",
|
||||
"wss://nostr.swiss-enigma.ch",
|
||||
"wss://nostr.oooxxx.ml",
|
||||
"wss://nostr.yael.at",
|
||||
"wss://nostr-relay.trustbtc.org",
|
||||
"wss://nostr.namek.link",
|
||||
"wss://nostr-relay.wolfandcrow.tech",
|
||||
"wss://nostr.8e23.net",
|
||||
"wss://nostr.actn.io",
|
||||
"wss://relay.sendstr.com",
|
||||
"wss://nostr.satsophone.tk",
|
||||
"wss://nostr-relay.derekross.me",
|
||||
"wss://nostr.jiashanlu.synology.me",
|
||||
"wss://nostr.radixrat.com",
|
||||
"wss://nostr.shawnyeager.net",
|
||||
"wss://relay.dev.kronkltd.net",
|
||||
"wss://nostr2.namek.link",
|
||||
"wss://nostr-dev.wellorder.net",
|
||||
"wss://nostr.mwmdev.com",
|
||||
"wss://relay.21spirits.io",
|
||||
"wss://nostr-relay.freedomnode.com",
|
||||
"wss://relay.minds.io/nostr/v1/ws",
|
||||
"wss://wlvs.space",
|
||||
"wss://nostr.einundzwanzig.space",
|
||||
"wss://nostr.d11n.net",
|
||||
"wss://nostr1.tunnelsats.com",
|
||||
"wss://nostr.tunnelsats.com",
|
||||
"wss://nostr.leximaster.com",
|
||||
"wss://nostr.hugo.md",
|
||||
"wss://mule.platanito.org",
|
||||
"wss://relay.ryzizub.com",
|
||||
"wss://nostr.w3ird.tech",
|
||||
"wss://nostr.robotechy.com",
|
||||
"wss://relay.stoner.com",
|
||||
"wss://relay.nostrmoto.xyz",
|
||||
"wss://relay.boring.surf",
|
||||
"wss://nostr.bongbong.com",
|
||||
"wss://nostr.gruntwerk.org",
|
||||
"wss://nostr.mado.io",
|
||||
"wss://nostr.corebreach.com",
|
||||
"wss://nostr.hyperlingo.com",
|
||||
"wss://nostr.ethtozero.fr",
|
||||
"wss://nostr-relay.digitalmob.ro",
|
||||
"wss://relay.nvote.co",
|
||||
"wss://jiggytom.ddns.net",
|
||||
"wss://nostr.sectiontwo.org",
|
||||
"wss://nostr.roundrockbitcoiners.com",
|
||||
"wss://nostr.nodeofsven.com",
|
||||
"wss://nostr.jimc.me",
|
||||
"wss://nostr.utxo.lol",
|
||||
"wss://relay.lexingtonbitcoin.org",
|
||||
"wss://nostr.mikedilger.com",
|
||||
"wss://nostr.f44.dev",
|
||||
"wss://relay.nyx.ma",
|
||||
"wss://nostr.walletofsatoshi.com",
|
||||
"wss://nostr.shmueli.org",
|
||||
"wss://wizards.wormrobot.org",
|
||||
"wss://nostr.orangepill.dev",
|
||||
"wss://paid.no.str.cr",
|
||||
"wss://nostr.sovbit.com",
|
||||
"wss://nostr.datamagik.com",
|
||||
"wss://relay.nostrid.com",
|
||||
"wss://nostr1.starbackr.me",
|
||||
"wss://nostr-relay.schnitzel.world",
|
||||
"wss://relay.nostr.express",
|
||||
"wss://sg.qemura.xyz",
|
||||
"wss://nostr.formigator.eu",
|
||||
"wss://nostr.xpersona.net",
|
||||
"wss://relay.n057r.club",
|
||||
"wss://nostr.digitalreformation.info",
|
||||
"wss://nostr.gromeul.eu",
|
||||
"wss://nostr-relay.alekberg.net",
|
||||
"wss://nostr2.actn.io",
|
||||
"wss://nostr-relay.usebitcoin.space",
|
||||
"wss://nostrich.friendship.tw",
|
||||
"wss://nostr.mustardnodes.com",
|
||||
"wss://nostr-alpha.gruntwerk.org",
|
||||
"wss://nostr-relay.australiaeast.cloudapp.azure.com",
|
||||
"wss://nostr.bch.ninja",
|
||||
"wss://nostr-relay.smoove.net",
|
||||
"wss://nostr-relay.j3s7m4n.com",
|
||||
"wss://nostr.demovement.net",
|
||||
"wss://nostr.thesimplekid.com",
|
||||
"wss://nostr.aozing.com",
|
||||
"wss://nostr.blocs.fr",
|
||||
"wss://no.str.watch",
|
||||
"wss://nostr.vulpem.com",
|
||||
"wss://btc.klendazu.com",
|
||||
"wss://nostr.hackerman.pro",
|
||||
"wss://relay.realsearch.cc",
|
||||
"wss://nostr.mrbits.it",
|
||||
"wss://nostr.coollamer.com",
|
||||
"wss://node01.nostress.cc",
|
||||
"wss://nostr.zenon.wtf",
|
||||
"wss://nostr.massmux.com",
|
||||
"wss://no.contry.xyz",
|
||||
"wss://relay.nostr.bg",
|
||||
"wss://nostr.uselessshit.co",
|
||||
"wss://brb.io",
|
||||
"wss://nostream.gromeul.eu",
|
||||
"wss://relay.nostr.ro",
|
||||
"wss://nostr.developer.li",
|
||||
"wss://nostr.screaminglife.io",
|
||||
"wss://deschooling.us",
|
||||
"wss://relay-pub.deschooling.us",
|
||||
"wss://nostr-pub1.southflorida.ninja",
|
||||
"wss://nostr.ncsa.illinois.edu",
|
||||
"wss://nostr.whoop.ph",
|
||||
"wss://nostr.zoomout.chat",
|
||||
"wss://nostr.chaker.net",
|
||||
"wss://nostr-1.nbo.angani.co"
|
||||
]
|
||||
}
|
@ -1,99 +1,22 @@
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalFooter,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Tr,
|
||||
Th,
|
||||
Td,
|
||||
TableCaption,
|
||||
TableContainer,
|
||||
useDisclosure,
|
||||
Badge,
|
||||
} from "@chakra-ui/react";
|
||||
import { useState } from "react";
|
||||
import { Text } from "@chakra-ui/react";
|
||||
import { useInterval } from "react-use";
|
||||
import { Relay } from "../services/relays";
|
||||
import relayPool from "../services/relays/relay-pool";
|
||||
import useSubject from "../hooks/use-subject";
|
||||
import settings from "../services/settings";
|
||||
|
||||
const getRelayStatusText = (relay: Relay) => {
|
||||
if (relay.connecting) return "Connecting...";
|
||||
if (relay.connected) return "Connected";
|
||||
if (relay.closing) return "Disconnecting...";
|
||||
if (relay.closed) return "Disconnected";
|
||||
};
|
||||
|
||||
export const ConnectedRelays = () => {
|
||||
const relayUrls = useSubject(settings.relays);
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const [relays, setRelays] = useState<Relay[]>([]);
|
||||
const [relays, setRelays] = useState<Relay[]>(relayPool.getRelays());
|
||||
|
||||
useInterval(() => {
|
||||
setRelays(relayPool.getRelays());
|
||||
}, 1000);
|
||||
|
||||
useInterval(() => {
|
||||
for (const url of relayUrls) {
|
||||
// ask the pool to reconnect if disconnected
|
||||
relayPool.requestRelay(url);
|
||||
}
|
||||
}, 1000 * 30);
|
||||
|
||||
const connected = relays.filter((relay) => relay.okay);
|
||||
const disconnected = relays.filter((relay) => !relay.okay);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant="link" onClick={onOpen}>
|
||||
{connected.length}/{relays.length} of relays connected
|
||||
</Button>
|
||||
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="4xl">
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>Relay Status</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<TableContainer>
|
||||
<Table variant="simple">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>Url</Th>
|
||||
<Th>status</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{relays.map((relay) => (
|
||||
<Tr key={relay.url}>
|
||||
<Td>{relay.url}</Td>
|
||||
<Td>
|
||||
<Badge colorScheme={relay.okay ? "green" : "red"}>
|
||||
{getRelayStatusText(relay)}
|
||||
</Badge>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button colorScheme="blue" mr={3} onClick={onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
<Text textAlign="center">
|
||||
{connected.length}/{relays.length} of relays connected
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
@ -49,3 +49,8 @@ export const ClipboardIcon = createIcon({
|
||||
displayName: "clipboard-line",
|
||||
d: "M7 4V2h10v2h3.007c.548 0 .993.445.993.993v16.014a.994.994 0 0 1-.993.993H3.993A.994.994 0 0 1 3 21.007V4.993C3 4.445 3.445 4 3.993 4H7zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z",
|
||||
});
|
||||
|
||||
export const TrashIcon = createIcon({
|
||||
displayName: "delete-bin-line",
|
||||
d: "M17 6h5v2h-2v13a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V8H2V6h5V3a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v3zm1 2H6v12h12V8zm-9 3h2v6H9v-6zm4 0h2v6h-2v-6zM9 4v2h6V4H9z",
|
||||
});
|
||||
|
@ -1,77 +0,0 @@
|
||||
import {
|
||||
Button,
|
||||
Divider,
|
||||
Flex,
|
||||
FormControl,
|
||||
FormHelperText,
|
||||
FormLabel,
|
||||
Heading,
|
||||
Input,
|
||||
Stack,
|
||||
Switch,
|
||||
Textarea,
|
||||
useColorMode,
|
||||
} from "@chakra-ui/react";
|
||||
import { SyntheticEvent, useState } from "react";
|
||||
import useSubject from "../hooks/use-subject";
|
||||
import settings from "../services/settings";
|
||||
|
||||
export const SettingsView = () => {
|
||||
const relays = useSubject(settings.relays);
|
||||
const [relayUrls, setRelayUrls] = useState(relays.join("\n"));
|
||||
|
||||
const { colorMode, setColorMode } = useColorMode();
|
||||
|
||||
const handleSubmit = async (event: SyntheticEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
const newRelays = relayUrls
|
||||
.split("\n")
|
||||
.filter(Boolean)
|
||||
.map((url) => url.trim());
|
||||
|
||||
if (newRelays.length > 0) {
|
||||
settings.relays.next(newRelays);
|
||||
}
|
||||
};
|
||||
|
||||
const resetForm = async () => {
|
||||
setRelayUrls(relays.join("\n"));
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="4" pt="2" pb="2" overflow="auto">
|
||||
<Heading>Settings</Heading>
|
||||
<FormControl display="flex" alignItems="center">
|
||||
<FormLabel htmlFor="use-dark-theme" mb="0">
|
||||
Use dark theme
|
||||
</FormLabel>
|
||||
<Switch
|
||||
id="use-dark-theme"
|
||||
isChecked={colorMode === "dark"}
|
||||
onChange={(v) => setColorMode(v.target.checked ? "dark" : "light")}
|
||||
/>
|
||||
</FormControl>
|
||||
<Divider />
|
||||
<form onSubmit={handleSubmit}>
|
||||
<FormControl>
|
||||
<FormLabel>Relays</FormLabel>
|
||||
<Textarea
|
||||
value={relayUrls}
|
||||
onChange={(e) => setRelayUrls(e.target.value)}
|
||||
required
|
||||
size="md"
|
||||
rows={10}
|
||||
resize="vertical"
|
||||
/>
|
||||
<FormHelperText>One relay per line</FormHelperText>
|
||||
</FormControl>
|
||||
<Stack direction="row" spacing={4}>
|
||||
<Button onClick={resetForm}>Reset</Button>
|
||||
<Button type="submit" colorScheme="teal">
|
||||
Save
|
||||
</Button>
|
||||
</Stack>
|
||||
</form>
|
||||
</Flex>
|
||||
);
|
||||
};
|
152
src/views/settings/index.tsx
Normal file
152
src/views/settings/index.tsx
Normal file
@ -0,0 +1,152 @@
|
||||
import {
|
||||
Button,
|
||||
Flex,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Switch,
|
||||
useColorMode,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Tr,
|
||||
Th,
|
||||
Td,
|
||||
TableContainer,
|
||||
IconButton,
|
||||
AccordionItem,
|
||||
Accordion,
|
||||
AccordionPanel,
|
||||
AccordionButton,
|
||||
Box,
|
||||
AccordionIcon,
|
||||
} from "@chakra-ui/react";
|
||||
import { SyntheticEvent, useState } from "react";
|
||||
import { useAsync } from "react-use";
|
||||
import { TrashIcon } from "../../components/icons";
|
||||
import { RelayStatus } from "./relay-status";
|
||||
import useSubject from "../../hooks/use-subject";
|
||||
import settings from "../../services/settings";
|
||||
|
||||
export const SettingsView = () => {
|
||||
const relays = useSubject(settings.relays);
|
||||
const [relayInputValue, setRelayInputValue] = useState("");
|
||||
|
||||
const { value: relaysJson, loading: loadingRelaysJson } = useAsync(async () =>
|
||||
fetch("/relays.json").then(
|
||||
(res) => res.json() as Promise<{ relays: string[] }>
|
||||
)
|
||||
);
|
||||
const relaySuggestions =
|
||||
relaysJson?.relays.filter((url) => !relays.includes(url)) ?? [];
|
||||
|
||||
const { colorMode, setColorMode } = useColorMode();
|
||||
|
||||
const handleRemoveRelay = (url: string) => {
|
||||
settings.relays.next(relays.filter((v) => v !== url));
|
||||
};
|
||||
const handleAddRelay = (event: SyntheticEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
|
||||
settings.relays.next([...relays, relayInputValue]);
|
||||
setRelayInputValue("");
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex direction="column" pt="2" pb="2" overflow="auto">
|
||||
<Accordion defaultIndex={[0]} allowMultiple>
|
||||
<AccordionItem>
|
||||
<h2>
|
||||
<AccordionButton>
|
||||
<Box as="span" flex="1" textAlign="left">
|
||||
Relays
|
||||
</Box>
|
||||
<AccordionIcon />
|
||||
</AccordionButton>
|
||||
</h2>
|
||||
<AccordionPanel>
|
||||
<TableContainer mb="4">
|
||||
<Table variant="simple" size="sm">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>Url</Th>
|
||||
<Th>Status</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{relays.map((url) => (
|
||||
<Tr key={url}>
|
||||
<Td>{url}</Td>
|
||||
<Td>
|
||||
<RelayStatus url={url} />
|
||||
</Td>
|
||||
<Td isNumeric>
|
||||
<IconButton
|
||||
icon={<TrashIcon />}
|
||||
title="Remove Relay"
|
||||
aria-label="Remove Relay"
|
||||
size="sm"
|
||||
onClick={() => handleRemoveRelay(url)}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<form onSubmit={handleAddRelay}>
|
||||
<FormControl>
|
||||
<FormLabel htmlFor="relay-url-input">Add Relay</FormLabel>
|
||||
<Flex gap="2">
|
||||
<Input
|
||||
id="relay-url-input"
|
||||
value={relayInputValue}
|
||||
onChange={(e) => setRelayInputValue(e.target.value)}
|
||||
required
|
||||
list="relay-suggestions"
|
||||
type="url"
|
||||
isDisabled={loadingRelaysJson}
|
||||
/>
|
||||
<datalist id="relay-suggestions">
|
||||
{relaySuggestions.map((url) => (
|
||||
<option key={url} value={url}>
|
||||
{url}
|
||||
</option>
|
||||
))}
|
||||
</datalist>
|
||||
<Button type="submit">Add</Button>
|
||||
</Flex>
|
||||
</FormControl>
|
||||
</form>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem>
|
||||
<h2>
|
||||
<AccordionButton>
|
||||
<Box as="span" flex="1" textAlign="left">
|
||||
Display
|
||||
</Box>
|
||||
<AccordionIcon />
|
||||
</AccordionButton>
|
||||
</h2>
|
||||
<AccordionPanel>
|
||||
<FormControl display="flex" alignItems="center">
|
||||
<FormLabel htmlFor="use-dark-theme" mb="0">
|
||||
Use dark theme
|
||||
</FormLabel>
|
||||
<Switch
|
||||
id="use-dark-theme"
|
||||
isChecked={colorMode === "dark"}
|
||||
onChange={(v) =>
|
||||
setColorMode(v.target.checked ? "dark" : "light")
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</Flex>
|
||||
);
|
||||
};
|
30
src/views/settings/relay-status.tsx
Normal file
30
src/views/settings/relay-status.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { Badge, useForceUpdate } from "@chakra-ui/react";
|
||||
import { useInterval } from "react-use";
|
||||
import { Relay, relayPool } from "../../services/relays";
|
||||
|
||||
const getStatusText = (relay: Relay) => {
|
||||
if (relay.connecting) return "Connecting...";
|
||||
if (relay.connected) return "Connected";
|
||||
if (relay.closing) return "Disconnecting...";
|
||||
if (relay.closed) return "Disconnected";
|
||||
return "Unused";
|
||||
};
|
||||
const getStatusColor = (relay: Relay) => {
|
||||
if (relay.connecting) return "yellow";
|
||||
if (relay.connected) return "green";
|
||||
if (relay.closing) return "yellow";
|
||||
if (relay.closed) return "red";
|
||||
return "gray";
|
||||
};
|
||||
|
||||
export const RelayStatus = ({ url }: { url: string }) => {
|
||||
const update = useForceUpdate();
|
||||
|
||||
const relay = relayPool.requestRelay(url, false);
|
||||
|
||||
useInterval(() => update(), 500);
|
||||
|
||||
return (
|
||||
<Badge colorScheme={getStatusColor(relay)}>{getStatusText(relay)}</Badge>
|
||||
);
|
||||
};
|
@ -5,7 +5,6 @@ import react from "@vitejs/plugin-react";
|
||||
export default defineConfig({
|
||||
build: {
|
||||
target: ["chrome89", "edge89", "firefox89", "safari15"],
|
||||
minify: false,
|
||||
},
|
||||
plugins: [react()],
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user