This commit is contained in:
moririn2528
2023-09-01 18:35:22 +09:00
19 changed files with 556 additions and 68 deletions
+3
View File
@@ -0,0 +1,3 @@
[run]
concurrency = multiprocessing,thread
source = optuna_dashboard/
+49
View File
@@ -0,0 +1,49 @@
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
publish-gh-pages:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust toolchains
uses: dtolnay/rust-toolchain@stable
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Build standalone_app
env:
PUBLIC_PATH: /optuna-dashboard/public/
run: make MODE="prd" standalone_app/public/bundle.js
- name: Create publish directory
run: |
mkdir gh-publish
cp -r standalone_app/public gh-publish/public
cp standalone_app/favicon.ico gh-publish/favicon.ico
cp standalone_app/github-pages.html gh-publish/index.html
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
path: './gh-publish'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
+48
View File
@@ -0,0 +1,48 @@
name: python coverage
on:
push:
branches:
- master
pull_request: {}
jobs:
coverage:
runs-on: ubuntu-latest
# Not intended for forks.
if: github.repository == 'optuna/optuna-dashboard'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
architecture: x64
- name: Install dependencies
run: |
python -m pip install --progress-bar off --upgrade pip setuptools
pip install --progress-bar off .[optional]
pip install --progress-bar off .[test]
pip install --progress-bar off "optuna>=3.0.0"
pip install --progress-bar off .
echo 'import coverage; coverage.process_startup()' > sitecustomize.py
- name: Tests
env:
PYTHONPATH: . # To invoke sitecutomize.py
COVERAGE_PROCESS_START: .coveragerc # https://coverage.readthedocs.io/en/6.4.1/subprocess.html
COVERAGE_COVERAGE: yes # https://github.com/nedbat/coveragepy/blob/65bf33fc03209ffb01bbbc0d900017614645ee7a/coverage/control.py#L255-L261
run: |
coverage run --source=optuna_dashboard -m pytest python_tests
coverage combine
coverage xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
fail_ci_if_error: true
+4 -2
View File
@@ -45,7 +45,8 @@ jobs:
# python_tests requires optuna>=3.0.0 since it imports FloatDistribution
run: |
python -m pip install --progress-bar off --upgrade pip setuptools
pip install streamlit boto3 moto[s3] pytest
pip install --progress-bar off .[optional]
pip install --progress-bar off .[test]
pip install --progress-bar off "optuna>=3.0.0"
pip install --progress-bar off .
- run: pytest python_tests
@@ -61,7 +62,8 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --progress-bar off --upgrade pip setuptools
pip install streamlit boto3 moto[s3] pytest
pip install --progress-bar off .[optional]
pip install --progress-bar off .[test]
pip install --progress-bar off .
python -m pip install --progress-bar off --upgrade git+https://github.com/optuna/optuna.git
- run: pytest python_tests
+7
View File
@@ -28,9 +28,16 @@ docs/_generated/
rustlib/target/
rustlib/pkg/
# Test
.coverage
.coverage.*
coverage.xml
# Others
.envrc
.idea/
.vscode/
.DS_Store
tmp/
examples/preferential-optimization/artifact/
+16 -15
View File
@@ -45,6 +45,8 @@ Listening on http://localhost:8080/
Hit Ctrl-C to quit.
```
<img src="./docs/_static/optuna-dashboard.gif" style="width:600px;" alt="VSCode Extension">
Please check out [our documentation](https://optuna-dashboard.readthedocs.io/en/latest/getting-started.html) for more details.
## Using an official Docker image
@@ -75,27 +77,26 @@ $ docker run -it --rm -p 8080:8080 ghcr.io/optuna/optuna-dashboard postgresql+ps
</details>
## Browser-only version (Experimental)
<img src="./docs/_static/browser-app.gif" style="width:600px;" alt="Browser-only version">
Weve developed the version that operates solely within your web browser, which internally uses SQLite3 Wasm and Rust.
Theres no need to install Python or any other dependencies.
Simply open the following URL in your browser, drag and drop your SQLite3 file onto the page, and youre ready to view your Optuna studies!
https://optuna.github.io/optuna-dashboard/
*Please note that only a subset of features is available. However, you can still check the optimization history, hyperparameter importances, and etc. in graphs and tables.*
## VS Code Extension (Experimental)
You can install the VS Code extension via [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=Optuna.optuna-dashboard#overview).
![vscode-extension](./docs/_static/vscode-extension.png)
<img src="./docs/_static/vscode-extension.png" style="width:600px;" alt="VSCode Extension">
Please right-click the SQLite3 files (`*.db` or `*.sqlite3`) in the VS Code file explorer and select the "Open in Optuna Dashboard" command from the dropdown menu.
## Features
### Manage Studies
You can create and delete studies from Dashboard.
![optuna-dashboard-create-delete-study](https://user-images.githubusercontent.com/5564044/205545958-305f2354-c7cd-4687-be2f-9e46e7401838.gif)
### Visualize with Interactive Graphs & Rich Trials Data Grid
You can check the optimization history, hyperparameter importances, etc. in graphs and tables.
![optuna-dashboard-realtime-graph](https://user-images.githubusercontent.com/5564044/205545965-278cd7f4-da7d-4e2e-ac31-6d81b106cada.gif)
This extension leverages the browser-only version of Optuna Dashboard, so the same limitations apply.
## Submitting patches
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 810 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

+43 -11
View File
@@ -1,6 +1,13 @@
Getting Started
===============
.. figure:: _static/optuna-dashboard.gif
:alt: Optuna Dashboard
:align: center
:width: 800px
Optuna Dashboard
Installation
------------
@@ -172,6 +179,42 @@ or
$ uwsgi --http :8080 --workeers 4 --wsgi-file wsgi.py
Browser-only version (Experimental)
-----------------------------------
.. figure:: _static/browser-app.gif
:alt: GIF animation for the browser-only version
:align: center
:width: 800px
Browser-only version of Optuna Dashboard, powered by Wasm.
We've developed the version that operates solely within your web browser.
There's no need to install Python or any other dependencies.
Simply open the following URL in your browser, drag and drop your SQLite3 file onto the page, and you're ready to view your Optuna studies!
https://optuna.github.io/optuna-dashboard/
.. warning::
Currently, only a subset of features is available. However, you can still check the optimization history, hyperparameter importances, and etc. in graphs and tables.
VS Code Extension (Experimental)
--------------------------------
You can install the VS Code extension via `Visual Studio Marketplace <https://marketplace.visualstudio.com/items?itemName=Optuna.optuna-dashboard#overview>`_.
.. figure:: _static/vscode-extension.png
:alt: Screenshot for the VS Code Extension
:align: center
:width: 800px
VS Code Extension
To use, right-click the SQLite3 files (``*.db`` or ``*.sqlite3``) in the file explorer and select the "Open in Optuna Dashboard" from the dropdown menu.
This extension leverages the browser-only version of Optuna Dashboard, so the same limitations apply.
Google Colaboratory
-------------------
@@ -201,14 +244,3 @@ you can use ``google.colab.output()`` function as follows:
output.serve_kernel_port_as_window(port, path='/dashboard/')
Then please open http://localhost:8081/dashboard to browse.
VS Code (Experimental)
----------------------
You can install the VS Code extension via `Visual Studio Marketplace <https://marketplace.visualstudio.com/items?itemName=Optuna.optuna-dashboard#overview>`_.
.. image:: _static/vscode-extension.png
:alt: Screenshot for the VS Code Extension
:align: center
Please right-click the SQLite3 files (`*.db` or `*.sqlite3`) in the file explorer and select the "Open in Optuna Dashboard" command from the dropdown menu.
+13 -15
View File
@@ -233,21 +233,19 @@ export const AppDrawer: FC<{
</ListItemButton>
</ListItem>
)}
{!isPreferential && (
<ListItem key="Analytics" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}/analytics`}
sx={styleListItemButton}
selected={page === "analytics"}
>
<ListItemIcon sx={styleListItemIcon}>
<QueryStatsIcon />
</ListItemIcon>
<ListItemText primary="Analytics" sx={styleListItemText} />
</ListItemButton>
</ListItem>
)}
<ListItem key="Analytics" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
to={`${URL_PREFIX}/studies/${studyId}/analytics`}
sx={styleListItemButton}
selected={page === "analytics"}
>
<ListItemIcon sx={styleListItemIcon}>
<QueryStatsIcon />
</ListItemIcon>
<ListItemText primary="Analytics" sx={styleListItemText} />
</ListItemButton>
</ListItem>
<ListItem key="TableList" disablePadding sx={styleListItem}>
<ListItemButton
component={Link}
@@ -96,9 +96,11 @@ export const BestTrialsCard: FC<{
<Typography variant="h5">Trial {trial.number}</Typography>
}
/>
<Typography>
Objective Values = [{trial.values?.join(", ")}]
</Typography>
{studyDetail?.is_preferential ? null : (
<Typography>
Objective Values = [{trial.values?.join(", ")}]
</Typography>
)}
<Typography>
Params = [
{trial.params
+49 -18
View File
@@ -11,6 +11,7 @@ import {
useTheme,
Box,
} from "@mui/material"
import blue from "@mui/material/colors/blue"
import { plotlyDarkTemplate } from "./PlotlyDarkMode"
import { useMergedUnionSearchSpace } from "../searchSpace"
@@ -211,32 +212,62 @@ const plotContour = (
}
})
if (!study.is_preferential) {
const plotData: Partial<plotly.PlotData>[] = [
{
type: "contour",
x: xIndices,
y: yIndices,
z: zValues,
colorscale: "Blues",
connectgaps: true,
hoverinfo: "none",
line: {
smoothing: 1.3,
},
reversescale: study.directions[objectiveId] !== "minimize",
// https://github.com/plotly/react-plotly.js/issues/251
// @ts-ignore
contours: {
coloring: "heatmap",
},
},
{
type: "scatter",
x: xValues,
y: yValues,
marker: { line: { width: 2.0, color: "Grey" }, color: "black" },
mode: "markers",
showlegend: false,
},
]
plotly.react(plotDomId, plotData, layout)
return
}
layout.legend = {
y: 0.8,
}
const bestTrialIndices = study.best_trials.map((trial) => trial.number)
const plotData: Partial<plotly.PlotData>[] = [
{
type: "contour",
x: xIndices,
y: yIndices,
z: zValues,
colorscale: "Blues",
connectgaps: true,
hoverinfo: "none",
line: {
smoothing: 1.3,
},
reversescale: study.directions[objectiveId] !== "minimize",
// https://github.com/plotly/react-plotly.js/issues/251
// @ts-ignore
contours: {
coloring: "heatmap",
type: "scatter",
x: xValues.filter((_, i) => bestTrialIndices.includes(i)),
y: yValues.filter((_, i) => bestTrialIndices.includes(i)),
marker: {
line: { width: 2.0, color: "Grey" },
color: blue[200],
},
name: "best trials",
mode: "markers",
},
{
type: "scatter",
x: xValues,
y: yValues,
x: xValues.filter((_, i) => !bestTrialIndices.includes(i)),
y: yValues.filter((_, i) => !bestTrialIndices.includes(i)),
marker: { line: { width: 2.0, color: "Grey" }, color: "black" },
name: "others",
mode: "markers",
showlegend: false,
},
]
plotly.react(plotDomId, plotData, layout)
@@ -0,0 +1,68 @@
import React, { FC } from "react"
import {
Box,
Card,
CardContent,
Paper,
Typography,
useTheme,
} from "@mui/material"
import Grid2 from "@mui/material/Unstable_Grid2"
import { DataGrid, DataGridColumn } from "./DataGrid"
import { BestTrialsCard } from "./BestTrialsCard"
import { useStudyDetailValue, useStudySummaryValue } from "../state"
import { Contour } from "./GraphContour"
export const PreferentialAnalytics: FC<{ studyId: number }> = ({ studyId }) => {
const theme = useTheme()
const studySummary = useStudySummaryValue(studyId)
const studyDetail = useStudyDetailValue(studyId)
const userAttrs = studySummary?.user_attrs || studyDetail?.user_attrs || []
const userAttrColumns: DataGridColumn<Attribute>[] = [
{ field: "key", label: "Key", sortable: true },
{ field: "value", label: "Value", sortable: true },
]
return (
<Box sx={{ display: "flex", width: "100%", flexDirection: "column" }}>
<Grid2 container spacing={2} sx={{ padding: theme.spacing(0, 2) }}>
<Grid2 xs={14}>
<Paper elevation={2} sx={{ padding: theme.spacing(2) }}>
<Contour study={studyDetail} />
</Paper>
</Grid2>
<Grid2 xs={6} spacing={2}>
<BestTrialsCard studyDetail={studyDetail} />
</Grid2>
<Grid2 xs={6}>
<Card>
<CardContent
sx={{
display: "flex",
flexDirection: "column",
}}
>
<Typography
variant="h6"
sx={{
margin: "1em 0",
fontWeight: theme.typography.fontWeightBold,
}}
>
Study User Attributes
</Typography>
<DataGrid<Attribute>
columns={userAttrColumns}
rows={userAttrs}
keyField={"key"}
dense={true}
initialRowsPerPage={5}
rowsPerPageOption={[5, 10, { label: "All", value: -1 }]}
/>
</CardContent>
</Card>
</Grid2>
</Grid2>
</Box>
)
}
@@ -31,6 +31,7 @@ import { TrialList } from "./TrialList"
import { StudyHistory } from "./StudyHistory"
import { PreferentialTrials } from "./PreferentialTrials"
import { PreferenceHistory } from "./PreferenceHistory"
import { PreferentialAnalytics } from "./PreferentialAnalytics"
interface ParamTypes {
studyId: string
@@ -99,7 +100,9 @@ export const StudyDetail: FC<{
<StudyHistory studyId={studyId} />
)
} else if (page === "analytics") {
content = (
content = isPreferential ? (
<PreferentialAnalytics studyId={studyId} />
) : (
<Box sx={{ display: "flex", width: "100%", flexDirection: "column" }}>
<Typography variant="h5" sx={{ margin: theme.spacing(2) }}>
Hyperparameter Relationships
+12
View File
@@ -41,6 +41,18 @@ docs = [
"sphinx_rtd_theme",
]
test = [
"coverage",
"pytest",
"moto[s3]",
]
optional = [
"streamlit",
"boto3",
]
[project.scripts]
optuna-dashboard = "optuna_dashboard._cli:main"
+19
View File
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Optuna Dashboard (Wasm ver.)</title>
<script defer type="module" src="/optuna-dashboard/public/bundle.js"></script>
<link rel="icon" href="/optuna-dashboard/favicon.ico" />
<!-- ogp -->
<meta property="og:title" content="Optuna Dashboard (Wasm ver.)" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://optuna.github.io/optuna-dashboard/" />
<meta property="og:image" content="/img/ogp_image.png" />
<meta property="og:description" content="Web Dashboard for Optuna, Python library for hyperparameter optimization" />
</head>
<body>
<div id="root"></div>
</body>
</html>
+208
View File
@@ -28,6 +28,7 @@
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.1",
"@types/react-router-dom": "^5.3.3",
"compression-webpack-plugin": "^10.0.0",
"esbuild-loader": "^3.0.1",
"prettier": "^2.8.8",
"ts-loader": "^9.4.2",
@@ -1366,6 +1367,45 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dev": true,
"dependencies": {
"ajv": "^8.0.0"
},
"peerDependencies": {
"ajv": "^8.0.0"
},
"peerDependenciesMeta": {
"ajv": {
"optional": true
}
}
},
"node_modules/ajv-formats/node_modules/ajv": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
@@ -1552,6 +1592,79 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"node_modules/compression-webpack-plugin": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-10.0.0.tgz",
"integrity": "sha512-wLXLIBwpul/ALcm7Aj+69X0pYT3BYt6DdPn3qrgBIh9YejV9Bju9ShhlAsjujLyWMo6SAweFIWaUoFmXZNuNrg==",
"dev": true,
"dependencies": {
"schema-utils": "^4.0.0",
"serialize-javascript": "^6.0.0"
},
"engines": {
"node": ">= 14.15.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^5.1.0"
}
},
"node_modules/compression-webpack-plugin/node_modules/ajv": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/compression-webpack-plugin/node_modules/ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.3"
},
"peerDependencies": {
"ajv": "^8.8.2"
}
},
"node_modules/compression-webpack-plugin/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/compression-webpack-plugin/node_modules/schema-utils": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
"integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.9.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.1.0"
},
"engines": {
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
@@ -2498,6 +2611,15 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/resolve": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
@@ -3997,6 +4119,35 @@
"uri-js": "^4.2.2"
}
},
"ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dev": true,
"requires": {
"ajv": "^8.0.0"
},
"dependencies": {
"ajv": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
}
},
"json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
}
}
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
@@ -4123,6 +4274,57 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"compression-webpack-plugin": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-10.0.0.tgz",
"integrity": "sha512-wLXLIBwpul/ALcm7Aj+69X0pYT3BYt6DdPn3qrgBIh9YejV9Bju9ShhlAsjujLyWMo6SAweFIWaUoFmXZNuNrg==",
"dev": true,
"requires": {
"schema-utils": "^4.0.0",
"serialize-javascript": "^6.0.0"
},
"dependencies": {
"ajv": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
}
},
"ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.3"
}
},
"json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"schema-utils": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
"integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.9.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.1.0"
}
}
}
},
"convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
@@ -4829,6 +5031,12 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true
},
"resolve": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
+3 -2
View File
@@ -14,6 +14,7 @@
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.1",
"@types/react-router-dom": "^5.3.3",
"compression-webpack-plugin": "^10.0.0",
"esbuild-loader": "^3.0.1",
"prettier": "^2.8.8",
"ts-loader": "^9.4.2",
@@ -30,11 +31,11 @@
"@sqlite.org/sqlite-wasm": "^3.41.2-build11",
"module-workers-polyfill": "^0.3.2",
"notistack": "^3.0.1",
"optuna": "../rustlib/pkg",
"plotly.js-dist-min": "^2.22.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.11.0",
"recoil": "^0.7.7",
"optuna": "../rustlib/pkg"
"recoil": "^0.7.7"
}
}
+5 -1
View File
@@ -3,6 +3,10 @@ const path = require('path');
const mode = process.env.NODE_ENV === 'production' ? 'production' : 'development';
const isDev = mode === 'development';
const PUBLIC_PATH = process.env.PUBLIC_PATH ?? '/public/';
if (!PUBLIC_PATH.endsWith('/')) {
PUBLIC_PATH += '/';
}
const typeScriptLoader = process.env.TYPESCRIPT_LOADER === "esbuild-loader" ? {
test: /\.tsx?$/,
@@ -34,7 +38,7 @@ var config = [
output: {
path: __dirname + '/public/',
filename: 'bundle.js',
publicPath: '/public/'
publicPath: PUBLIC_PATH
},
module: {
rules: [{ oneOf: [typeScriptLoader] }]