ui: use vite

This commit is contained in:
undefined committed 2024-06-05 10:38:00 +08:00
1 parent 3a26cfbfe3
commit 54d440710b
15 files changed
+588 -31

No files matched your search

+270 -2
View File
@@ -1,10 +1,278 @@
// This file is imported in all stylus source code
base-font-size ?= 16px
rasterise-media-queries ?= false
rupture = {
rasterise-media-queries: rasterise-media-queries
mobile-cutoff: 400px
desktop-cutoff: 1050px
hd-cutoff: 1800px
enable-em-breakpoints: false
base-font-size: base-font-size
anti-overlap: false
density-queries: 'dppx' 'webkit' 'moz' 'dpi'
retina-density: 1.5
use-device-width: false
}
rupture.scale = 0 (rupture.mobile-cutoff) 600px 800px (rupture.desktop-cutoff) (rupture.hd-cutoff)
rupture.scale-names = 'xs' 's' 'm' 'l' 'xl' 'hd'
-is-string(val)
if typeof(val) is not 'unit'
if val is a 'string' or val is a 'ident'
true
else
false
else
false
-get-scale-number(scale-name)
for list-item, i in rupture.scale-names
if list-item is scale-name
return i + 1
return false
-convert-to(to-unit, value, context = rupture.base-font-size)
from-unit = unit(value)
return value if to-unit is from-unit
if to-unit in ('em' 'rem')
return value if from-unit in ('em' 'rem')
return unit((value / context), to-unit)
if to-unit is 'px'
return unit((value * context), 'px')
-on-scale(n)
return unit(n) is ''
-larger-than-scale(n)
return (n > (length(rupture.scale) - 1)) and -on-scale(n)
-is-zero(n)
return n is 0
-overlap-shift(anti-overlap, n)
shift-unit = unit(n)
anti-overlap = 0px unless anti-overlap
anti-overlap = 1px if anti-overlap is true
if length(anti-overlap) is 1
return -convert-to(shift-unit, anti-overlap)
for val in anti-overlap
return val if unit(val) is shift-unit
-adjust-overlap(anti-overlap, n, side = 'min')
-shift = -overlap-shift(anti-overlap, n)
if (side is 'min' and -shift > 0) or (side is 'max' and -shift < 0)
n = n + -shift
return n
-is-positive(n)
return n >= 0
-density-queries(density)
if typeof(density) is not 'unit'
if not -is-string(density)
density = '%s' % density
density = rupture.retina-density if density is 'retina'
queries = ()
for query in rupture.density-queries
if query is 'webkit'
push(queries, '(-webkit-min-device-pixel-ratio: %s)' % (density))
else if query is 'moz'
push(queries, '(min--moz-device-pixel-ratio: %s)' % (density))
else if query is 'o'
push(queries, '(-o-min-device-pixel-ratio: %s/1)' % (density))
else if query is 'ratio'
push(queries, '(min-device-pixel-ratio: %s)' % (density))
else if query is 'dpi'
if -is-string(density)
density=convert(density)
push(queries, '(min-resolution: %sdpi)' % (round(density * 96, 1)))
else if query is 'dppx'
push(queries, '(min-resolution: %sdppx)' % (density))
return queries
create-fallback-class(selected, class)
/{'' + class + ' ' + selected}
{block}
// +between(min, max)
// usage (scale can be mixed with custom values):
// - +between(1, 3) scale:scale
// - +between(0, 3) 0 width:scale
// - +between(200px, 500px) custom:custom
// - +between(0, 300px) 0 width:custom
// - +between(1, 300px) scale:custom
// - +between(200px, 4) custom:scale
between(min, max, anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
selected = selector()
if -is-string(orientation)
orientation = convert(orientation)
if -is-string(density)
density = convert(density)
if -is-string(min)
min = -get-scale-number(min)
if -is-string(max)
max = -get-scale-number(max)
-min = rupture.scale[min - 1] unless -is-zero(min) or (not -on-scale(min))
-max = rupture.scale[max] unless not -on-scale(max)
-min ?= min
-max ?= max
if (rupture.rasterise-media-queries)
if not (density or -max or orientation)
{block}
else
condition = 'only screen'
use-device-width = use-device-width ? 'device-' : ''
unless -min is 0
-min = -convert-to('em', -min) if rupture.enable-em-breakpoints
-min = -adjust-overlap(anti-overlap, -min, side: 'min')
condition = condition + ' and (min-' + use-device-width + 'width: %s)' % (-min)
unless -larger-than-scale(max)
-max = -convert-to('em', -max) if rupture.enable-em-breakpoints
-max = -adjust-overlap(anti-overlap, -max, side: 'max')
condition = condition + ' and (max-' + use-device-width + 'width: %s)' % (-max)
if orientation
condition = condition + ' and (orientation: %s)' % (orientation)
if density
conditions = ()
for query in -density-queries(density)
push(conditions, condition + ' and %s' % (query))
condition = join(', ', conditions)
@media condition
{block}
if fallback-class
+create-fallback-class(selected, fallback-class)
{block}
at(scale-point, anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
if -is-string(orientation)
orientation = convert(orientation)
if -is-string(density)
density = convert(density)
+between(scale-point, scale-point, anti-overlap, density, orientation, use-device-width, fallback-class)
{block}
from-width(scale-point, anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
if -is-string(orientation)
orientation = convert(orientation)
if -is-string(density)
density = convert(density)
+between(scale-point, length(rupture.scale), anti-overlap, density, orientation, use-device-width, fallback-class)
{block}
above = from-width
to-width(scale-point, anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
if -is-string(orientation)
orientation = convert(orientation)
if -is-string(density)
density = convert(density)
+between(1, scale-point, anti-overlap, density, orientation, use-device-width, fallback-class)
{block}
below = to-width
mobile(anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
if -is-string(orientation)
orientation = convert(orientation)
if -is-string(density)
density = convert(density)
+below(rupture.mobile-cutoff, anti-overlap, density, orientation, use-device-width, fallback-class)
{block}
tablet(anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
if -is-string(orientation)
orientation = convert(orientation)
if -is-string(density)
density = convert(density)
+between(rupture.mobile-cutoff, rupture.desktop-cutoff, anti-overlap, density, orientation, use-device-width, fallback-class)
{block}
desktop(anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
if -is-string(orientation)
orientation = convert(orientation)
if -is-string(density)
density = convert(density)
+above(rupture.desktop-cutoff, anti-overlap, density, orientation, use-device-width, fallback-class)
{block}
hd(anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
if -is-string(orientation)
orientation = convert(orientation)
if -is-string(density)
density = convert(density)
+above(rupture.hd-cutoff, anti-overlap, density, orientation, use-device-width, fallback-class)
{block}
density(density, orientation = null, fallback-class = null)
selected = selector()
if not (rupture.rasterise-media-queries)
conditions = ()
for query in -density-queries(density)
condition = 'only screen and %s' % (query)
if orientation
condition = condition + ' and (orientation: %s)' % (orientation)
push(conditions, condition)
condition = join(', ', conditions)
@media condition
{block}
if fallback-class
+create-fallback-class(selected, fallback-class)
{block}
pixel-ratio = density
retina(orientation = null, fallback-class = null)
+density('retina', orientation, fallback-class)
{block}
landscape(density = null, fallback-class = null)
selected = selector()
if not (rupture.rasterise-media-queries)
if -is-string(density)
density = convert(density)
if density
+pixel-ratio(density, orientation: landscape, fallback-class)
{block}
else
@media only screen and (orientation: landscape)
{block}
if fallback-class
+create-fallback-class(selected, fallback-class)
{block}
portrait(density = null, fallback-class = null)
selected = selector()
if not (rupture.rasterise-media-queries)
if -is-string(density)
density = convert(density)
if density
+pixel-ratio(density, orientation: portrait, fallback-class)
{block}
else
@media only screen and (orientation: portrait)
{block}
if fallback-class
+create-fallback-class(selected, fallback-class)
{block}
rupture-hover(density = null, orientation = null, fallback-class = null)
condition = "only screen and (hover: hover)";
@media ({condition})
{block}
hover = rupture-hover
breakpoints = json('../breakpoints.json', { hash: true })
rupture.mobile-cutoff = unit(breakpoints.mobile, 'px')
rupture.desktop-cutoff = unit(breakpoints.desktop, 'px')
rupture.hd-cutoff = unit(breakpoints.hd, 'px')
@import '~vj/misc/.iconfont/webicon.inc.styl'
@import '../misc/.iconfont/webicon.inc.styl'
@import 'color.inc.styl'
@import 'variables.inc.styl'
@import 'easing.inc.styl'
@@ -13,14 +13,14 @@ import getLoader from 'prismjs/dependencies';
import Notification from 'vj/components/notification/index';
import { i18n } from 'vj/utils';
import languageMeta from './meta';
import langs from 'prismjs/components/index';
const files = require.context('prismjs/components/', true, /prism-[a-z0-9-]+\.js/);
const loadedLanguages = new Set();
function loadLanguages() {
const languages = Object.keys(components.languages).filter((l) => l !== 'meta');
const loaded = [...loadedLanguages, ...Object.keys(Prism.languages)];
getLoader(components, languages, loaded).load((lang) => {
files(`./prism-${lang}.js`);
langs[lang]?.();
loadedLanguages.add(lang);
});
}
@@ -61,7 +61,7 @@ const onmessage = (msg) => {
const initWorkerMode = (endpoint) => {
console.log('Messages: using SharedWorker');
const worker = new SharedWorker('/messages-shared-worker.js', { name: 'HydroMessagesWorker' });
const worker = new SharedWorker(new URL('./worker.ts?worker', import.meta.url), { name: 'HydroMessagesWorker' });
worker.port.start();
window.addEventListener('beforeunload', () => {
worker.port.postMessage({ type: 'unload' });
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
import React from 'react';
export default function DataInputComponent(props) {
const {
@@ -1,5 +1,6 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
export default function ToolbarComponent(props) {
const {
@@ -1,19 +1,21 @@
import $ from 'jquery';
import * as timeago from 'timeago.js';
import en_US from 'timeago.js/lib/lang/en_US';
import ko from 'timeago.js/lib/lang/ko';
import zh_CN from 'timeago.js/lib/lang/zh_CN';
import zh_TW from 'timeago.js/lib/lang/zh_TW';
import { AutoloadPage } from 'vj/misc/Page';
import { i18n } from 'vj/utils';
try {
const locales = require.context('timeago.js/lib/lang', false, /\.js$/);
let locale;
try {
locale = locales(`./${i18n('timeago_locale')}.js`).default;
} catch (e) {
locale = locales('./en_US.js').default;
}
const locales = {
// eslint-disable-next-line @typescript-eslint/naming-convention
zh_CN, zh_TW, ko, en_US,
};
const locale = locales[i18n('timeago_locale')] || locales.en_US;
timeago.register(i18n('timeago_locale'), locale);
} catch (e) {
console.error(`Cannot register timeago locale: ${i18n('timeago_locale')}`);
console.error(`Cannot register timeago locale: ${i18n('timeago_locale')}`, e);
}
function runRelativeTime($container) {
$container.find('span.time.relative[data-timestamp]').get().forEach((element) => {
@@ -7,6 +7,7 @@ window.Hydro = {
node_modules: {},
version: process.env.VERSION,
};
window.jQuery = $; // sticky-kit require this
window.externalModules = {};
window.lazyModuleResolver = {};
@@ -30,7 +31,11 @@ window.UserContext = JSON.parse(window.UserContext);
try { __webpack_public_path__ = UiContext.cdn_prefix; } catch (e) { }
if ('serviceWorker' in navigator) {
const encodedConfig = encodeURIComponent(JSON.stringify(UiContext.SWConfig));
navigator.serviceWorker.register(`/service-worker.js?config=${encodedConfig}`).then((registration) => {
const dev = process.env.NODE_ENV === 'development';
navigator.serviceWorker.register(
dev ? '/dev-sw.js?dev-sw' : `/sw.js?config=${encodedConfig}`,
{ scope: '/', type: dev ? 'module' : 'classic' },
).then((registration) => {
console.log('SW registered: ', registration);
}).catch((registrationError) => {
console.log('SW registration failed: ', registrationError);
+1
View File
@@ -82,6 +82,7 @@ export async function initPageLoader() {
Notification.warn(`Failed to call '${type}Loading' of ${page.name}`);
console.error(`Failed to call '${type}Loading' of ${page.name}\n${e.stack}`);
console.error(e);
console.info(func.toString());
}
if (process.env.NODE_ENV !== 'production') {
console.time(`${page.name}: ${type}Loading`);
+2 -4
View File
@@ -1,12 +1,10 @@
import pages from '../__glob_page';
import { Page } from './Page';
export default class PageLoader {
constructor() {
const pages = require.context('../pages/', true, /\.page\.[jt]sx?$/i);
const components = require.context('../components/', true, /\.page\.[jt]sx?$/i);
this.pageInstances = [
...pages.keys().map((key) => pages(key)),
...components.keys().map((key) => components(key)),
...pages,
...window.Hydro.extraPages,
].map((page) => {
page = page?.default || page;
+6
View File
@@ -15,6 +15,7 @@
},
"devDependencies": {
"@blueprintjs/core": "^5.10.3",
"@codingame/esbuild-import-meta-url-plugin": "^1.0.2",
"@fontsource/dm-mono": "^5.0.20",
"@fontsource/fira-code": "^5.0.18",
"@fontsource/inconsolata": "^5.0.18",
@@ -24,6 +25,7 @@
"@fontsource/source-code-pro": "^5.0.18",
"@fontsource/ubuntu-mono": "^5.0.20",
"@hydrooj/utils": "workspace:^",
"@rollup/plugin-inject": "^5.0.5",
"@simplewebauthn/browser": "7.4.0",
"@svgr/webpack": "^8.1.0",
"@types/gulp-if": "^0.0.34",
@@ -117,6 +119,10 @@
"ts-loader": "^9.5.1",
"vditor": "^3.10.4",
"vinyl-buffer": "^1.0.1",
"vite": "^5.2.12",
"vite-plugin-pwa": "^0.20.0",
"vite-plugin-static-copy": "^1.0.5",
"vite-plugin-svgr": "^4.2.0",
"web-streams-polyfill": "^4.0.0",
"webpack": "^5.91.0",
"webpack-bundle-analyzer": "^4.10.2",
@@ -1,4 +1,4 @@
@import '~vj/components/tab/var.inc.styl'
@import '../components/tab/var.inc.styl'
.page--user_detail
+15 -4
View File
@@ -4,6 +4,16 @@
export { }; // make it a module so that declare self works
declare const self: ServiceWorkerGlobalScope;
let dev = false;
let version = 'dev';
try {
dev = process.env.NODE_ENV !== 'production';
version = process.env.VERSION;
} catch (e) {
// process doesnt exist
dev = location.search.includes('dev-sw');
}
const map = new Map();
function createStream(port) {
@@ -88,13 +98,13 @@ self.addEventListener('notificationclick', (event) => {
}));
});
const PRECACHE = `precache-${process.env.VERSION}`;
const PRECACHE = `precache-${version}`;
const DO_NOT_PRECACHE = ['vditor', '.worker.js', 'fonts', 'i.monaco'];
function shouldCachePath(path: string) {
if (!path.split('?')[0].split('/').pop()) return false;
if (!path.split('?')[0].split('/').pop().includes('.')) return false;
if (process.env.NODE_ENV !== 'production' && (path.includes('.hot-update.') || path.includes('?version='))) return false;
if (dev && (path.includes('.hot-update.') || path.includes('?version='))) return false;
return true;
}
function shouldCache(request: Request) {
@@ -119,7 +129,7 @@ interface ServiceWorkerConfig {
let config: ServiceWorkerConfig = null;
function initConfig() {
config = JSON.parse(new URLSearchParams(location.search).get('config'));
config = JSON.parse(new URLSearchParams(location.search).get('config')) || {};
config.hosts ||= [];
if (!config.domains?.length) config.domains = [location.host];
console.log('Config:', config);
@@ -127,7 +137,7 @@ function initConfig() {
self.addEventListener('install', (event) => event.waitUntil((async () => {
initConfig();
if (process.env.NODE_ENV === 'production' && config?.preload) {
if (!dev && config?.preload) {
const [cache, manifest] = await Promise.all([
caches.open(PRECACHE),
fetch('/manifest.json').then((res) => res.json()),
@@ -193,6 +203,7 @@ async function cachedRespond(request: Request) {
caches.open(PRECACHE),
get(request),
]);
if (response.headers.get('Cache-Control') === 'no-cache') return response;
if (response.ok) {
cache.put(url, response.clone());
return response;
@@ -37,8 +37,7 @@
{% endif %}
</style>
{% if process.env.DEV %}
<script src="/default.theme.js?version={{ global.Hydro.version['ui-default'] }}"></script>
<link rel="stylesheet" media="all" href="/theme.css?version={{ global.Hydro.version['ui-default'] }}">
<script src="/theme/default.js?version={{ global.Hydro.version['ui-default'] }}" type="module"></script>
{% else %}
<link rel="stylesheet" media="all" href="{{ UiContext.cdn_prefix }}theme-{{ global.Hydro.version['ui-default'] }}.css">
{% endif %}
@@ -67,7 +66,7 @@
{% set UserContext = Object.create(UserContext) %}
{% if process.env.DEV %}
<script type="text/javascript" src="/resource/hash/lang-{{ _('__id') }}.js?version={{ global.Hydro.version['ui-default'] }}"></script>
<script type="text/javascript" src="/hydro.js?version={{ global.Hydro.version['ui-default'] }}"></script>
<script type="module" src="/entry.jsx?version={{ global.Hydro.version['ui-default'] }}"></script>
{% else %}
<script type="text/javascript" src="{{ UiContext.cdn_prefix }}resource/{{ global.Hydro.version['ui-default'] }}/lang-{{ _('__id') }}.js"></script>
<script type="text/javascript" src="{{ UiContext.cdn_prefix }}hydro-{{ global.Hydro.version['ui-default'] }}.js"></script>
+2 -5
View File
@@ -27,9 +27,6 @@ import 'vj/misc/nothing.styl';
import 'vj/components/editor/cmeditor.styl';
import 'vj/components/datepicker/datepicker.styl';
import './dark.styl';
// load all page stylesheets
const pageStyleReq = require.context('../', true, /\.page\.styl$/i);
pageStyleReq.keys().map((key) => pageStyleReq(key));
const pageStyleReqDefault = require.context('../', true, /\.page\.default\.styl$/i);
pageStyleReqDefault.keys().map((key) => pageStyleReqDefault(key));
import '../__glob_page.styl';
import '../__glob_default.styl';
+268
View File
@@ -0,0 +1,268 @@
import importMetaUrlPlugin from '@codingame/esbuild-import-meta-url-plugin';
import inject from '@rollup/plugin-inject';
import fs from 'fs';
import { globbySync } from 'globby';
import httpProxy from 'http-proxy';
import path from 'path';
import colors from 'picocolors';
// import federation from '@originjs/vite-plugin-federation';
import { defineConfig } from 'vite';
import { VitePWA } from 'vite-plugin-pwa';
import { viteStaticCopy } from 'vite-plugin-static-copy';
import svgr from 'vite-plugin-svgr';
import { version } from './package.json';
const proxy = httpProxy.createProxyServer({
ws: true,
target: 'http://localhost:2333',
});
const setOriginHeader = (proxyReq, options) => {
if (options.changeOrigin) {
const { target } = options;
if (proxyReq.getHeader('origin') && target) {
const changedOrigin = typeof target === 'object'
? `${target.protocol}//${target.host}`
: target;
proxyReq.setHeader('origin', changedOrigin);
}
}
};
proxy.on('error', (err, req, originalRes) => {
const res = originalRes;
if (!res) {
console.error(
`${colors.red(`http proxy error: ${err.message}`)}\n${err.stack}`,
{
timestamp: true,
error: err,
},
);
} else if ('req' in res) {
console.error(
`${colors.red(`http proxy error: ${originalRes.req.url}`)}\n${err.stack
}`,
{
timestamp: true,
error: err,
},
);
if (!res.headersSent && !res.writableEnded) {
res
.writeHead(500, {
'Content-Type': 'text/plain',
})
.end();
}
} else {
console.error(`${colors.red('ws proxy error:')}\n${err.stack}`, {
timestamp: true,
error: err,
});
res.end();
}
});
proxy.on('proxyReq', (proxyReq, req, res, options) => {
setOriginHeader(proxyReq, options);
});
proxy.on('proxyReqWs', (proxyReq, req, socket, options) => {
setOriginHeader(proxyReq, options);
socket.on('error', (err) => {
console.error(
`${colors.red('ws proxy socket error:')}\n${err.stack}`,
{
timestamp: true,
error: err,
},
);
});
});
proxy.on('proxyRes', (proxyRes, req, res) => {
res.on('close', () => {
if (!res.writableEnded) {
proxyRes.destroy();
}
});
});
function getGlobStyle(glob = '**/*.page.styl') {
const files = globbySync(glob, { cwd: __dirname, ignore: ['node_modules'] });
const result = [];
for (const file of files) {
const content = fs.readFileSync(path.join(__dirname, file), 'utf-8');
if (content.includes('@import \'.')) {
result.push(`@import ${JSON.stringify(file)}`);
} else {
result.push(content);
}
}
return `${result.filter((i) => i.startsWith('@import')).join('\n')}
${result.filter((i) => !i.startsWith('@import')).join('\n')}`;
}
function updateGlobStyle(glob, filename) {
const file = path.join(__dirname, filename);
const content = getGlobStyle(glob);
if (!fs.existsSync(file) || fs.readFileSync(file, 'utf-8') !== content) {
fs.writeFileSync(file, content);
}
}
updateGlobStyle('**/*.page.styl', '__glob_page.styl');
updateGlobStyle('**/*.page.default.styl', '__glob_default.styl');
function getGlobPage(glob = '**/*.page.[jt]sx?') {
const files = globbySync(glob, { cwd: __dirname, ignore: ['node_modules'] });
const result = [];
const exps = [];
for (const file of files) {
result.push(`import ${file.replace(/[/\\.-]/g, '_')} from "${file.startsWith('/') ? file : `./${file}`}";`);
exps.push(file.replace(/[/\\.-]/g, '_'));
}
result.push(`export default [${exps.join(',')}]`);
return result.join('\n');
}
function updateGlobPage(glob, filename) {
const file = path.join(__dirname, filename);
const content = getGlobPage(glob);
if (!fs.existsSync(file) || fs.readFileSync(file, 'utf-8') !== content) {
fs.writeFileSync(file, content);
}
}
updateGlobPage(['**/*.page.js', '**/*.page.ts', '**/*.page.jsx', '**/*.page.tsx'], '__glob_page.js');
function patchPrism() {
const langs = globbySync('prism-*.js', { cwd: import.meta.resolve('prismjs/components').split(':')[1], ignore: ['node_modules'] });
const lines = langs.filter((i) => !i.endsWith('.min.js')).map((i) => {
const name = i.split('prism-')[1].split('.')[0];
return `'${name}': () => require('./${i}'),`;
});
const loader = `export default {
${lines.join('\n')}
}`;
fs.writeFileSync(import.meta.resolve('prismjs/components/index.js').split(':')[1], loader);
}
patchPrism();
export default defineConfig({
root: __dirname,
esbuild: {
jsx: 'transform',
loader: 'tsx',
},
publicDir: 'static',
build: {
minify: process.env.NODE_NEV === 'production',
outDir: 'public',
rollupOptions: {
input: './entry.jsx',
output: {
globals: {
jQuery: 'jQuery',
},
},
},
},
resolve: {
dedupe: ['monaco-editor', 'vscode'],
alias: {
vj: __dirname,
},
},
define: {
'process.env.VERSION': JSON.stringify(version),
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
...(process.env.NODE_ENV === 'development' ? { 'process.cwd': '()=>null' } : {}),
},
optimizeDeps: {
include: ['jquery'],
esbuildOptions: {
plugins: [importMetaUrlPlugin],
},
},
css: {
preprocessorOptions: {
styl: {
use: [],
imports: [
// import.meta.resolve('rupture/rupture/index.styl'),
path.join(__dirname, 'common/common.inc.styl'),
],
},
},
},
server: {
host: true,
port: 8000,
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
proxy: {
},
},
worker: {
format: 'es',
},
plugins: [
inject({
$: 'jquery',
React: 'react',
include: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
}),
svgr({}),
viteStaticCopy({
targets: [
{ src: 'components/navigation/nav-logo-small_dark.png', dest: 'components/navigation/nav-logo-small_dark.png' },
{ src: import.meta.resolve('streamsaver/mitm.html'), dest: 'streamsaver/mitm.html' },
{ src: import.meta.resolve('streamsaver/sw.js'), dest: 'streamsaver/sw.js' },
{ src: import.meta.resolve('vditor/dist'), dest: 'vditor/dist' },
// { from: root(`${dirname(require.resolve('graphiql/package.json'))}/graphiql.min.css`), to: 'graphiql.min.css' },
// { from: `${dirname(require.resolve('monaco-themes/package.json'))}/themes`, to: 'monaco/themes/' },
],
}),
VitePWA({
injectRegister: null,
registerType: 'autoUpdate',
strategies: 'injectManifest',
srcDir: '.',
filename: 'service-worker.ts',
injectManifest: {
injectionPoint: undefined,
},
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg}'],
},
devOptions: {
enabled: true,
type: 'module',
},
}),
{
name: 'configure-server',
watchChange(id) {
if (id.endsWith('.styl') && !id.includes('/__')) {
console.log('change', id);
updateGlobStyle('**/*.page.styl', '__glob_page.styl');
updateGlobStyle('**/*.page.default.styl', '__glob_default.styl');
}
},
configureServer(server) {
server.middlewares.use(async (req, res, next) => {
// console.log(req.url);
const resource = req.url.split('?')[0];
if (['/@fs/', '/@vite/', '/sw.js', '/dev-sw.js', '/vditor'].some((t) => resource.startsWith(t))) next();
else if (resource !== '/' && fs.existsSync(path.join(__dirname, resource.substring(1)))) next();
else {
const options = {};
proxy.web(req, res, options);
}
});
server.httpServer.on('upgrade', (req, socket, head) => {
if (req.url !== '/') {
proxy.ws(req, socket, head);
}
});
},
},
],
});