diff --git a/packages/ui-default/backendlib/builder.ts b/packages/ui-default/backendlib/builder.ts index 15d328852..cba4b3ce5 100644 --- a/packages/ui-default/backendlib/builder.ts +++ b/packages/ui-default/backendlib/builder.ts @@ -1,7 +1,7 @@ import esbuild from 'esbuild'; import { Context, fs, Handler, Logger, NotFoundError, param, SettingModel, sha1, - size, Types, UiContextBase, + size, SystemModel, Types, UiContextBase, } from 'hydrooj'; import { debounce } from 'lodash'; import { tmpdir } from 'os'; @@ -46,6 +46,7 @@ const build = async (contents: string) => { format: 'iife' as 'iife', bundle: true, outdir: tmp, + sourcemap: SystemModel.get('ui-default.nosourcemap') ? false : 'external', splitting: false, write: false, target: ['chrome65'], @@ -106,7 +107,7 @@ export async function buildUI() { ...entryPoints.map((i) => `import '${relative(tmp, i).replace(/\\/g, '\\\\')}';`), ].join('\n')); const pages = entry.outputFiles.map((i) => i.text); - const str = `window.LANGS=${JSON.stringify(SettingModel.langs)};${pages.join('\n')}`; + const str = `window.LANGS=${JSON.stringify(SettingModel.langs)};window._hydroLoad=()=>{ ${pages.join('\n')} };`; addFile('entry.js', str); UiContextBase.constantVersion = hashes['entry.js']; for (const key in vfs) { diff --git a/packages/ui-default/build/config/webpack.ts b/packages/ui-default/build/config/webpack.ts index 7e19e3ec4..e070e1891 100644 --- a/packages/ui-default/build/config/webpack.ts +++ b/packages/ui-default/build/config/webpack.ts @@ -2,18 +2,43 @@ import { sentryWebpackPlugin } from '@sentry/webpack-plugin'; import { CleanWebpackPlugin } from 'clean-webpack-plugin'; import CopyWebpackPlugin from 'copy-webpack-plugin'; +import { version as coreJsVersion } from 'core-js/package.json'; +import compat from 'core-js-compat'; import { EsbuildPlugin } from 'esbuild-loader'; +import fs from 'fs'; import { DuplicatesPlugin } from 'inspectpack/plugin'; import ExtractCssPlugin from 'mini-css-extract-plugin'; import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin'; +import packageJson from 'package-json'; import { dirname } from 'path'; +import { gt } from 'semver'; import webpack from 'webpack'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import { WebpackManifestPlugin } from 'webpack-manifest-plugin'; import WebpackBar from 'webpackbar'; +import { version } from '../../package.json'; import root from '../utils/root'; -export default function (env: { watch?: boolean, production?: boolean, measure?: boolean } = {}) { +const { + list, + targets, +} = compat({ + targets: '> 0.5%, chrome 80', + modules: [ + 'core-js/stable', + ], + exclude: [], + version: coreJsVersion, + inverse: false, +}); +fs.writeFileSync(root('__core-js.js'), list.map((i) => `import 'core-js/modules/${i}';`).join('\n')); + +export default async function (env: { watch?: boolean, production?: boolean, measure?: boolean } = {}) { + if (env.production) console.log(targets); + let isNew = false; + const { version: latest } = await packageJson('@hydrooj/ui-default', { version: 'latest' }); + if (typeof version === 'string' && gt(version, latest)) isNew = true; + function esbuildLoader() { return { loader: 'esbuild-loader', @@ -73,8 +98,7 @@ export default function (env: { watch?: boolean, production?: boolean, measure?: // sentry requires source-map while keep it simple in dev mode devtool: env.production ? 'source-map' : false, entry: { - hydro: './entry.js', - polyfill: './polyfill.ts', + [`hydro-${version}`]: './entry.js', 'default.theme': './theme/default.js', 'service-worker': './service-worker.ts', }, @@ -262,6 +286,12 @@ export default function (env: { watch?: boolean, production?: boolean, measure?: org: 'hydro-dev', project: 'hydro-web', url: 'https://sentry.hydro.ac', + sourcemaps: { + rewriteSources: (source) => source.replace('@hydrooj/ui-default/../../node_modules/', ''), + }, + release: { + uploadLegacySourcemaps: (process.env.CI && isNew) ? root('public') : undefined, + }, }), new webpack.DefinePlugin({ 'process.env.VERSION': JSON.stringify(require('@hydrooj/ui-default/package.json').version), @@ -271,6 +301,7 @@ export default function (env: { watch?: boolean, production?: boolean, measure?: }), new webpack.NormalModuleReplacementPlugin(/\/(vscode-)?nls\.js/, require.resolve('../../components/monaco/nls')), new webpack.NormalModuleReplacementPlugin(/^prettier[$/]/, root('../../modules/nop.ts')), + new webpack.NormalModuleReplacementPlugin(/core-js\/stable/, root('__core-js.js')), new MonacoWebpackPlugin({ filename: '[name].[hash:6].worker.js', customLanguages: [{ diff --git a/packages/ui-default/build/main.ts b/packages/ui-default/build/main.ts index 646cdc45e..cfc9d4dba 100644 --- a/packages/ui-default/build/main.ts +++ b/packages/ui-default/build/main.ts @@ -19,7 +19,7 @@ const argv = cac().parse(); async function runWebpack({ watch, production, measure, dev, https, }) { - const compiler = webpack(webpackConfig({ watch, production, measure })); + const compiler = webpack(await webpackConfig({ watch, production, measure })); if (dev) { const server = new WebpackDevServer({ port: https ? 8001 : 8000, @@ -124,12 +124,6 @@ async function main() { if (argv.options.gulp) await runGulp(); else { await runWebpack(argv.options as any); - if (fs.existsSync('public/hydro.js')) { - fs.copyFileSync('public/hydro.js', `public/hydro-${pkg.version}.js`); - } - if (fs.existsSync('public/polyfill.js')) { - fs.copyFileSync('public/polyfill.js', `public/polyfill-${pkg.version}.js`); - } if (fs.existsSync('public/theme.css')) { fs.copyFileSync('public/theme.css', `public/theme-${pkg.version}.css`); } @@ -137,8 +131,6 @@ async function main() { for (const f of ['echarts', 'graphviz', 'mermaid', 'mathjax']) { fs.removeSync(`public/vditor/dist/js/${f}`); } - const files = fs.readdirSync('public'); - files.filter((i) => /(^[in]\..+|worker)\.js\.map$/.test(i)).forEach((i) => fs.removeSync(`public/${i}`)); } await Promise.all(globbySync('public/**/*.map').map((i) => fs.remove(i))); } diff --git a/packages/ui-default/entry.js b/packages/ui-default/entry.js index ae344f2d9..c13f762bb 100644 --- a/packages/ui-default/entry.js +++ b/packages/ui-default/entry.js @@ -1,3 +1,5 @@ +import './polyfill'; + import * as Sentry from '@sentry/browser'; import $ from 'jquery'; @@ -57,16 +59,10 @@ const PageLoader = '