From 32c0cf28283ac1aa7875fcf2cf23ad366eeacedf Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Fri, 8 Jul 2022 11:30:37 +0800 Subject: [PATCH 01/13] fix: userConfig plugins types (#290) --- packages/types/src/plugin.ts | 2 +- packages/types/src/userConfig.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/types/src/plugin.ts b/packages/types/src/plugin.ts index 7597b23c0..3e490f20d 100644 --- a/packages/types/src/plugin.ts +++ b/packages/types/src/plugin.ts @@ -78,7 +78,7 @@ export interface ExtendsPluginAPI { }; } -interface OverwritePluginAPI extends ExtendsPluginAPI { +export interface OverwritePluginAPI extends ExtendsPluginAPI { onHook: OnHook; } diff --git a/packages/types/src/userConfig.ts b/packages/types/src/userConfig.ts index 6f567f1a7..0e4e52a1e 100644 --- a/packages/types/src/userConfig.ts +++ b/packages/types/src/userConfig.ts @@ -1,6 +1,7 @@ import type { DefineRouteFunction } from '@ice/route-manifest'; import type { PluginList } from 'build-scripts'; import type { Config, ModifyWebpackConfig } from './config'; +import type { OverwritePluginAPI } from './plugin'; export interface UserConfig { alias?: Record; @@ -17,7 +18,7 @@ export interface UserConfig { ignoreFiles?: string[]; defineRoutes?: (defineRoute: DefineRouteFunction) => void; }; - plugins?: PluginList; + plugins?: PluginList; dropLogLevel?: 'trace' | 'debug' | 'log' | 'info' | 'warn' | 'error'; minify?: boolean; compileDependencies?: boolean | string[] | RegExp[]; From e96c87a4a2d715ea8ed1ee5d75682472012df735 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Fri, 8 Jul 2022 11:30:50 +0800 Subject: [PATCH 02/13] feat: support global style (#237) * feat: support global style * fix: global style path * feat: watch global style * fix: comment --- examples/basic-project/src/global.css | 3 +++ packages/ice/package.json | 2 +- packages/ice/src/createService.ts | 2 +- packages/ice/src/getWatchEvents.ts | 21 +++++++++++++++---- packages/ice/src/service/runtimeGenerator.ts | 6 +++--- .../src/utils/getGlobalStyleGlobPattern.ts | 3 +++ packages/ice/{template => templates}/404.tsx | 0 .../data-loader.ts.ejs | 0 .../entry.client.ts.ejs | 0 .../entry.server.ts.ejs | 0 .../{template => templates}/env.server.ts.ejs | 0 .../ice/{template => templates}/index.ts.ejs | 3 +++ .../route-manifest.json.ejs | 0 .../routes-config.ts.ejs | 0 .../ice/{template => templates}/routes.ts.ejs | 0 .../runtimeModules.ts.ejs | 0 .../ice/{template => templates}/types.ts.ejs | 0 17 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 examples/basic-project/src/global.css create mode 100644 packages/ice/src/utils/getGlobalStyleGlobPattern.ts rename packages/ice/{template => templates}/404.tsx (100%) rename packages/ice/{template => templates}/data-loader.ts.ejs (100%) rename packages/ice/{template => templates}/entry.client.ts.ejs (100%) rename packages/ice/{template => templates}/entry.server.ts.ejs (100%) rename packages/ice/{template => templates}/env.server.ts.ejs (100%) rename packages/ice/{template => templates}/index.ts.ejs (95%) rename packages/ice/{template => templates}/route-manifest.json.ejs (100%) rename packages/ice/{template => templates}/routes-config.ts.ejs (100%) rename packages/ice/{template => templates}/routes.ts.ejs (100%) rename packages/ice/{template => templates}/runtimeModules.ts.ejs (100%) rename packages/ice/{template => templates}/types.ts.ejs (100%) diff --git a/examples/basic-project/src/global.css b/examples/basic-project/src/global.css new file mode 100644 index 000000000..604282adc --- /dev/null +++ b/examples/basic-project/src/global.css @@ -0,0 +1,3 @@ +body { + font-size: 14px; +} diff --git a/packages/ice/package.json b/packages/ice/package.json index 4b1a99010..4c5185a6d 100644 --- a/packages/ice/package.json +++ b/packages/ice/package.json @@ -11,7 +11,7 @@ "files": [ "bin", "esm", - "template", + "templates", "!esm/**/*.map" ], "engines": { diff --git a/packages/ice/src/createService.ts b/packages/ice/src/createService.ts index 702c2d26f..5b2ffd47d 100644 --- a/packages/ice/src/createService.ts +++ b/packages/ice/src/createService.ts @@ -33,7 +33,7 @@ interface CreateServiceOptions { async function createService({ rootDir, command, commandArgs }: CreateServiceOptions) { const targetDir = '.ice'; - const templateDir = path.join(__dirname, '../template/'); + const templateDir = path.join(__dirname, '../templates/'); const configFile = 'ice.config.(mts|mjs|ts|js|cjs|json)'; const dataCache = new Map(); const generator = new Generator({ diff --git a/packages/ice/src/getWatchEvents.ts b/packages/ice/src/getWatchEvents.ts index 0dcbc0f62..e17f48928 100644 --- a/packages/ice/src/getWatchEvents.ts +++ b/packages/ice/src/getWatchEvents.ts @@ -5,6 +5,7 @@ import type { Context } from 'build-scripts'; import type { Config } from '@ice/types'; import { generateRoutesInfo } from './routes.js'; import type Generator from './service/runtimeGenerator'; +import getGlobalStyleGlobPattern from './utils/getGlobalStyleGlobPattern.js'; interface Options { targetDir: string; @@ -47,11 +48,23 @@ const getWatchEvents = (options: Options): WatchEvent[] => { ]; const watchGlobalStyle: WatchEvent = [ - /src\/global.(scss|less|css)/, + getGlobalStyleGlobPattern(), (event: string, filePath: string) => { - if (event === 'unlink' || event === 'add') { - consola.debug('[event]', `style '${filePath}': ${event}`); - // TODO render global style template + if (event === 'unlink') { + consola.log('[event]', `style '${filePath}': ${event}`); + generator.renderFile( + path.join(templateDir, 'index.ts.ejs'), + path.join(rootDir, targetDir, 'index.ts'), + { globalStyle: undefined }, + ); + } + if (event === 'add') { + consola.log('[event]', `style '${filePath}': ${event}`); + generator.renderFile( + path.join(templateDir, 'index.ts.ejs'), + path.join(rootDir, targetDir, 'index.ts'), + { globalStyle: `@/${path.basename(filePath)}` }, + ); } }, ]; diff --git a/packages/ice/src/service/runtimeGenerator.ts b/packages/ice/src/service/runtimeGenerator.ts index 80d1128dd..e58dca1d9 100644 --- a/packages/ice/src/service/runtimeGenerator.ts +++ b/packages/ice/src/service/runtimeGenerator.ts @@ -23,7 +23,7 @@ import type { Registration, TemplateOptions, } from '@ice/types/esm/generator.js'; -import formatPath from '../utils/formatPath.js'; +import getGlobalStyleGlobPattern from '../utils/getGlobalStyleGlobPattern.js'; const { debounce } = lodash; @@ -175,7 +175,7 @@ export default class Generator { public parseRenderData: ParseRenderData = () => { const staticConfig = fg.sync(['src/manifest.json'], { cwd: this.rootDir }); - const globalStyles = fg.sync(['src/global.@(scss|less|styl|css)'], { cwd: this.rootDir, absolute: true }); + const globalStyles = fg.sync([getGlobalStyleGlobPattern()], { cwd: this.rootDir }); let exportsData = {}; this.contentTypes.forEach(item => { const data = this.getExportStr(item, ['imports', 'exports']); @@ -188,7 +188,7 @@ export default class Generator { ...this.renderData, ...exportsData, staticConfig: staticConfig.length && staticConfig[0], - globalStyle: globalStyles.length && formatPath(path.relative(path.join(this.targetDir, 'core'), globalStyles[0])), + globalStyle: globalStyles.length && `@/${path.basename(globalStyles[0])}`, }; }; diff --git a/packages/ice/src/utils/getGlobalStyleGlobPattern.ts b/packages/ice/src/utils/getGlobalStyleGlobPattern.ts new file mode 100644 index 000000000..54fdfd228 --- /dev/null +++ b/packages/ice/src/utils/getGlobalStyleGlobPattern.ts @@ -0,0 +1,3 @@ +export default function getGlobalStyleGlobPattern() { + return 'src/global.@(css|scss|less)'; +} diff --git a/packages/ice/template/404.tsx b/packages/ice/templates/404.tsx similarity index 100% rename from packages/ice/template/404.tsx rename to packages/ice/templates/404.tsx diff --git a/packages/ice/template/data-loader.ts.ejs b/packages/ice/templates/data-loader.ts.ejs similarity index 100% rename from packages/ice/template/data-loader.ts.ejs rename to packages/ice/templates/data-loader.ts.ejs diff --git a/packages/ice/template/entry.client.ts.ejs b/packages/ice/templates/entry.client.ts.ejs similarity index 100% rename from packages/ice/template/entry.client.ts.ejs rename to packages/ice/templates/entry.client.ts.ejs diff --git a/packages/ice/template/entry.server.ts.ejs b/packages/ice/templates/entry.server.ts.ejs similarity index 100% rename from packages/ice/template/entry.server.ts.ejs rename to packages/ice/templates/entry.server.ts.ejs diff --git a/packages/ice/template/env.server.ts.ejs b/packages/ice/templates/env.server.ts.ejs similarity index 100% rename from packages/ice/template/env.server.ts.ejs rename to packages/ice/templates/env.server.ts.ejs diff --git a/packages/ice/template/index.ts.ejs b/packages/ice/templates/index.ts.ejs similarity index 95% rename from packages/ice/template/index.ts.ejs rename to packages/ice/templates/index.ts.ejs index ccaf16b1a..3f42fbe90 100644 --- a/packages/ice/template/index.ts.ejs +++ b/packages/ice/templates/index.ts.ejs @@ -10,6 +10,9 @@ import { useSearchParamsSingle, useLocationSingle, } from '@ice/runtime'; +<% if (globalStyle) {%> + import '<%= globalStyle %>' +<% } %> let Link: typeof OriginLink; let Outlet: typeof OriginOutlet; diff --git a/packages/ice/template/route-manifest.json.ejs b/packages/ice/templates/route-manifest.json.ejs similarity index 100% rename from packages/ice/template/route-manifest.json.ejs rename to packages/ice/templates/route-manifest.json.ejs diff --git a/packages/ice/template/routes-config.ts.ejs b/packages/ice/templates/routes-config.ts.ejs similarity index 100% rename from packages/ice/template/routes-config.ts.ejs rename to packages/ice/templates/routes-config.ts.ejs diff --git a/packages/ice/template/routes.ts.ejs b/packages/ice/templates/routes.ts.ejs similarity index 100% rename from packages/ice/template/routes.ts.ejs rename to packages/ice/templates/routes.ts.ejs diff --git a/packages/ice/template/runtimeModules.ts.ejs b/packages/ice/templates/runtimeModules.ts.ejs similarity index 100% rename from packages/ice/template/runtimeModules.ts.ejs rename to packages/ice/templates/runtimeModules.ts.ejs diff --git a/packages/ice/template/types.ts.ejs b/packages/ice/templates/types.ts.ejs similarity index 100% rename from packages/ice/template/types.ts.ejs rename to packages/ice/templates/types.ts.ejs From ed147421bb3b9b6d6e6e5cefc969147b3af40ee3 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Fri, 8 Jul 2022 12:24:56 +0800 Subject: [PATCH 03/13] fix: fail to reuse existed tab (#320) * fix: fail to reuse existed tab * chore: move openChrome.applescript to outside --- packages/ice/{src/utils => }/openChrome.applescript | 0 packages/ice/package.json | 3 ++- packages/ice/src/utils/openBrowser.ts | 4 +++- scripts/copyFile.ts | 8 -------- 4 files changed, 5 insertions(+), 10 deletions(-) rename packages/ice/{src/utils => }/openChrome.applescript (100%) delete mode 100644 scripts/copyFile.ts diff --git a/packages/ice/src/utils/openChrome.applescript b/packages/ice/openChrome.applescript similarity index 100% rename from packages/ice/src/utils/openChrome.applescript rename to packages/ice/openChrome.applescript diff --git a/packages/ice/package.json b/packages/ice/package.json index 4c5185a6d..1b271834b 100644 --- a/packages/ice/package.json +++ b/packages/ice/package.json @@ -11,8 +11,9 @@ "files": [ "bin", "esm", + "!esm/**/*.map", "templates", - "!esm/**/*.map" + "openChrome.applescript" ], "engines": { "node": ">=12.22.0", diff --git a/packages/ice/src/utils/openBrowser.ts b/packages/ice/src/utils/openBrowser.ts index 5bb91746e..df964f364 100644 --- a/packages/ice/src/utils/openBrowser.ts +++ b/packages/ice/src/utils/openBrowser.ts @@ -80,6 +80,8 @@ function startBrowserProcess(browser, url, args) { const supportedChromiumBrowsers = [ 'Google Chrome Canary', 'Google Chrome', + 'Google Chrome Dev', + 'Google Chrome Beta', 'Microsoft Edge', 'Brave Browser', 'Vivaldi', @@ -98,7 +100,7 @@ function startBrowserProcess(browser, url, args) { chromiumBrowser }"`, { - cwd: __dirname, + cwd: path.join(__dirname, '../../'), stdio: 'ignore', }, ); diff --git a/scripts/copyFile.ts b/scripts/copyFile.ts deleted file mode 100644 index b032ea6e4..000000000 --- a/scripts/copyFile.ts +++ /dev/null @@ -1,8 +0,0 @@ -import path from 'path'; -import fse from 'fs-extra'; - -export default async function copyOneFile(file: string, cwd: string) { - const from = path.join(cwd, file); - const to = path.join(cwd, file.replace(/\/src\//, '/esm/')); - await fse.copy(from, to); -} From 9017482b019888d1a9bee2e639527d24322a8908 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Fri, 8 Jul 2022 15:31:07 +0800 Subject: [PATCH 04/13] fix: outputDir (#289) * fix: outputDir * fix: generate error output path * fix: comment * chore: remove outputDir config * chore: remove comment * fix: build fail * feat: optimize code --- packages/ice/src/commands/build.ts | 11 +++++++---- packages/ice/src/config.ts | 1 + packages/ice/src/middlewares/ssr/compileMiddleware.ts | 5 +++-- packages/ice/src/tasks/web/data-loader.ts | 1 - packages/ice/src/tasks/web/index.ts | 1 - packages/webpack-config/src/index.ts | 8 ++++---- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/ice/src/commands/build.ts b/packages/ice/src/commands/build.ts index bd95c526c..c66609db7 100644 --- a/packages/ice/src/commands/build.ts +++ b/packages/ice/src/commands/build.ts @@ -24,7 +24,10 @@ const build = async ( // @ts-expect-error fix type error of compiled webpack webpack, })); - await emptyDir(taskConfigs.find(({ name }) => name === 'web').config.outputDir); + const outputDir = webpackConfigs[0].output.path; + + await emptyDir(outputDir); + const compiler = await webpackCompiler({ rootDir, webpackConfigs, @@ -35,12 +38,12 @@ const build = async ( serverCompiler, }); const { ssg, ssr, server } = userConfig; - const { outputDir } = taskConfigs.find(({ name }) => name === 'web').config; // compile server bundle const entryPoint = path.join(rootDir, SERVER_ENTRY); const esm = server?.format === 'esm'; const outJSExtension = esm ? '.mjs' : '.cjs'; - const serverEntry = path.join(outputDir, SERVER_OUTPUT_DIR, `index${outJSExtension}`); + const serverOutputDir = path.join(outputDir, SERVER_OUTPUT_DIR); + const serverEntry = path.join(serverOutputDir, `index${outJSExtension}`); const documentOnly = !ssg && !ssr; const { stats, isSuccessful, messages } = await new Promise((resolve, reject): void => { @@ -68,7 +71,7 @@ const build = async ( const isSuccessful = !messages.errors.length; await serverCompiler({ entryPoints: { index: entryPoint }, - outdir: path.join(outputDir, SERVER_OUTPUT_DIR), + outdir: serverOutputDir, splitting: esm, format: server?.format, platform: esm ? 'browser' : 'node', diff --git a/packages/ice/src/config.ts b/packages/ice/src/config.ts index 0ca0ab891..139986928 100644 --- a/packages/ice/src/config.ts +++ b/packages/ice/src/config.ts @@ -71,6 +71,7 @@ const userConfig = [ { name: 'outputDir', validation: 'string', + defaultValue: 'build', setConfig: (config: Config, outputDir: UserConfig['outputDir']) => { return mergeDefaultValue(config, 'outputDir', outputDir); }, diff --git a/packages/ice/src/middlewares/ssr/compileMiddleware.ts b/packages/ice/src/middlewares/ssr/compileMiddleware.ts index ce958df58..3ea9028a4 100644 --- a/packages/ice/src/middlewares/ssr/compileMiddleware.ts +++ b/packages/ice/src/middlewares/ssr/compileMiddleware.ts @@ -21,10 +21,11 @@ export default function createCompileMiddleware(options: Options): Middleware { const { format } = server; const esm = format === 'esm'; const outJSExtension = esm ? '.mjs' : '.cjs'; - const serverEntry = path.join(outputDir, SERVER_OUTPUT_DIR, `index${outJSExtension}`); + const serverOutputDir = path.join(rootDir, outputDir, SERVER_OUTPUT_DIR); + const serverEntry = path.join(serverOutputDir, `index${outJSExtension}`); await serverCompiler({ entryPoints: { index: entryPoint }, - outdir: path.join(outputDir, SERVER_OUTPUT_DIR), + outdir: serverOutputDir, splitting: esm, format, platform: esm ? 'browser' : 'node', diff --git a/packages/ice/src/tasks/web/data-loader.ts b/packages/ice/src/tasks/web/data-loader.ts index cfc3a2b24..24a39283c 100644 --- a/packages/ice/src/tasks/web/data-loader.ts +++ b/packages/ice/src/tasks/web/data-loader.ts @@ -10,7 +10,6 @@ const getTask = ({ rootDir, command }): Config => { }, mode: command === 'start' ? 'development' : 'production', sourceMap: command === 'start' ? 'cheap-module-source-map' : false, - outputDir: path.join(rootDir, 'build'), cacheDir: path.join(rootDir, CACHE_DIR), alias: { ice: path.join(rootDir, '.ice', 'index.ts'), diff --git a/packages/ice/src/tasks/web/index.ts b/packages/ice/src/tasks/web/index.ts index ea1b3bdbe..2282e1a55 100644 --- a/packages/ice/src/tasks/web/index.ts +++ b/packages/ice/src/tasks/web/index.ts @@ -8,7 +8,6 @@ const getWebTask = ({ rootDir, command }): Config => { mode: command === 'start' ? 'development' : 'production', sourceMap: command === 'start' ? 'cheap-module-source-map' : false, cacheDir: path.join(rootDir, CACHE_DIR), - outputDir: path.join(rootDir, 'build'), alias: { ice: path.join(rootDir, '.ice', 'index.ts'), '@': path.join(rootDir, 'src'), diff --git a/packages/webpack-config/src/index.ts b/packages/webpack-config/src/index.ts index 308ca90b5..e6ec54785 100644 --- a/packages/webpack-config/src/index.ts +++ b/packages/webpack-config/src/index.ts @@ -60,7 +60,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack }) => { define = {}, externals = {}, publicPath = '/', - outputDir = path.join(rootDir, 'build'), + outputDir, loaders = [], plugins = [], alias = {}, @@ -84,7 +84,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack }) => { devServer, fastRefresh, } = config; - + const absoluteOutputDir = path.isAbsolute(outputDir) ? outputDir : path.join(rootDir, outputDir); const dev = mode !== 'production'; const supportedBrowsers = getSupportedBrowsers(rootDir, dev); const hashKey = hash === true ? 'hash:8' : (hash || ''); @@ -146,7 +146,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack }) => { externals, output: { publicPath, - path: path.isAbsolute(outputDir) ? outputDir : path.join(rootDir, outputDir), + path: absoluteOutputDir, filename: `js/${hashKey ? `[name]-[${hashKey}].js` : '[name].js'}`, assetModuleFilename: 'assets/[name].[hash:8][ext]', }, @@ -238,7 +238,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack }) => { !dev && new CopyPlugin({ patterns: [{ from: path.join(rootDir, 'public'), - to: outputDir, + to: absoluteOutputDir, // ignore assets already in compilation.assets such as js and css files force: false, noErrorOnMissing: true, From 767c0048727a9578b320dbd1e03e5d654c0c95ee Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Fri, 8 Jul 2022 17:34:11 +0800 Subject: [PATCH 05/13] feat: config transform (#339) * feat: add transform * fix: config transform * docs: config transform --- examples/basic-project/ice.config.mts | 6 ++++++ packages/ice/src/config.ts | 7 +++++++ packages/types/src/userConfig.ts | 2 ++ website/docs/guide/basic/config.md | 26 ++++++++++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/examples/basic-project/ice.config.mts b/examples/basic-project/ice.config.mts index 2450e9687..4586ac1cc 100644 --- a/examples/basic-project/ice.config.mts +++ b/examples/basic-project/ice.config.mts @@ -9,6 +9,12 @@ export default defineConfig({ HAHA: JSON.stringify(true), 'process.env.HAHA': JSON.stringify(true), }, + transform: (code, id) => { + if (id.includes('src/pages')) { + console.log('transform page:', id); + } + return code; + }, webpack: (webpackConfig) => { if (process.env.NODE_ENV !== 'test') { webpackConfig.plugins?.push(new SpeedMeasurePlugin()); diff --git a/packages/ice/src/config.ts b/packages/ice/src/config.ts index 139986928..bee76ff37 100644 --- a/packages/ice/src/config.ts +++ b/packages/ice/src/config.ts @@ -267,6 +267,13 @@ const userConfig = [ } }, }, + { + name: 'transform', + validation: 'function', + setConfig: (config: Config, transform: UserConfig['transform']) => { + config.transforms = config.transforms ? [...config.transforms, transform] : [transform]; + }, + }, { name: 'removeHistoryDeadCode', validation: 'boolean', diff --git a/packages/types/src/userConfig.ts b/packages/types/src/userConfig.ts index 0e4e52a1e..5ea6bc803 100644 --- a/packages/types/src/userConfig.ts +++ b/packages/types/src/userConfig.ts @@ -1,5 +1,6 @@ import type { DefineRouteFunction } from '@ice/route-manifest'; import type { PluginList } from 'build-scripts'; +import type { UnpluginOptions } from 'unplugin'; import type { Config, ModifyWebpackConfig } from './config'; import type { OverwritePluginAPI } from './plugin'; @@ -33,4 +34,5 @@ export interface UserConfig { }; removeHistoryDeadCode?: boolean; mock?: { exclude?: string[] }; + transform?: UnpluginOptions['transform']; } diff --git a/website/docs/guide/basic/config.md b/website/docs/guide/basic/config.md index 4da9f3839..ddea04d10 100644 --- a/website/docs/guide/basic/config.md +++ b/website/docs/guide/basic/config.md @@ -217,6 +217,32 @@ export default defineConfig({ }); ``` +### transform + +- 类型:`(code:string, id: string) => string | {code: string; map?: SourceMap | null;}` +- 默认值:`undefined` + +通过 `transform` 配置实现代码的转化: + +```js +import { defineConfig } from '@ice/app'; +import { transformSync } from '@babel/core'; + +export default defineConfig({ + transform: (originalCode, id) => { + if (!id.includes('node_modules')) { + // 借助 babel 编译 + const { code, map } = transformSync(originalCode, { + plugins: ['transform-decorators-legacy'], + }); + return { code, map }; + } + }, +}); +``` + +> ICE 内置通过 `swc` 提升编译体验,如果在 `transform` 配置上过多依赖 babel 等工具将可以能造成编译性能瓶颈 + ### ssr - 类型:`boolean` From abd1b90a51824ce367d04f48faf1c6513e5714c4 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Mon, 11 Jul 2022 12:18:24 +0800 Subject: [PATCH 06/13] feat: optimize server compile (#334) * feat: support compile server bundle after the webpack compile end * feat: support watch appConfig * chore: update .ice to RUNTIME_TMP_DIR * chore: optimize code * chore: remove build condition * chore: remove SERVER_OUTPUT * chore: remove compileMiddleware * chore: comment * fix: outputDir * fix: comment * chore: add preBundle option * feat: pass serverCompileTask to plugin * fix: get serverCompileTask from extendsPluginAPI --- examples/with-antd-mobile/public/favicon.ico | Bin 0 -> 2719 bytes packages/ice/package.json | 2 +- packages/ice/src/analyzeRuntime.ts | 18 ++-- packages/ice/src/commands/build.ts | 43 ++++---- packages/ice/src/commands/start.ts | 61 +++++++---- packages/ice/src/constant.ts | 15 +-- packages/ice/src/createService.ts | 32 ++++-- packages/ice/src/esbuild/depRedirect.ts | 3 + packages/ice/src/getWatchEvents.ts | 18 +++- .../src/middlewares/ssr/compileMiddleware.ts | 49 --------- .../src/middlewares/ssr/renderMiddleware.ts | 62 ++++++----- packages/ice/src/service/preBundleCJSDeps.ts | 3 + packages/ice/src/service/serverCompiler.ts | 96 +++++++++++------- packages/ice/src/tasks/web/data-loader.ts | 6 +- packages/ice/src/tasks/web/index.ts | 4 +- packages/ice/src/utils/ServerCompileTask.ts | 18 ++++ packages/ice/src/utils/runtimeEnv.ts | 5 +- .../ice/src/webpack/ServerCompilerPlugin.ts | 29 ++++++ packages/runtime/package.json | 3 +- packages/runtime/src/index.ts | 2 - packages/runtime/src/matchRoutes.ts | 25 +++++ packages/runtime/src/routes.tsx | 21 ---- packages/runtime/src/runClientApp.tsx | 3 +- packages/runtime/src/runServerApp.tsx | 3 +- packages/types/package.json | 2 +- packages/types/src/plugin.ts | 17 +++- packages/webpack-config/README.md | 7 +- packages/webpack-config/package.json | 2 +- packages/webpack-config/src/index.ts | 11 +- pnpm-lock.yaml | 17 ++-- 30 files changed, 343 insertions(+), 234 deletions(-) create mode 100644 examples/with-antd-mobile/public/favicon.ico delete mode 100644 packages/ice/src/middlewares/ssr/compileMiddleware.ts create mode 100644 packages/ice/src/utils/ServerCompileTask.ts create mode 100644 packages/ice/src/webpack/ServerCompilerPlugin.ts create mode 100644 packages/runtime/src/matchRoutes.ts diff --git a/examples/with-antd-mobile/public/favicon.ico b/examples/with-antd-mobile/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a2605c57e9d85aabd689ff5c565286dee148ab6d GIT binary patch literal 2719 zcmbVO`8yMiA9svQv58DRxk@YN91}_`b4{U4xk7!C`zZN1)+bw`g+vn_YM5h6q=V&5 zY&mjF?i^!|S(r95*X&b&!uR`np7;CpJg?XDeqPV>{^^x+*4bW0T3K2|L_`MVVB`9m z^Z$&LFJVfVn*0@o`Uz6v;qRJkbcT zDz0Q12lTZ%`ghogFZaE+CzC-?b?9FC>?D|Pkd}eIbR7dOXL}DpS5J}aua3Bq7}H>3 z8Og;>eXE)t$2j*0A8+@``?d@C5+r!O_l|zaGtfJqEVzm*-TcP@xe{qr(<>BvWYfnOA_I+w&Y*YLR6D?M(%fv^^ylDNyqy>P1;<>wK^T+^*ewX1F*_vqxLT{VuTwPl_xOnH+!=f&y+_wjGs5N)( zIwZ0G zVGDjn#KgnB&u8q{TCQ(JV{CoGszvgBKP2U=F>)r@Dd4e=_(ruDP;4@M8F1kb3KIcNh8el;^6SjxPb7UgHpr7VfQ{=QKLXR9T}an41j9LX(*&x z-s#Okyn>i7`hll*yEa0SH(77uC0SJod(1wZCZLG$IX8 zgg3YePH-pHznZz=(oROkAeRf08LlBU$+*P0OW%>UC7k&8KMHpwmfDk`%76o_!Ai5Q zv)lzh<8xj&BbK%Y*OQ66ME|)KPtGM~9a&2KcW&o<8==OD`^n_3dOjy-R&Dl$5-+l* zJk2a{$R7I*qYCI3d|S*C82Dj`%fgc&G38RV+WC_$Yb{Uz={03hE-uD{=}iJUvPZc@ zt@}G;<>y$*@SltoJE~focFsZ_%Vbscb&wTfMg7u*ewX*sdAFmh*0k%&US4YBUcE7I zS*M!n8G80JPMI?e(Kh;8I!0u|uubOc~y^z<%yrpt0`9F!ItogT=I31$ZGr>Mw-+qHLv=|9sm zqSffY$EJ3d$F3s{wZ^iI$ORCwgCovV*z7IJR_1c20|(Pu``hy5BR9x; zj`h)HANSU`uiHrH1al^C++E+4k-F#40F8fOzDsC(0Xs_TfF_ULf!|_ydeL)|a1Jro z`}oH|*+3cJgt{U(L5hV1`U2z}RHY)-m_|6j3|=SDC%ammwfd@xib@hygHkVx9b`lO z?$3^18)@?D*+AOx0ZjHT`-U6{Gw5FzvfmkN3 z>iM1+Vy@*`o~eUlNbT~YRw;AfVZk*Rzhw{rfS>9?r{1t{Jz0+mb{haKPbYZv5|eNn z{VNt9&hCNNqdZGqsVPQ278pp2rceA9wQu#Hu@5G@9)y1mxhlAJgx^x41b|O)>(hC6 zxd+|P4EGtQlBdYei{4G+%Yjm*!k3gG4k^VNrm%6MB+4qxbr8fSZ)yPg8T}_ZJT+IP zPp>P*QW*+sNU72cez@>5*Y{~{N`ykK-2%RGGE`#c5`~cR(bxhgHm7@CaT!_8+Mjy; zHnG=2&MHd)7E?Cz8+Avg7#vT&{UEqr*A$6pnRzmfOtWn~ryvDmrNp@=;|j;Q`*Pf~ z0wA-DHO_2Rx{kE?x=eA}-pcZLRF1s-8H3LN$F?iILXGiax~+Tq(*AT!Z$j3GqT~QM zDJ`F4Bhc|j5w71Oqzj^ZTcN0e;k$t-6jDX82_cvM&yKe5hu z{TF*|*%zp_PJCQ=e=%NMFhSpL9&+)wS_~GOdp1WOv0%r%V44FAam3hgp7A%Eqw9j7 zIXBU3EgbRndo#+!1Zz8t$)d)OHLuyV&l1PAn?smen<&|-$OZu2@8QTn+MFr)m3y5- zfPE&Ulh$|uf)x((@(gCxmst)n0lNsHVHV1vQ#pvcm1a`CF zS@fp^M4vE;eKx|G*CXdsmp&Wt1mx%QJo>M(<&}@+-#Hn(j8=1Slj$Qe+2o-f9!SL> zEHKc%kW6BqCu-JR%k3tZRt?x>Bi-k>>pFEKlwy7na65EDm3*q_CZ5vQlsF&RSHHAk zHG23^LvvqA)%5Kw(48PmI=s$K?gnb-%=m$(j$Z$1A5lTUkx;d$vpI=C9~KSm?z_~c z#SXvKTSJ~$>E(6?fHXpHU_&wdoa3=(dgo@B&oO~(nr*w#-l#{yhr6ZiG zDK@Pu;rBB-zUnG5K`1`LFFgGPx93J zo=uIxw8w{%Ah89CE zG%Z{%x-c=Q%W~)VcuxU+8@pZ@!$84eF)sG~iycG%+E-hae$E0JnM{rKv6SObgAvd= zaAXfwR)*@t?uUq zrv8D1TZTqxkCAXZq(WAY7Ogs8eUtXYJ4IS4%)&D|9^+Qd3!h**T4=;BlDsFb@~YaS zs8Ks~*8$jS{|`e^1EWtdZ4QHH1}etRcJfqc7dId05z9J`2!%ttHP;`wI>YxHjW8Z1 ztxy7L7%x$L(!+>)q|FupVfw;o&5+IA4Oi_6Kadib+iKTi>Ozfzo9y&%QVVV literal 0 HcmV?d00001 diff --git a/packages/ice/package.json b/packages/ice/package.json index 1b271834b..f0ed6ede2 100644 --- a/packages/ice/package.json +++ b/packages/ice/package.json @@ -36,7 +36,7 @@ "@ice/webpack-config": "^1.0.0", "acorn": "^8.7.1", "address": "^1.1.2", - "build-scripts": "^2.0.0-22", + "build-scripts": "^2.0.0-23", "body-parser": "^1.20.0", "chalk": "^4.0.0", "commander": "^9.0.0", diff --git a/packages/ice/src/analyzeRuntime.ts b/packages/ice/src/analyzeRuntime.ts index d83579aa9..0ae285199 100644 --- a/packages/ice/src/analyzeRuntime.ts +++ b/packages/ice/src/analyzeRuntime.ts @@ -1,15 +1,20 @@ import * as path from 'path'; import consola from 'consola'; import type { ServerCompiler } from '@ice/types/esm/plugin.js'; -import type { AppConfig } from './utils/runtimeEnv.js'; +import type { AppConfig } from '@ice/types'; interface Options { serverCompiler: ServerCompiler; rootDir: string; } -export const getAppConfig = async (options: Options): Promise => { - const { serverCompiler, rootDir } = options; +let appConfig: AppConfig; + +export const getAppConfig = (): AppConfig => { + return appConfig; +}; + +export async function compileAppConfig({ rootDir, serverCompiler }: Options) { const outfile = path.join(rootDir, 'node_modules', 'entry.mjs'); // TODO: remove top level calls to ensure that appConfig is always returned successfully in build time await serverCompiler({ @@ -18,8 +23,7 @@ export const getAppConfig = async (options: Options): Promise => { format: 'esm', inject: [], }); - - const appConfig = (await import(outfile)).default; - consola.debug('get app config by esbuild:', appConfig); + appConfig = (await import(outfile)).default; + consola.debug('Compile app config by esbuild: ', appConfig); return appConfig; -}; +} diff --git a/packages/ice/src/commands/build.ts b/packages/ice/src/commands/build.ts index c66609db7..585d0f085 100644 --- a/packages/ice/src/commands/build.ts +++ b/packages/ice/src/commands/build.ts @@ -8,7 +8,7 @@ import type { ServerCompiler } from '@ice/types/esm/plugin.js'; import webpack from '@ice/bundles/compiled/webpack/index.js'; import webpackCompiler from '../service/webpackCompiler.js'; import formatWebpackMessages from '../utils/formatWebpackMessages.js'; -import { SERVER_ENTRY, SERVER_OUTPUT_DIR } from '../constant.js'; +import { RUNTIME_TMP_DIR, SERVER_ENTRY, SERVER_OUTPUT_DIR } from '../constant.js'; import generateHTML from '../utils/generateHTML.js'; import emptyDir from '../utils/emptyDir.js'; @@ -23,6 +23,7 @@ const build = async ( rootDir, // @ts-expect-error fix type error of compiled webpack webpack, + runtimeTmpDir: RUNTIME_TMP_DIR, })); const outputDir = webpackConfigs[0].output.path; @@ -37,15 +38,14 @@ const build = async ( applyHook, serverCompiler, }); - const { ssg, ssr, server } = userConfig; + const { ssg, ssr, server: { format } } = userConfig; // compile server bundle const entryPoint = path.join(rootDir, SERVER_ENTRY); - const esm = server?.format === 'esm'; + const esm = format === 'esm'; const outJSExtension = esm ? '.mjs' : '.cjs'; const serverOutputDir = path.join(outputDir, SERVER_OUTPUT_DIR); - const serverEntry = path.join(serverOutputDir, `index${outJSExtension}`); const documentOnly = !ssg && !ssr; - + let serverEntry; const { stats, isSuccessful, messages } = await new Promise((resolve, reject): void => { let messages: { errors: string[]; warnings: string[] }; compiler.run(async (err, stats) => { @@ -69,18 +69,25 @@ const build = async ( } else { compiler?.close?.(() => {}); const isSuccessful = !messages.errors.length; - await serverCompiler({ - entryPoints: { index: entryPoint }, - outdir: serverOutputDir, - splitting: esm, - format: server?.format, - platform: esm ? 'browser' : 'node', - outExtension: { '.js': outJSExtension }, - }, { - // Remove components and getData when document only. - removeExportExprs: documentOnly ? ['default', 'getData', 'getServerData', 'getStaticData'] : [], - jsxTransform: true, - }); + const serverCompilerResult = await serverCompiler( + { + entryPoints: { index: entryPoint }, + outdir: serverOutputDir, + splitting: esm, + format, + platform: esm ? 'browser' : 'node', + outExtension: { '.js': outJSExtension }, + }, + { + preBundle: format === 'esm', + swc: { + // Remove components and getData when document only. + removeExportExprs: documentOnly ? ['default', 'getData', 'getServerData', 'getStaticData'] : [], + jsxTransform: true, + }, + }, + ); + serverEntry = serverCompilerResult.serverEntry; let renderMode; if (ssg) { @@ -103,6 +110,7 @@ const build = async ( } }); }); + await applyHook('after.build.compile', { stats, isSuccessful, @@ -111,6 +119,7 @@ const build = async ( serverCompiler, serverEntry, }); + return { compiler }; }; diff --git a/packages/ice/src/commands/start.ts b/packages/ice/src/commands/start.ts index a3c29dccc..19b975619 100644 --- a/packages/ice/src/commands/start.ts +++ b/packages/ice/src/commands/start.ts @@ -1,27 +1,30 @@ +import * as path from 'path'; import WebpackDevServer from 'webpack-dev-server'; import type { Configuration } from 'webpack-dev-server'; import type { Context, TaskConfig } from 'build-scripts'; import lodash from '@ice/bundles/compiled/lodash/index.js'; import type { Config } from '@ice/types'; -import type { ServerCompiler } from '@ice/types/esm/plugin.js'; -import type { AppConfig } from '@ice/runtime'; +import type { ExtendsPluginAPI, ServerCompiler } from '@ice/types/esm/plugin.js'; +import type { AppConfig, RenderMode } from '@ice/runtime'; import { getWebpackConfig } from '@ice/webpack-config'; import webpack from '@ice/bundles/compiled/webpack/index.js'; import webpackCompiler from '../service/webpackCompiler.js'; import prepareURLs from '../utils/prepareURLs.js'; -import createCompileMiddleware from '../middlewares/ssr/compileMiddleware.js'; import createRenderMiddleware from '../middlewares/ssr/renderMiddleware.js'; import createMockMiddleware from '../middlewares/mock/createMiddleware.js'; +import { ROUTER_MANIFEST, RUNTIME_TMP_DIR, SERVER_ENTRY, SERVER_OUTPUT_DIR } from '../constant.js'; +import ServerCompilerPlugin from '../webpack/ServerCompilerPlugin.js'; +import { getAppConfig } from '../analyzeRuntime.js'; const { merge } = lodash; const start = async ( - context: Context, + context: Context, taskConfigs: TaskConfig[], serverCompiler: ServerCompiler, appConfig: AppConfig, ) => { - const { applyHook, commandArgs, command, rootDir, userConfig } = context; + const { applyHook, commandArgs, command, rootDir, userConfig, extendsPluginAPI: { serverCompileTask } } = context; const { port, host, https = false } = commandArgs; const webpackConfigs = taskConfigs.map(({ config }) => getWebpackConfig({ @@ -29,42 +32,64 @@ const start = async ( rootDir, // @ts-expect-error fix type error of compiled webpack webpack, + runtimeTmpDir: RUNTIME_TMP_DIR, })); + // Compile server entry after the webpack compilation. + const outputDir = webpackConfigs[0].output.path; + const { ssg, ssr, server: { format } } = userConfig; + const entryPoint = path.join(rootDir, SERVER_ENTRY); + const esm = format === 'esm'; + const outJSExtension = esm ? '.mjs' : '.cjs'; + webpackConfigs[0].plugins.push( + new ServerCompilerPlugin( + serverCompiler, + [ + { + entryPoints: { index: entryPoint }, + outdir: path.join(outputDir, SERVER_OUTPUT_DIR), + splitting: esm, + format, + platform: esm ? 'browser' : 'node', + outExtension: { '.js': outJSExtension }, + }, + { + preBundle: format === 'esm', + }, + ], + serverCompileTask, + ), + ); + const customMiddlewares = webpackConfigs[0].devServer?.setupMiddlewares; let devServerConfig: Configuration = { port, host, https, setupMiddlewares: (middlewares, devServer) => { - const { outputDir } = taskConfigs.find(({ name }) => name === 'web').config; - const { ssg, ssr, server } = userConfig; - const documentOnly = !ssr && !ssg; - const serverCompileMiddleware = createCompileMiddleware({ - rootDir, - outputDir, - serverCompiler, - server, - documentOnly, - }); - - let renderMode; + let renderMode: RenderMode; // If ssr is set to true, use ssr for preview. if (ssr) { renderMode = 'SSR'; } else if (ssg) { renderMode = 'SSG'; } + const appConfig = getAppConfig(); + const routeManifestPath = path.join(rootDir, ROUTER_MANIFEST); + const documentOnly = !ssr && !ssg; const serverRenderMiddleware = createRenderMiddleware({ + serverCompileTask, + routeManifestPath, documentOnly, renderMode, + basename: appConfig?.router?.basename, }); const insertIndex = middlewares.findIndex(({ name }) => name === 'serve-index'); middlewares.splice( insertIndex, 0, - serverCompileMiddleware, serverRenderMiddleware, ); + if (commandArgs.mock) { const mockMiddleware = createMockMiddleware({ rootDir, exclude: userConfig?.mock?.exclude }); middlewares.splice(insertIndex, 0, mockMiddleware); diff --git a/packages/ice/src/constant.ts b/packages/ice/src/constant.ts index e19be31ac..4cba0456a 100644 --- a/packages/ice/src/constant.ts +++ b/packages/ice/src/constant.ts @@ -1,13 +1,16 @@ -export const ROUTER_MANIFEST = '.ice/route-manifest.json'; -export const ASSETS_MANIFEST = '.ice/assets-manifest.json'; -export const SERVER_ENTRY = '.ice/entry.server.ts'; +import * as path from 'path'; + +export const RUNTIME_TMP_DIR = '.ice'; +export const ROUTER_MANIFEST = path.join(RUNTIME_TMP_DIR, 'route-manifest.json'); +export const ASSETS_MANIFEST = path.join(RUNTIME_TMP_DIR, 'assets-manifest.json'); +export const SERVER_ENTRY = path.join(RUNTIME_TMP_DIR, 'entry.server.ts'); +export const DATA_LOADER_ENTRY = path.join(RUNTIME_TMP_DIR, 'data-loader.ts'); export const SERVER_OUTPUT_DIR = 'server'; -export const SERVER_OUTPUT = `${SERVER_OUTPUT_DIR}/index.mjs`; -export const CACHE_DIR = 'node_modules/.ice'; +export const CACHE_DIR = path.join('node_modules', RUNTIME_TMP_DIR); export const BUILDIN_ESM_DEPS = [ '@ice/runtime', ]; export const BUILDIN_CJS_DEPS = [ 'react', 'react-dom', -]; \ No newline at end of file +]; diff --git a/packages/ice/src/createService.ts b/packages/ice/src/createService.ts index 5b2ffd47d..d9e5c515e 100644 --- a/packages/ice/src/createService.ts +++ b/packages/ice/src/createService.ts @@ -3,7 +3,7 @@ import { fileURLToPath } from 'url'; import { Context } from 'build-scripts'; import consola from 'consola'; import type { CommandArgs, CommandName } from 'build-scripts'; -import type { Config } from '@ice/types'; +import type { AppConfig, Config } from '@ice/types'; import type { ExportData } from '@ice/types/esm/generator.js'; import type { ExtendsPluginAPI } from '@ice/types/esm/plugin.js'; import webpack from '@ice/bundles/compiled/webpack/index.js'; @@ -14,14 +14,15 @@ import start from './commands/start.js'; import build from './commands/build.js'; import mergeTaskConfig from './utils/mergeTaskConfig.js'; import getWatchEvents from './getWatchEvents.js'; -import { getAppConfig } from './analyzeRuntime.js'; +import { compileAppConfig } from './analyzeRuntime.js'; import { initProcessEnv, updateRuntimeEnv, getCoreEnvKeys } from './utils/runtimeEnv.js'; import getRuntimeModules from './utils/getRuntimeModules.js'; import { generateRoutesInfo } from './routes.js'; import getWebTask from './tasks/web/index.js'; import getDataLoaderTask from './tasks/web/data-loader.js'; import * as config from './config.js'; -import type { AppConfig } from './utils/runtimeEnv.js'; +import { RUNTIME_TMP_DIR } from './constant.js'; +import ServerCompileTask from './utils/ServerCompileTask.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -32,13 +33,12 @@ interface CreateServiceOptions { } async function createService({ rootDir, command, commandArgs }: CreateServiceOptions) { - const targetDir = '.ice'; const templateDir = path.join(__dirname, '../templates/'); const configFile = 'ice.config.(mts|mjs|ts|js|cjs|json)'; const dataCache = new Map(); const generator = new Generator({ rootDir, - targetDir, + targetDir: RUNTIME_TMP_DIR, // add default template of ice templates: [templateDir], }); @@ -59,6 +59,7 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt addRenderTemplate: generator.addTemplateFiles, }; + const serverCompileTask = new ServerCompileTask(); const ctx = new Context({ rootDir, command, @@ -74,6 +75,7 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt // @ts-expect-error repack type can not match with original type webpack, }, + serverCompileTask, }, }); @@ -123,9 +125,6 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt // render template before webpack compile const renderStart = new Date().getTime(); generator.render(); - addWatchEvent( - ...getWatchEvents({ generator, targetDir, templateDir, cache: dataCache, ctx }), - ); consola.debug('template render cost:', new Date().getTime() - renderStart); // create serverCompiler with task config @@ -133,17 +132,30 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt rootDir, task: webTaskConfig, command, - serverBundle: server.bundle, + server, }); + + addWatchEvent( + ...getWatchEvents({ + generator, + targetDir: RUNTIME_TMP_DIR, + templateDir, + cache: dataCache, + ctx, + serverCompiler, + }), + ); + let appConfig: AppConfig; try { // should after generator, otherwise it will compile error - appConfig = await getAppConfig({ serverCompiler, rootDir }); + appConfig = await compileAppConfig({ serverCompiler, rootDir }); } catch (err) { consola.warn('Failed to get app config:', err.message); consola.debug(err); } + const disableRouter = userConfig.removeHistoryDeadCode && routesInfo.routesCount <= 1; if (disableRouter) { consola.info('[ice] removeHistoryDeadCode is enabled and only have one route, ice build will remove history and react-router dead code.'); diff --git a/packages/ice/src/esbuild/depRedirect.ts b/packages/ice/src/esbuild/depRedirect.ts index c50a65327..826fe9dbc 100644 --- a/packages/ice/src/esbuild/depRedirect.ts +++ b/packages/ice/src/esbuild/depRedirect.ts @@ -13,6 +13,9 @@ const { init, parse } = esModuleLexer; type ImportNameSpecifier = { importedName: string; localName: string }; +/** + * Redirect original dependency to the pre-bundle dependency(cjs) which is handled by preBundleCJSDeps function. + */ const createDepRedirectPlugin = (metadata: DepsMetaData): Plugin => { return { name: 'esbuild-dep-redirect', diff --git a/packages/ice/src/getWatchEvents.ts b/packages/ice/src/getWatchEvents.ts index e17f48928..3fc9f4414 100644 --- a/packages/ice/src/getWatchEvents.ts +++ b/packages/ice/src/getWatchEvents.ts @@ -1,10 +1,11 @@ import * as path from 'path'; import consola from 'consola'; -import type { WatchEvent } from '@ice/types/esm/plugin.js'; +import type { ServerCompiler, WatchEvent } from '@ice/types/esm/plugin.js'; import type { Context } from 'build-scripts'; import type { Config } from '@ice/types'; import { generateRoutesInfo } from './routes.js'; import type Generator from './service/runtimeGenerator'; +import { compileAppConfig } from './analyzeRuntime.js'; import getGlobalStyleGlobPattern from './utils/getGlobalStyleGlobPattern.js'; interface Options { @@ -13,10 +14,11 @@ interface Options { generator: Generator; cache: Map; ctx: Context; + serverCompiler: ServerCompiler; } const getWatchEvents = (options: Options): WatchEvent[] => { - const { generator, targetDir, templateDir, cache, ctx } = options; + const { serverCompiler, generator, targetDir, templateDir, cache, ctx } = options; const { userConfig: { routes: routesConfig }, configFile, rootDir } = ctx; const watchRoutes: WatchEvent = [ /src\/pages\/?[\w*-:.$]+$/, @@ -78,7 +80,17 @@ const getWatchEvents = (options: Options): WatchEvent[] => { }, ]; - return [watchConfigFile, watchRoutes, watchGlobalStyle]; + const watchAppConfigFile: WatchEvent = [ + /src\/app.(js|jsx|ts|tsx)/, + async (event: string) => { + if (event === 'change') { + consola.debug('[event]', 'Compile app config.'); + await compileAppConfig({ rootDir, serverCompiler }); + } + }, + ]; + + return [watchConfigFile, watchRoutes, watchGlobalStyle, watchAppConfigFile]; }; export default getWatchEvents; diff --git a/packages/ice/src/middlewares/ssr/compileMiddleware.ts b/packages/ice/src/middlewares/ssr/compileMiddleware.ts deleted file mode 100644 index 3ea9028a4..000000000 --- a/packages/ice/src/middlewares/ssr/compileMiddleware.ts +++ /dev/null @@ -1,49 +0,0 @@ -import path from 'path'; -import type { ServerCompiler } from '@ice/types/esm/plugin'; -import type { ExpressRequestHandler, Middleware } from 'webpack-dev-server'; -import consola from 'consola'; -import type { UserConfig } from '@ice/types'; -import { SERVER_ENTRY, SERVER_OUTPUT_DIR } from '../../constant.js'; - -interface Options { - rootDir: string; - outputDir: string; - serverCompiler: ServerCompiler; - server: UserConfig['server']; - documentOnly: boolean; -} - -export default function createCompileMiddleware(options: Options): Middleware { - const { rootDir, outputDir, serverCompiler, server, documentOnly } = options; - const middleware: ExpressRequestHandler = async function (req, _, next) { - try { - const entryPoint = path.join(rootDir, SERVER_ENTRY); - const { format } = server; - const esm = format === 'esm'; - const outJSExtension = esm ? '.mjs' : '.cjs'; - const serverOutputDir = path.join(rootDir, outputDir, SERVER_OUTPUT_DIR); - const serverEntry = path.join(serverOutputDir, `index${outJSExtension}`); - await serverCompiler({ - entryPoints: { index: entryPoint }, - outdir: serverOutputDir, - splitting: esm, - format, - platform: esm ? 'browser' : 'node', - outExtension: { '.js': outJSExtension }, - }, { - removeExportExprs: documentOnly ? ['default', 'getData'] : [], - }); - // @ts-ignore - req.serverEntry = serverEntry; - } catch (err) { - consola.error(`fail to compile in ssr middleware: ${err}`); - } - - next(); - }; - - return { - name: 'server-compile', - middleware, - }; -} \ No newline at end of file diff --git a/packages/ice/src/middlewares/ssr/renderMiddleware.ts b/packages/ice/src/middlewares/ssr/renderMiddleware.ts index d824f0d03..e32b11540 100644 --- a/packages/ice/src/middlewares/ssr/renderMiddleware.ts +++ b/packages/ice/src/middlewares/ssr/renderMiddleware.ts @@ -1,43 +1,53 @@ import { createRequire } from 'module'; +import fse from 'fs-extra'; import type { ExpressRequestHandler, Middleware } from 'webpack-dev-server'; import type { ServerContext, RenderMode } from '@ice/runtime'; import consola from 'consola'; +// @ts-expect-error FIXME: esm type error +import matchRoutes from '@ice/runtime/matchRoutes'; +import type { ExtendsPluginAPI } from '@ice/types/esm/plugin.js'; const require = createRequire(import.meta.url); interface Options { + serverCompileTask: ExtendsPluginAPI['serverCompileTask']; + routeManifestPath: string; documentOnly?: boolean; renderMode?: RenderMode; + basename?: string; } export default function createRenderMiddleware(options: Options): Middleware { - const { documentOnly, renderMode } = options; - const middleware: ExpressRequestHandler = async function (req, res) { - // @ts-ignore - const { serverEntry } = req; - if (!serverEntry) { - consola.error('The server entry is not defined.'); - return; - } - let serverModule; - try { - delete require.cache[serverEntry]; - // timestamp for disable import cache - const serverEntryWithVersion = `${serverEntry}?version=${new Date().getTime()}`; - serverModule = await import(serverEntryWithVersion); - } catch (err) { - // make error clearly, notice typeof err === 'string' - consola.error(`import ${serverEntry} error: ${err}`); - return; + const { documentOnly, renderMode, serverCompileTask, routeManifestPath, basename } = options; + const middleware: ExpressRequestHandler = async function (req, res, next) { + const routes = JSON.parse(fse.readFileSync(routeManifestPath, 'utf-8')); + const matches = matchRoutes(routes, req.path, basename); + if (matches.length) { + // Wait for the server compilation to finish + const { serverEntry } = await serverCompileTask.get(); + + let serverModule; + try { + delete require.cache[serverEntry]; + // timestamp for disable import cache + const serverEntryWithVersion = `${serverEntry}?version=${new Date().getTime()}`; + serverModule = await import(serverEntryWithVersion); + } catch (err) { + // make error clearly, notice typeof err === 'string' + consola.error(`import ${serverEntry} error: ${err}`); + return; + } + const requestContext: ServerContext = { + req, + res, + }; + serverModule.renderToResponse(requestContext, { + renderMode, + documentOnly, + }); + } else { + next(); } - const requestContext: ServerContext = { - req, - res, - }; - serverModule.renderToResponse(requestContext, { - renderMode, - documentOnly, - }); }; return { diff --git a/packages/ice/src/service/preBundleCJSDeps.ts b/packages/ice/src/service/preBundleCJSDeps.ts index a7a1c132e..b4f521d5f 100644 --- a/packages/ice/src/service/preBundleCJSDeps.ts +++ b/packages/ice/src/service/preBundleCJSDeps.ts @@ -45,6 +45,9 @@ interface PreBundleDepsOptions { taskConfig: Config; } +/** + * Pre bundle dependencies from esm to cjs. + */ export default async function preBundleCJSDeps(options: PreBundleDepsOptions): Promise { const { depsInfo, rootDir, cacheDir, taskConfig } = options; const metadata = createDepsMetadata(depsInfo, taskConfig); diff --git a/packages/ice/src/service/serverCompiler.ts b/packages/ice/src/service/serverCompiler.ts index 7f2af01f5..dfd264c2a 100644 --- a/packages/ice/src/service/serverCompiler.ts +++ b/packages/ice/src/service/serverCompiler.ts @@ -4,7 +4,7 @@ import { createHash } from 'crypto'; import * as fs from 'fs'; import consola from 'consola'; import esbuild from 'esbuild'; -import type { Config } from '@ice/types'; +import type { Config, UserConfig } from '@ice/types'; import type { ServerCompiler } from '@ice/types/esm/plugin.js'; import type { TaskConfig } from 'build-scripts'; import { getCompilerPlugins } from '@ice/webpack-config'; @@ -12,7 +12,7 @@ import escapeLocalIdent from '../utils/escapeLocalIdent.js'; import cssModulesPlugin from '../esbuild/cssModules.js'; import aliasPlugin from '../esbuild/alias.js'; import createAssetsPlugin from '../esbuild/assets.js'; -import { ASSETS_MANIFEST, CACHE_DIR, SERVER_ENTRY } from '../constant.js'; +import { ASSETS_MANIFEST, CACHE_DIR, SERVER_ENTRY, SERVER_OUTPUT_DIR } from '../constant.js'; import emptyCSSPlugin from '../esbuild/emptyCSS.js'; import createDepRedirectPlugin from '../esbuild/depRedirect.js'; import isExternalBuiltinDep from '../utils/isExternalBuiltinDep.js'; @@ -25,12 +25,11 @@ interface Options { rootDir: string; task: TaskConfig; command: string; - serverBundle: boolean; + server: UserConfig['server']; } export function createServerCompiler(options: Options) { - const { task, rootDir, command, serverBundle } = options; - const { config } = task; + const { task, rootDir, command, server } = options; const alias = (task.config?.alias || {}) as Record; const assetsManifest = path.join(rootDir, ASSETS_MANIFEST); @@ -54,39 +53,14 @@ export function createServerCompiler(options: Options) { } }); - const serverCompiler: ServerCompiler = async (buildOptions, swcOptions) => { - const serverEntry = path.join(rootDir, SERVER_ENTRY); - let metadata; - if (buildOptions?.format === 'esm') { - const deps = await scanImports([serverEntry], { - rootDir, - alias: (task.config?.alias || {}) as Record, - }); - - function filterPreBundleDeps(deps: Record) { - const preBundleDepsInfo = {}; - for (const dep in deps) { - if (!isExternalBuiltinDep(dep, buildOptions?.format)) { - preBundleDepsInfo[dep] = deps[dep]; - } - } - return preBundleDepsInfo; - } - // don't pre bundle the deps because they can run in node env. - // For examples: react, react-dom, @ice/runtime - const preBundleDepsInfo = filterPreBundleDeps(deps); - const cacheDir = path.join(rootDir, CACHE_DIR); - const ret = await preBundleCJSDeps({ - depsInfo: preBundleDepsInfo, - rootDir, - cacheDir, - taskConfig: task.config, - }); - metadata = ret.metadata; + const serverCompiler: ServerCompiler = async (buildOptions, { preBundle, swc: swcOptions } = {}) => { + let depsMetadata; + if (preBundle) { + depsMetadata = await createDepsMetadata({ task, rootDir }); } const transformPlugins = getCompilerPlugins({ - ...config, + ...task.config, fastRefresh: false, swcOptions, }, 'esbuild'); @@ -100,7 +74,8 @@ export function createServerCompiler(options: Options) { ...defineVars, ...runtimeDefineVars, }; - const buildResult = await esbuild.build({ + + const esbuildResult = await esbuild.build({ bundle: true, format: 'esm', target: 'node12.20.0', @@ -113,10 +88,10 @@ export function createServerCompiler(options: Options) { plugins: [ ...(buildOptions.plugins || []), emptyCSSPlugin(), - dev && buildOptions?.format === 'esm' && createDepRedirectPlugin(metadata), + dev && preBundle && createDepRedirectPlugin(depsMetadata), aliasPlugin({ alias, - serverBundle, + serverBundle: server.bundle, format: buildOptions?.format || 'esm', }), cssModulesPlugin({ @@ -132,9 +107,52 @@ export function createServerCompiler(options: Options) { ].filter(Boolean), }); consola.debug('[esbuild]', `time cost: ${new Date().getTime() - startTime}ms`); - return buildResult; + const esm = server?.format === 'esm'; + const outJSExtension = esm ? '.mjs' : '.cjs'; + const serverEntry = path.join(rootDir, task.config.outputDir, SERVER_OUTPUT_DIR, `index${outJSExtension}`); + + return { + ...esbuildResult, + serverEntry, + }; }; return serverCompiler; } +interface CreateDepsMetadataOptions { + rootDir: string; + task: TaskConfig; +} +/** + * Create dependencies metadata only when server entry is bundled to esm. + */ +async function createDepsMetadata({ rootDir, task }: CreateDepsMetadataOptions) { + const serverEntry = path.join(rootDir, SERVER_ENTRY); + const deps = await scanImports([serverEntry], { + rootDir, + alias: (task.config?.alias || {}) as Record, + }); + + function filterPreBundleDeps(deps: Record) { + const preBundleDepsInfo = {}; + for (const dep in deps) { + if (!isExternalBuiltinDep(dep)) { + preBundleDepsInfo[dep] = deps[dep]; + } + } + return preBundleDepsInfo; + } + // don't pre bundle the deps because they can run in node env. + // For examples: react, react-dom, @ice/runtime + const preBundleDepsInfo = filterPreBundleDeps(deps); + const cacheDir = path.join(rootDir, CACHE_DIR); + const ret = await preBundleCJSDeps({ + depsInfo: preBundleDepsInfo, + rootDir, + cacheDir, + taskConfig: task.config, + }); + + return ret.metadata; +} diff --git a/packages/ice/src/tasks/web/data-loader.ts b/packages/ice/src/tasks/web/data-loader.ts index 24a39283c..aac7f76b9 100644 --- a/packages/ice/src/tasks/web/data-loader.ts +++ b/packages/ice/src/tasks/web/data-loader.ts @@ -1,18 +1,18 @@ import * as path from 'path'; import type { Config } from '@ice/types'; -import { CACHE_DIR } from '../../constant.js'; +import { CACHE_DIR, DATA_LOADER_ENTRY, RUNTIME_TMP_DIR } from '../../constant.js'; const getTask = ({ rootDir, command }): Config => { // basic task config of data-loader return { entry: { - 'data-loader': path.join(rootDir, '.ice/data-loader'), + 'data-loader': path.join(rootDir, DATA_LOADER_ENTRY), }, mode: command === 'start' ? 'development' : 'production', sourceMap: command === 'start' ? 'cheap-module-source-map' : false, cacheDir: path.join(rootDir, CACHE_DIR), alias: { - ice: path.join(rootDir, '.ice', 'index.ts'), + ice: path.join(rootDir, RUNTIME_TMP_DIR, 'index.ts'), '@': path.join(rootDir, 'src'), // set alias for webpack/hot while webpack has been prepacked 'webpack/hot': '@ice/bundles/compiled/webpack/hot', diff --git a/packages/ice/src/tasks/web/index.ts b/packages/ice/src/tasks/web/index.ts index 2282e1a55..ae7326c31 100644 --- a/packages/ice/src/tasks/web/index.ts +++ b/packages/ice/src/tasks/web/index.ts @@ -1,6 +1,6 @@ import * as path from 'path'; import type { Config } from '@ice/types'; -import { CACHE_DIR } from '../../constant.js'; +import { CACHE_DIR, RUNTIME_TMP_DIR } from '../../constant.js'; const getWebTask = ({ rootDir, command }): Config => { // basic task config of web task @@ -9,7 +9,7 @@ const getWebTask = ({ rootDir, command }): Config => { sourceMap: command === 'start' ? 'cheap-module-source-map' : false, cacheDir: path.join(rootDir, CACHE_DIR), alias: { - ice: path.join(rootDir, '.ice', 'index.ts'), + ice: path.join(rootDir, RUNTIME_TMP_DIR, 'index.ts'), '@': path.join(rootDir, 'src'), // set alias for webpack/hot while webpack has been prepacked 'webpack/hot': '@ice/bundles/compiled/webpack/hot', diff --git a/packages/ice/src/utils/ServerCompileTask.ts b/packages/ice/src/utils/ServerCompileTask.ts new file mode 100644 index 000000000..43a5040aa --- /dev/null +++ b/packages/ice/src/utils/ServerCompileTask.ts @@ -0,0 +1,18 @@ +import type { ServerCompiler } from '@ice/types/esm/plugin.js'; + +/** + * Get server compile promise task in middlewares or plugins. + */ +class ServerCompileTask { + private task: ReturnType; + + set(task: ReturnType) { + this.task = task; + } + + public async get() { + return this.task; + } +} + +export default ServerCompileTask; diff --git a/packages/ice/src/utils/runtimeEnv.ts b/packages/ice/src/utils/runtimeEnv.ts index 20b721a5e..dadb13cb7 100644 --- a/packages/ice/src/utils/runtimeEnv.ts +++ b/packages/ice/src/utils/runtimeEnv.ts @@ -3,8 +3,8 @@ import * as fs from 'fs'; import * as dotenv from 'dotenv'; import { expand as dotenvExpand } from 'dotenv-expand'; import type { CommandArgs, CommandName } from 'build-scripts'; +import type { AppConfig } from '@ice/types'; -export type AppConfig = Record; export interface Envs { [key: string]: string; } @@ -62,9 +62,6 @@ export async function initProcessEnv( export const updateRuntimeEnv = (appConfig: AppConfig, options: EnvOptions) => { const { disableRouter } = options; - if (!appConfig?.app?.getInitialData) { - process.env['ICE_CORE_INITIAL_DATA'] = 'false'; - } if (!appConfig?.app?.errorBoundary) { process.env['ICE_CORE_ERROR_BOUNDARY'] = 'false'; } diff --git a/packages/ice/src/webpack/ServerCompilerPlugin.ts b/packages/ice/src/webpack/ServerCompilerPlugin.ts new file mode 100644 index 000000000..ebe4c7d89 --- /dev/null +++ b/packages/ice/src/webpack/ServerCompilerPlugin.ts @@ -0,0 +1,29 @@ +import type { ExtendsPluginAPI, ServerCompiler } from '@ice/types/esm/plugin.js'; +import type { Compiler } from 'webpack'; + +const pluginName = 'ServerCompilerPlugin'; + +/** + * After compilation, compile the server entry. + */ +export default class ServerCompilerPlugin { + private serverCompiler: ServerCompiler; + private serverCompilerOptions: Parameters; + private serverCompileTask: ExtendsPluginAPI['serverCompileTask']; + + public constructor( + serverCompiler: ServerCompiler, + serverCompilerOptions: Parameters, + serverCompileTask: ExtendsPluginAPI['serverCompileTask'], + ) { + this.serverCompiler = serverCompiler; + this.serverCompilerOptions = serverCompilerOptions; + this.serverCompileTask = serverCompileTask; + } + + public apply(compiler: Compiler) { + compiler.hooks.emit.tap(pluginName, () => { + this.serverCompileTask.set(this.serverCompiler(...this.serverCompilerOptions)); + }); + } +} diff --git a/packages/runtime/package.json b/packages/runtime/package.json index e1d5aa1dd..aa152b074 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -10,7 +10,8 @@ "./client": "./esm/index.js", "./server": "./esm/index.server.js", "./jsx-runtime": "./esm/jsx-runtime.js", - "./jsx-dev-runtime": "./esm/jsx-dev-runtime.js" + "./jsx-dev-runtime": "./esm/jsx-dev-runtime.js", + "./matchRoutes": "./esm/matchRoutes.js" }, "files": [ "esm", diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts index 765f02a5e..8e44e3f56 100644 --- a/packages/runtime/src/index.ts +++ b/packages/runtime/src/index.ts @@ -35,14 +35,12 @@ import type { RouteWrapper, RenderMode, } from './types.js'; -import { matchRoutes } from './routes.js'; import dataLoader from './dataLoader.js'; import getAppConfig, { defineAppConfig } from './appConfig.js'; export { getAppConfig, defineAppConfig, - matchRoutes, Runtime, App, runClientApp, diff --git a/packages/runtime/src/matchRoutes.ts b/packages/runtime/src/matchRoutes.ts new file mode 100644 index 000000000..23bf820d1 --- /dev/null +++ b/packages/runtime/src/matchRoutes.ts @@ -0,0 +1,25 @@ +/** + * Notice: Don't write any top level expressions in this file because it may cause esm loaded cache. + */ +import type { Location } from 'history'; +import type { RouteObject } from 'react-router-dom'; +import { matchRoutes as originMatchRoutes } from 'react-router-dom'; +import { matchRoutesSingle } from './utils/history-single.js'; +import type { RouteItem, RouteMatch } from './types.js'; + +export default function matchRoutes( + routes: RouteItem[], + location: Partial | string, + basename?: string, +): RouteMatch[] { + const matchRoutesFn = process.env.ICE_CORE_ROUTER === 'true' ? originMatchRoutes : matchRoutesSingle; + let matches = matchRoutesFn(routes as unknown as RouteObject[], location, basename); + if (!matches) return []; + + return matches.map(({ params, pathname, pathnameBase, route }) => ({ + params, + pathname, + route: route as unknown as RouteItem, + pathnameBase, + })); +} diff --git a/packages/runtime/src/routes.tsx b/packages/runtime/src/routes.tsx index 413429031..97b862fb0 100644 --- a/packages/runtime/src/routes.tsx +++ b/packages/runtime/src/routes.tsx @@ -1,8 +1,4 @@ import React from 'react'; -import type { Location } from 'history'; -import type { RouteObject } from 'react-router-dom'; -import { matchRoutes as originMatchRoutes } from 'react-router-dom'; -import { matchRoutesSingle } from './utils/history-single.js'; import RouteWrapper from './RouteWrapper.js'; import type { RouteItem, RouteModules, RouteWrapperConfig, RouteMatch, RequestContext, RoutesConfig, RoutesData, RenderMode } from './types.js'; import { useAppContext } from './AppContext.js'; @@ -166,23 +162,6 @@ function RouteComponent({ id }: { id: string }) { return ; } -export function matchRoutes( - routes: RouteItem[], - location: Partial | string, - basename?: string, -): RouteMatch[] { - const matchRoutesFn = process.env.ICE_CORE_ROUTER === 'true' ? originMatchRoutes : matchRoutesSingle; - let matches = matchRoutesFn(routes as unknown as RouteObject[], location, basename); - if (!matches) return []; - - return matches.map(({ params, pathname, pathnameBase, route }) => ({ - params, - pathname, - route: route as unknown as RouteItem, - pathnameBase, - })); -} - /** * filter matches is new or path changed. */ diff --git a/packages/runtime/src/runClientApp.tsx b/packages/runtime/src/runClientApp.tsx index ac8aa9437..1542605fd 100644 --- a/packages/runtime/src/runClientApp.tsx +++ b/packages/runtime/src/runClientApp.tsx @@ -10,10 +10,11 @@ import type { AppContext, AppExport, RouteItem, AppRouterProps, RoutesData, RoutesConfig, RouteWrapperConfig, RuntimeModules, RouteMatch, ComponentWithChildren, RouteModules, } from './types.js'; -import { loadRouteModules, loadRoutesData, getRoutesConfig, matchRoutes, filterMatchesToLoad } from './routes.js'; +import { loadRouteModules, loadRoutesData, getRoutesConfig, filterMatchesToLoad } from './routes.js'; import { updateRoutesConfig } from './routesConfig.js'; import getRequestContext from './requestContext.js'; import getAppConfig from './appConfig.js'; +import matchRoutes from './matchRoutes.js'; interface RunClientAppOptions { app: AppExport; diff --git a/packages/runtime/src/runServerApp.tsx b/packages/runtime/src/runServerApp.tsx index e2851f454..b3649072e 100644 --- a/packages/runtime/src/runServerApp.tsx +++ b/packages/runtime/src/runServerApp.tsx @@ -8,7 +8,7 @@ import App from './App.js'; import { AppContextProvider } from './AppContext.js'; import getAppConfig from './appConfig.js'; import { DocumentContextProvider } from './Document.js'; -import { loadRouteModules, loadRoutesData, getRoutesConfig, matchRoutes } from './routes.js'; +import { loadRouteModules, loadRoutesData, getRoutesConfig } from './routes.js'; import { piperToString, renderToNodeStream } from './server/streamRender.js'; import { createStaticNavigator } from './server/navigator.js'; import type { NodeWritablePiper } from './server/streamRender.js'; @@ -23,6 +23,7 @@ import type { RenderMode, } from './types.js'; import getRequestContext from './requestContext.js'; +import matchRoutes from './matchRoutes.js'; interface RenderOptions { app: AppExport; diff --git a/packages/types/package.json b/packages/types/package.json index 619d38e8f..dce2b44f3 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -32,7 +32,7 @@ "devDependencies": { "@ice/route-manifest": "^1.0.0", "@ice/runtime": "^1.0.0", - "build-scripts": "^2.0.0-22", + "build-scripts": "^2.0.0-23", "esbuild": "^0.14.23", "eslint": "^8.14.0", "eslint-webpack-plugin": "3.1.1", diff --git a/packages/types/src/plugin.ts b/packages/types/src/plugin.ts index 3e490f20d..024ca7fe4 100644 --- a/packages/types/src/plugin.ts +++ b/packages/types/src/plugin.ts @@ -9,12 +9,15 @@ import type { ExportData, AddRenderFile, AddTemplateFiles } from './generator.js type AddExport = (exportData: ExportData) => void; type EventName = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir'; + +type ServerCompilerBuildOptions = Pick; export type ServerCompiler = ( - buildOptions: Pick< - BuildOptions, - 'minify' | 'inject' | 'format' | 'entryPoints' | 'outfile' | 'bundle' | 'outdir' | 'splitting' | 'platform' | 'outExtension' | 'plugins'>, - swcOptions?: Config['swcOptions'] -) => Promise; + buildOptions: ServerCompilerBuildOptions, + options?: { + swc?: Config['swcOptions']; + preBundle?: boolean; + } +) => Promise; export type WatchEvent = [ pattern: RegExp | string, event: (eventName: EventName, filePath: string) => void, @@ -76,6 +79,10 @@ export interface ExtendsPluginAPI { addEvent?: (watchEvent: WatchEvent) => void; removeEvent?: (name: string) => void; }; + serverCompileTask: { + set: (task: ReturnType) => void; + get: () => ReturnType; + }; } export interface OverwritePluginAPI extends ExtendsPluginAPI { diff --git a/packages/webpack-config/README.md b/packages/webpack-config/README.md index efe169b34..3c28388dc 100644 --- a/packages/webpack-config/README.md +++ b/packages/webpack-config/README.md @@ -2,12 +2,15 @@ This package providers basic webpack configuration. - ## Usage ```js import { getWebpackConfig } from '@ice/webpack-config'; +import webpack from 'webpack'; + const config = { alias: {} }; const rootDir = process.cwd(); -const webpackConfig = getWebpackConfig({ rootDir, config }); +const runtimeTmpDir = '.ice'; // the path of the asset-manifest.json + +const webpackConfig = getWebpackConfig({ rootDir, config, webpack, runtimeTmpDir }); ``` diff --git a/packages/webpack-config/package.json b/packages/webpack-config/package.json index 3bbf9cab6..0394383a4 100644 --- a/packages/webpack-config/package.json +++ b/packages/webpack-config/package.json @@ -27,7 +27,7 @@ }, "devDependencies": { "@ice/types": "^1.0.0", - "build-scripts": "^2.0.0-22", + "build-scripts": "^2.0.0-23", "esbuild": "^0.14.23", "webpack": "^5.73.0", "webpack-dev-server": "^4.7.4" diff --git a/packages/webpack-config/src/index.ts b/packages/webpack-config/src/index.ts index e6ec54785..f7f7d46f6 100644 --- a/packages/webpack-config/src/index.ts +++ b/packages/webpack-config/src/index.ts @@ -31,11 +31,12 @@ interface GetWebpackConfigOptions { rootDir: string; config: Config; webpack: typeof webpack; + runtimeTmpDir: string; } export type WebpackConfig = Configuration & { devServer?: DevServerConfiguration }; type GetWebpackConfig = (options: GetWebpackConfigOptions) => WebpackConfig; -function getEntry(rootDir: string) { +function getEntry(rootDir: string, runtimeTmpDir: string) { // check entry.client.ts let entryFile = fg.sync('entry.client.{tsx,ts,jsx.js}', { cwd: path.join(rootDir, 'src'), @@ -43,7 +44,7 @@ function getEntry(rootDir: string) { })[0]; if (!entryFile) { // use generated file in template directory - entryFile = path.join(rootDir, '.ice/entry.client.ts'); + entryFile = path.join(rootDir, runtimeTmpDir, 'entry.client.ts'); } // const dataLoaderFile = path.join(rootDir, '.ice/data-loader.ts'); @@ -54,7 +55,7 @@ function getEntry(rootDir: string) { }; } -const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack }) => { +const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack, runtimeTmpDir }) => { const { mode, define = {}, @@ -142,7 +143,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack }) => { topLevelAwait: true, ...(experimental || {}), }, - entry: entry || (() => getEntry(rootDir)), + entry: entry || (() => getEntry(rootDir, runtimeTmpDir)), externals, output: { publicPath, @@ -228,7 +229,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack }) => { }), assetsManifest && new AssetsManifestPlugin({ fileName: 'assets-manifest.json', - outputDir: path.join(rootDir, '.ice'), + outputDir: path.join(rootDir, runtimeTmpDir), }), analyzer && new BundleAnalyzerPlugin(), tsCheckerOptions && new ForkTsCheckerPlugin(tsCheckerOptions), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4327c0e67..d684c88cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -337,7 +337,7 @@ importers: acorn: ^8.7.1 address: ^1.1.2 body-parser: ^1.20.0 - build-scripts: ^2.0.0-22 + build-scripts: ^2.0.0-23 chalk: ^4.0.0 chokidar: ^3.5.3 commander: ^9.0.0 @@ -380,7 +380,7 @@ importers: acorn: 8.7.1 address: 1.1.2 body-parser: 1.20.0 - build-scripts: 2.0.0-22 + build-scripts: 2.0.0-23 chalk: 4.1.2 commander: 9.2.0 consola: 2.15.3 @@ -574,7 +574,7 @@ importers: specifiers: '@ice/route-manifest': ^1.0.0 '@ice/runtime': ^1.0.0 - build-scripts: ^2.0.0-22 + build-scripts: ^2.0.0-23 esbuild: ^0.14.23 eslint: ^8.14.0 eslint-webpack-plugin: 3.1.1 @@ -588,7 +588,7 @@ importers: devDependencies: '@ice/route-manifest': link:../route-manifest '@ice/runtime': link:../runtime - build-scripts: 2.0.0-22 + build-scripts: 2.0.0-23 esbuild: 0.14.38 eslint: 8.14.0 eslint-webpack-plugin: 3.1.1_7fh3pplfe77vb5lwiuqfjafe74 @@ -608,7 +608,7 @@ importers: '@pmmmwh/react-refresh-webpack-plugin': ^0.5.7 '@rollup/pluginutils': ^4.2.0 browserslist: ^4.19.3 - build-scripts: ^2.0.0-22 + build-scripts: ^2.0.0-23 consola: ^2.15.3 esbuild: ^0.14.23 fast-glob: ^3.2.11 @@ -634,7 +634,7 @@ importers: unplugin: 0.3.3_4upc34oiflw3lduyjvrzpjntau devDependencies: '@ice/types': link:../types - build-scripts: 2.0.0-22 + build-scripts: 2.0.0-23 esbuild: 0.14.38 webpack: 5.73.0_esbuild@0.14.38 webpack-dev-server: 4.8.1_webpack@5.73.0 @@ -7148,14 +7148,13 @@ packages: semver: 7.3.7 dev: true - /build-scripts/2.0.0-22: - resolution: {integrity: sha512-/MQR8quGXRsPlBCBL8AV6Srp2Q+aCHqo8Lr4F1FlNfQN6mqfYRPRlc7/YUe3jPMSHz/eGljXYcKrr9dJXK0uEA==} + /build-scripts/2.0.0-23: + resolution: {integrity: sha512-2hoh/Zhcjx1HuELEd3+tnuk8koN2aLgwZsXn2oJpGuAjf0IhsglzZKKyaVxFbkOstlKik0s4AA1tJsQTA4qVYA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: camelcase: 5.3.1 commander: 2.20.3 consola: 2.15.3 - deepmerge: 4.2.2 esbuild: 0.14.38 fast-glob: 3.2.11 fs-extra: 8.1.0 From db85f360da8d654e1ebcfd735752f973602a4577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B0=B4=E6=BE=9C?= Date: Wed, 13 Jul 2022 15:59:40 +0800 Subject: [PATCH 07/13] fix: basename in faas (#328) * fix: basename in faas * fix: if basename not exist * fix: type * fix: lint * fix: duplicate basename * feat: server only basename * fix: lint * fix: type * fix: basename order * fix: basename order --- packages/ice/src/utils/generateHTML.ts | 2 +- packages/ice/templates/entry.server.ts.ejs | 15 ++++++++------- packages/plugin-pha/src/manifestHelpers.ts | 5 ++++- packages/runtime/src/Document.tsx | 3 ++- packages/runtime/src/runClientApp.tsx | 6 ++++-- packages/runtime/src/runServerApp.tsx | 9 +++++++-- 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/ice/src/utils/generateHTML.ts b/packages/ice/src/utils/generateHTML.ts index 6c66151cc..a06771c8b 100644 --- a/packages/ice/src/utils/generateHTML.ts +++ b/packages/ice/src/utils/generateHTML.ts @@ -11,7 +11,6 @@ interface Options { entry: string; outputDir: string; documentOnly: boolean; - basename?: string; renderMode?: RenderMode; } @@ -50,6 +49,7 @@ export default async function generateHTML(options: Options) { const { value: html } = await serverEntry.renderToHTML(serverContext, { renderMode, documentOnly, + serverOnlyBasename: '/', }); const fileName = routePath === '/' ? 'index.html' : `${routePath}.html`; diff --git a/packages/ice/templates/entry.server.ts.ejs b/packages/ice/templates/entry.server.ts.ejs index 4dc3314d0..5a0a9cfd3 100644 --- a/packages/ice/templates/entry.server.ts.ejs +++ b/packages/ice/templates/entry.server.ts.ejs @@ -23,29 +23,29 @@ const setRuntimeEnv = (renderMode) => { interface RenderOptions { documentOnly?: boolean; renderMode?: RenderMode; + basename?: string; + serverOnlyBasename?: string; } export async function renderToHTML(requestContext, options: RenderOptions = {}) { - const { documentOnly, renderMode = 'SSR' } = options; + const { documentOnly, renderMode = 'SSR', basename, serverOnlyBasename } = options; setRuntimeEnv(renderMode); - const basename = getRouterBasename(); - // add basename for req.url so we don't need to add basename for mocked url - requestContext.req.url = `${basename}/${requestContext.req.url}`.replace(/\/+/g, '/'); return await runtime.renderToHTML(requestContext, { app, assetsManifest, routes, runtimeModules, Document, - basename, + serverOnlyBasename, + basename: basename || getRouterBasename(), documentOnly, renderMode, }); } export async function renderToResponse(requestContext, options: RenderOptions = {}) { - const { documentOnly, renderMode = 'SSR' } = options; + const { documentOnly, renderMode = 'SSR', basename, serverOnlyBasename } = options; setRuntimeEnv(options); runtime.renderToResponse(requestContext, { @@ -54,7 +54,8 @@ export async function renderToResponse(requestContext, options: RenderOptions = routes, runtimeModules, Document, - basename: getRouterBasename(), + serverOnlyBasename, + basename: basename || getRouterBasename(), documentOnly, renderMode, }); diff --git a/packages/plugin-pha/src/manifestHelpers.ts b/packages/plugin-pha/src/manifestHelpers.ts index 59f5d502d..9b302953d 100644 --- a/packages/plugin-pha/src/manifestHelpers.ts +++ b/packages/plugin-pha/src/manifestHelpers.ts @@ -113,7 +113,10 @@ async function renderPageDocument(routeId: string, serverEntry: string): Promise }, }; const serverModule = await import(serverEntry); - const { value } = await serverModule.renderToHTML(serverContext, true); + const { value } = await serverModule.renderToHTML(serverContext, { + documentOnly: true, + serverOnlyBasename: '/', + }); return value; } diff --git a/packages/runtime/src/Document.tsx b/packages/runtime/src/Document.tsx index 69b442e00..72c422a30 100644 --- a/packages/runtime/src/Document.tsx +++ b/packages/runtime/src/Document.tsx @@ -62,7 +62,7 @@ export function Links() { } export function Scripts() { - const { routesData, routesConfig, matches, assetsManifest, documentOnly, routeModules } = useAppContext(); + const { routesData, routesConfig, matches, assetsManifest, documentOnly, routeModules, basename } = useAppContext(); const routeScripts = getScripts(matches, routesConfig); const pageAssets = getPageAssets(matches, assetsManifest); @@ -79,6 +79,7 @@ export function Scripts() { appConfig: {}, matchedIds, routeModules, + basename, }; return ( diff --git a/packages/runtime/src/runClientApp.tsx b/packages/runtime/src/runClientApp.tsx index 1542605fd..2a01c13cd 100644 --- a/packages/runtime/src/runClientApp.tsx +++ b/packages/runtime/src/runClientApp.tsx @@ -31,16 +31,18 @@ export default async function runClientApp(options: RunClientAppOptions) { routes, runtimeModules, Document, - basename, + basename: defaultBasename, hydrate, } = options; const appContextFromServer: AppContext = (window as any).__ICE_APP_CONTEXT__ || {}; - let { routesData, routesConfig, assetsManifest } = appContextFromServer; + let { routesData, routesConfig, assetsManifest, basename: basenameFromServer } = appContextFromServer; const requestContext = getRequestContext(window.location); const appConfig = getAppConfig(app); + const basename = basenameFromServer || defaultBasename; + const matches = matchRoutes(routes, window.location, basename); const routeModules = await loadRouteModules(matches.map(({ route: { id, load } }) => ({ id, load }))); diff --git a/packages/runtime/src/runServerApp.tsx b/packages/runtime/src/runServerApp.tsx index b3649072e..2d4114bc5 100644 --- a/packages/runtime/src/runServerApp.tsx +++ b/packages/runtime/src/runServerApp.tsx @@ -33,7 +33,10 @@ interface RenderOptions { Document: ComponentWithChildren<{}>; documentOnly?: boolean; renderMode?: RenderMode; + // basename is used both for server and client, once set, it will be sync to client. basename?: string; + // serverOnlyBasename is used when just want to change basename for server. + serverOnlyBasename?: string; } interface Piper { @@ -122,13 +125,13 @@ function pipeToResponse(res: ServerResponse, pipe: NodeWritablePiper) { async function doRender(serverContext: ServerContext, renderOptions: RenderOptions): Promise { const { req } = serverContext; - const { routes, documentOnly, app, basename } = renderOptions; + const { routes, documentOnly, app, basename, serverOnlyBasename } = renderOptions; const location = getLocation(req.url); const requestContext = getRequestContext(location, serverContext); const appConfig = getAppConfig(app); - const matches = matchRoutes(routes, location, basename); + const matches = matchRoutes(routes, location, serverOnlyBasename || basename); if (!matches.length) { return render404(); @@ -267,6 +270,7 @@ function renderDocument(matches: RouteMatch[], options: RenderOptions, routeModu assetsManifest, app, Document, + basename, } = options; const routesData = null; @@ -282,6 +286,7 @@ function renderDocument(matches: RouteMatch[], options: RenderOptions, routeModu routes, documentOnly: true, routeModules, + basename, }; const documentContext = { From 7e7a3121af0e91407eec5ae2e0664d7089475429 Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Wed, 13 Jul 2022 17:58:53 +0800 Subject: [PATCH 08/13] chore: update version of postcss plugin (#352) --- packages/bundles/package.json | 2 +- pnpm-lock.yaml | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/bundles/package.json b/packages/bundles/package.json index d2c6a048e..51fe8559d 100644 --- a/packages/bundles/package.json +++ b/packages/bundles/package.json @@ -45,7 +45,7 @@ "postcss-loader": "6.2.1", "postcss-modules": "4.3.1", "postcss-nested": "5.0.6", - "postcss-plugin-rpx2vw": "^0.0.3", + "postcss-plugin-rpx2vw": "1.0.0", "postcss-preset-env": "7.4.3", "sass-loader": "12.6.0", "tapable": "2.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d684c88cd..57fc129da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -265,7 +265,7 @@ importers: postcss-loader: 6.2.1 postcss-modules: 4.3.1 postcss-nested: 5.0.6 - postcss-plugin-rpx2vw: ^0.0.3 + postcss-plugin-rpx2vw: 1.0.0 postcss-preset-env: 7.4.3 sass: 1.50.0 sass-loader: 12.6.0 @@ -307,7 +307,7 @@ importers: postcss-loader: 6.2.1_x2aj2q6umelkzhlylaf35s6ot4 postcss-modules: 4.3.1_postcss@8.4.12 postcss-nested: 5.0.6_postcss@8.4.12 - postcss-plugin-rpx2vw: 0.0.3 + postcss-plugin-rpx2vw: 1.0.0_postcss@8.4.12 postcss-preset-env: 7.4.3_postcss@8.4.12 sass-loader: 12.6.0_sass@1.50.0+webpack@5.73.0 tapable: 2.2.1 @@ -13881,10 +13881,12 @@ packages: postcss-value-parser: 4.2.0 dev: true - /postcss-plugin-rpx2vw/0.0.3: - resolution: {integrity: sha512-AxlNldVz3ECNqkyJOuytVAERQxkb2512XIOBIBHq/LvbrvmvvWrH10qIilEiBQ1ECxsQVhqO5lYtRIdg6e9iQA==} + /postcss-plugin-rpx2vw/1.0.0_postcss@8.4.12: + resolution: {integrity: sha512-iH+2s+FD0S9KFrqTCBrlfPoYpCmNxoeK5A9mWX7C9astId8gWSX4grnF+tkgWLQhTP7F+96Q6eLyX4/hI3xpDQ==} + peerDependencies: + postcss: ^8.0.0 dependencies: - postcss: 7.0.39 + postcss: 8.4.12 dev: true /postcss-preset-env/7.4.3_postcss@8.4.12: From bb24343b3514877028f3a2b4c6c6917664f36b9a Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Wed, 13 Jul 2022 19:34:48 +0800 Subject: [PATCH 09/13] feat: optimize log (#344) * fix: optimize webpack log * fix: merge error * chore: remove log * chore: optimize log * chore: optimize code --- packages/bundles/package.json | 1 + packages/bundles/scripts/tasks.ts | 2 +- packages/ice/src/commands/build.ts | 10 ++++- packages/ice/src/commands/start.ts | 14 ++++-- packages/ice/src/createService.ts | 30 +++++++++++-- packages/ice/src/service/webpackCompiler.ts | 44 ++++++++++-------- packages/ice/src/tasks/web/index.ts | 2 + packages/ice/src/utils/createSpinner.ts | 16 +++++++ packages/ice/src/utils/generateHTML.ts | 23 +--------- packages/ice/src/utils/getRoutePaths.ts | 23 ++++++++++ packages/types/src/config.ts | 2 + packages/webpack-config/src/index.ts | 50 ++++++++++++++++++--- pnpm-lock.yaml | 46 ++++++++++++++++++- 13 files changed, 205 insertions(+), 58 deletions(-) create mode 100644 packages/ice/src/utils/createSpinner.ts create mode 100644 packages/ice/src/utils/getRoutePaths.ts diff --git a/packages/bundles/package.json b/packages/bundles/package.json index 51fe8559d..82e731d6c 100644 --- a/packages/bundles/package.json +++ b/packages/bundles/package.json @@ -42,6 +42,7 @@ "less-loader": "10.2.0", "lodash": "4.17.21", "mini-css-extract-plugin": "2.6.0", + "ora": "5.4.1", "postcss-loader": "6.2.1", "postcss-modules": "4.3.1", "postcss-nested": "5.0.6", diff --git a/packages/bundles/scripts/tasks.ts b/packages/bundles/scripts/tasks.ts index 6b7dff679..b0de7a0f8 100644 --- a/packages/bundles/scripts/tasks.ts +++ b/packages/bundles/scripts/tasks.ts @@ -45,7 +45,7 @@ const tasks = [ 'less-loader', 'postcss-loader', 'sass-loader', 'css-loader', 'postcss-preset-env', 'postcss-nested', 'postcss-modules', 'postcss-plugin-rpx2vw', 'webpack-bundle-analyzer', 'es-module-lexer', 'terser', - 'eslint-webpack-plugin', 'copy-webpack-plugin', 'cacache', + 'eslint-webpack-plugin', 'copy-webpack-plugin', 'cacache', 'ora', ].map((pkgName) => ({ pkgName })), { // pack main package diff --git a/packages/ice/src/commands/build.ts b/packages/ice/src/commands/build.ts index 585d0f085..040d5311c 100644 --- a/packages/ice/src/commands/build.ts +++ b/packages/ice/src/commands/build.ts @@ -6,6 +6,7 @@ import type { StatsError } from 'webpack'; import type { Config } from '@ice/types'; import type { ServerCompiler } from '@ice/types/esm/plugin.js'; import webpack from '@ice/bundles/compiled/webpack/index.js'; +import type ora from '@ice/bundles/compiled/ora/index.js'; import webpackCompiler from '../service/webpackCompiler.js'; import formatWebpackMessages from '../utils/formatWebpackMessages.js'; import { RUNTIME_TMP_DIR, SERVER_ENTRY, SERVER_OUTPUT_DIR } from '../constant.js'; @@ -14,9 +15,13 @@ import emptyDir from '../utils/emptyDir.js'; const build = async ( context: Context, - taskConfigs: TaskConfig[], - serverCompiler: ServerCompiler, + options: { + taskConfigs: TaskConfig[]; + serverCompiler: ServerCompiler; + spinner: ora.Ora; + }, ) => { + const { taskConfigs, serverCompiler, spinner } = options; const { applyHook, commandArgs, command, rootDir, userConfig } = context; const webpackConfigs = taskConfigs.map(({ config }) => getWebpackConfig({ config, @@ -37,6 +42,7 @@ const build = async ( command, applyHook, serverCompiler, + spinner, }); const { ssg, ssr, server: { format } } = userConfig; // compile server bundle diff --git a/packages/ice/src/commands/start.ts b/packages/ice/src/commands/start.ts index 19b975619..663f5014c 100644 --- a/packages/ice/src/commands/start.ts +++ b/packages/ice/src/commands/start.ts @@ -8,6 +8,7 @@ import type { ExtendsPluginAPI, ServerCompiler } from '@ice/types/esm/plugin.js' import type { AppConfig, RenderMode } from '@ice/runtime'; import { getWebpackConfig } from '@ice/webpack-config'; import webpack from '@ice/bundles/compiled/webpack/index.js'; +import type ora from '@ice/bundles/compiled/ora/index.js'; import webpackCompiler from '../service/webpackCompiler.js'; import prepareURLs from '../utils/prepareURLs.js'; import createRenderMiddleware from '../middlewares/ssr/renderMiddleware.js'; @@ -20,10 +21,15 @@ const { merge } = lodash; const start = async ( context: Context, - taskConfigs: TaskConfig[], - serverCompiler: ServerCompiler, - appConfig: AppConfig, + options: { + taskConfigs: TaskConfig[]; + serverCompiler: ServerCompiler; + appConfig: AppConfig; + devPath: string; + spinner: ora.Ora; + }, ) => { + const { taskConfigs, serverCompiler, appConfig, devPath, spinner } = options; const { applyHook, commandArgs, command, rootDir, userConfig, extendsPluginAPI: { serverCompileTask } } = context; const { port, host, https = false } = commandArgs; @@ -117,6 +123,8 @@ const start = async ( command, applyHook, serverCompiler, + spinner, + devPath, }); const devServer = new WebpackDevServer(devServerConfig, compiler); devServer.startCallback(() => { diff --git a/packages/ice/src/createService.ts b/packages/ice/src/createService.ts index d9e5c515e..4dbac59ed 100644 --- a/packages/ice/src/createService.ts +++ b/packages/ice/src/createService.ts @@ -21,6 +21,8 @@ import { generateRoutesInfo } from './routes.js'; import getWebTask from './tasks/web/index.js'; import getDataLoaderTask from './tasks/web/data-loader.js'; import * as config from './config.js'; +import createSpinner from './utils/createSpinner.js'; +import getRoutePaths from './utils/getRoutePaths.js'; import { RUNTIME_TMP_DIR } from './constant.js'; import ServerCompileTask from './utils/ServerCompileTask.js'; @@ -33,6 +35,7 @@ interface CreateServiceOptions { } async function createService({ rootDir, command, commandArgs }: CreateServiceOptions) { + const buildSpinner = createSpinner('loading config...'); const templateDir = path.join(__dirname, '../templates/'); const configFile = 'ice.config.(mts|mjs|ts|js|cjs|json)'; const dataCache = new Map(); @@ -164,10 +167,29 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt return { run: async () => { - if (command === 'start') { - return await start(ctx, taskConfigs, serverCompiler, appConfig); - } else if (command === 'build') { - return await build(ctx, taskConfigs, serverCompiler); + try { + if (command === 'start') { + const routePaths = getRoutePaths(routesInfo.routes) + .sort((a, b) => + // Sort by length, shortest path first. + a.split('/').filter(Boolean).length - b.split('/').filter(Boolean).length); + return await start(ctx, { + taskConfigs, + serverCompiler, + appConfig, + devPath: (routePaths[0] || '').replace(/^\//, ''), + spinner: buildSpinner, + }); + } else if (command === 'build') { + return await build(ctx, { + taskConfigs, + serverCompiler, + spinner: buildSpinner, + }); + } + } catch (err) { + buildSpinner.stop(); + throw err; } }, }; diff --git a/packages/ice/src/service/webpackCompiler.ts b/packages/ice/src/service/webpackCompiler.ts index bbd076619..c295d9df2 100644 --- a/packages/ice/src/service/webpackCompiler.ts +++ b/packages/ice/src/service/webpackCompiler.ts @@ -1,4 +1,5 @@ import webpack from '@ice/bundles/compiled/webpack/index.js'; +import type ora from '@ice/bundles/compiled/ora/index.js'; import consola from 'consola'; import chalk from 'chalk'; import type { CommandArgs, TaskConfig } from 'build-scripts'; @@ -19,8 +20,20 @@ async function webpackCompiler(options: { rootDir: string; urls?: Urls; serverCompiler: ServerCompiler; + spinner: ora.Ora; + devPath?: string; }) { - const { taskConfigs, urls, applyHook, command, commandArgs, serverCompiler, webpackConfigs } = options; + const { + taskConfigs, + urls, + applyHook, + command, + commandArgs, + serverCompiler, + webpackConfigs, + spinner, + devPath, + } = options; await applyHook(`before.${command}.run`, { urls, commandArgs, @@ -28,6 +41,15 @@ async function webpackCompiler(options: { webpackConfigs, serverCompiler, }); + // Add default plugins for spinner + webpackConfigs[0].plugins.push((compiler: Compiler) => { + compiler.hooks.beforeCompile.tap('spinner', () => { + spinner.text = 'compiling...'; + }); + compiler.hooks.afterEmit.tap('spinner', () => { + spinner.stop(); + }); + }); let compiler: Compiler; try { // @ts-expect-error ignore error with different webpack referer @@ -50,19 +72,6 @@ async function webpackCompiler(options: { }); const messages = formatWebpackMessages(statsData); const isSuccessful = !messages.errors.length; - if (isSuccessful && !process.env.DISABLE_STATS) { - const assetsStatsOptions = { - errors: false, - warnings: false, - colors: true, - assets: true, - chunks: false, - entrypoints: false, - modules: false, - timings: false, - }; - consola.log(stats.toString(assetsStatsOptions)); - } if (messages.errors.length) { // Only keep the first error. Others are often indicative // of the same problem, but confuse the reader with noise. @@ -82,11 +91,11 @@ async function webpackCompiler(options: { let logoutMessage = '\n'; logoutMessage += chalk.green(' Starting the development server at:'); if (process.env.CLOUDIDE_ENV) { - logoutMessage += `\n - IDE server: https://${process.env.WORKSPACE_UUID}-${commandArgs.port}.${process.env.WORKSPACE_HOST}`; + logoutMessage += `\n - IDE server: https://${process.env.WORKSPACE_UUID}-${commandArgs.port}.${process.env.WORKSPACE_HOST}${devPath}`; } else { logoutMessage += `\n - - Local : ${chalk.underline.white(urls.localUrlForBrowser)} - - Network: ${chalk.underline.white(urls.lanUrlForTerminal)}`; + - Local : ${chalk.underline.white(urls.localUrlForBrowser)}${devPath} + - Network: ${chalk.underline.white(urls.lanUrlForTerminal)}${devPath}`; } consola.log(`${logoutMessage}\n`); @@ -107,7 +116,6 @@ async function webpackCompiler(options: { } if (isSuccessful) { - consola.success(`Compiled successfully in ${(statsData.children ? statsData.children[0] : statsData).time} ms`); // if compiled successfully reset first compile flag after been posted to lifecycle hooks isFirstCompile = false; } diff --git a/packages/ice/src/tasks/web/index.ts b/packages/ice/src/tasks/web/index.ts index ae7326c31..1b523cc5a 100644 --- a/packages/ice/src/tasks/web/index.ts +++ b/packages/ice/src/tasks/web/index.ts @@ -4,6 +4,7 @@ import { CACHE_DIR, RUNTIME_TMP_DIR } from '../../constant.js'; const getWebTask = ({ rootDir, command }): Config => { // basic task config of web task + const defaultLogging = command === 'start' ? 'summary' : 'summary assets'; return { mode: command === 'start' ? 'development' : 'production', sourceMap: command === 'start' ? 'cheap-module-source-map' : false, @@ -21,6 +22,7 @@ const getWebTask = ({ rootDir, command }): Config => { }, assetsManifest: true, fastRefresh: command === 'start', + logging: process.env.WEBPACK_LOGGING || defaultLogging, }; }; diff --git a/packages/ice/src/utils/createSpinner.ts b/packages/ice/src/utils/createSpinner.ts new file mode 100644 index 000000000..9972e69aa --- /dev/null +++ b/packages/ice/src/utils/createSpinner.ts @@ -0,0 +1,16 @@ +import ora from '@ice/bundles/compiled/ora/index.js'; + +export default function createSpinner( + text: string, + options: ora.Options = {}, +) { + const spinner = ora({ + text, + stream: process.stdout, + isEnabled: process.stdout.isTTY, + interval: 200, + ...options, + }); + spinner.start(); + return spinner; +} \ No newline at end of file diff --git a/packages/ice/src/utils/generateHTML.ts b/packages/ice/src/utils/generateHTML.ts index a06771c8b..067b34bb6 100644 --- a/packages/ice/src/utils/generateHTML.ts +++ b/packages/ice/src/utils/generateHTML.ts @@ -3,8 +3,8 @@ import type { Request } from 'webpack-dev-server'; import fse from 'fs-extra'; import consola from 'consola'; import type { ServerContext, RenderMode } from '@ice/runtime'; -import type { RouteObject } from 'react-router'; import { ROUTER_MANIFEST } from '../constant.js'; +import getRoutePaths from './getRoutePaths.js'; interface Options { rootDir: string; @@ -34,7 +34,7 @@ export default async function generateHTML(options: Options) { // Read the latest routes info. const routeManifest = path.join(rootDir, ROUTER_MANIFEST); const routes = JSON.parse(fse.readFileSync(routeManifest, 'utf8')); - const paths = getPaths(routes); + const paths = getRoutePaths(routes); for (let i = 0, n = paths.length; i < n; i++) { const routePath = paths[i]; @@ -61,22 +61,3 @@ export default async function generateHTML(options: Options) { await fse.writeFile(contentPath, html); } } - -/** - * get all route path - * @param routes - * @returns - */ -function getPaths(routes: RouteObject[], parentPath = ''): string[] { - let pathList = []; - - routes.forEach(route => { - if (route.children) { - pathList = pathList.concat(getPaths(route.children, route.path)); - } else { - pathList.push(path.join('/', parentPath, route.path || '')); - } - }); - - return pathList; -} diff --git a/packages/ice/src/utils/getRoutePaths.ts b/packages/ice/src/utils/getRoutePaths.ts new file mode 100644 index 000000000..fa403a536 --- /dev/null +++ b/packages/ice/src/utils/getRoutePaths.ts @@ -0,0 +1,23 @@ +import * as path from 'path'; +import type { RouteObject } from 'react-router'; + +/** + * get all route path + * @param routes + * @returns + */ +function getRoutePaths(routes: RouteObject[], parentPath = ''): string[] { + let pathList = []; + + routes.forEach(route => { + if (route.children) { + pathList = pathList.concat(getRoutePaths(route.children, route.path)); + } else { + pathList.push(path.join('/', parentPath, route.path || '')); + } + }); + + return pathList; +} + +export default getRoutePaths; diff --git a/packages/types/src/config.ts b/packages/types/src/config.ts index dff297aa2..91eddba50 100644 --- a/packages/types/src/config.ts +++ b/packages/types/src/config.ts @@ -109,4 +109,6 @@ export interface Config { fastRefresh?: boolean; basename?: string; + + logging?: string; } diff --git a/packages/webpack-config/src/index.ts b/packages/webpack-config/src/index.ts index f7f7d46f6..e52eec352 100644 --- a/packages/webpack-config/src/index.ts +++ b/packages/webpack-config/src/index.ts @@ -11,7 +11,7 @@ import TerserPlugin from '@ice/bundles/compiled/terser-webpack-plugin/index.js'; import ForkTsCheckerPlugin from '@ice/bundles/compiled/fork-ts-checker-webpack-plugin/index.js'; import ESlintPlugin from '@ice/bundles/compiled/eslint-webpack-plugin/index.js'; import CopyPlugin from '@ice/bundles/compiled/copy-webpack-plugin/index.js'; -import type { Configuration, WebpackPluginInstance } from 'webpack'; +import type { Configuration, WebpackPluginInstance, Compiler } from 'webpack'; import type webpack from 'webpack'; import type { Configuration as DevServerConfiguration } from 'webpack-dev-server'; import type { Config } from '@ice/types'; @@ -84,6 +84,7 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack, runtimeT concatenateModules, devServer, fastRefresh, + logging, } = config; const absoluteOutputDir = path.isAbsolute(outputDir) ? outputDir : path.join(rootDir, outputDir); const dev = mode !== 'production'; @@ -298,12 +299,47 @@ const getWebpackConfig: GetWebpackConfig = ({ rootDir, config, webpack, runtimeT webpackConfig.optimization.usedExports = false; } - if (process.env.WEBPACK_LOGGING) { - webpackConfig.infrastructureLogging = { - level: 'verbose', - debug: /FileSystemInfo/, - }; - webpackConfig.stats = 'verbose'; + if (logging) { + const infra = logging.includes('infrastructure'); + const profile = logging.includes('profile'); + const summary = logging.includes('summary'); + const assets = logging.includes('assets'); + + if (infra) { + webpackConfig.infrastructureLogging = { + level: 'verbose', + debug: /FileSystemInfo/, + }; + webpackConfig.stats = 'verbose'; + } + + if (profile || summary) { + webpackConfig.plugins!.push((compiler: Compiler) => { + compiler.hooks.done.tap('webpack-logging', (stats) => { + console.log( + stats.toString(profile ? { + colors: true, + logging: 'verbose', + } : { + preset: 'summary', + assets, + colors: true, + timings: true, + }), + ); + }); + }); + } + + if (profile) { + const ProgressPlugin = webpack.ProgressPlugin as typeof webpack.ProgressPlugin; + webpackConfig.plugins!.push( + new ProgressPlugin({ + profile: true, + }), + ); + webpackConfig.profile = true; + } } // pipe webpack by built-in functions and custom functions diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57fc129da..15cd6879e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -261,6 +261,7 @@ importers: less-loader: 10.2.0 lodash: 4.17.21 mini-css-extract-plugin: 2.6.0 + ora: 5.4.1 postcss: 8.4.12 postcss-loader: 6.2.1 postcss-modules: 4.3.1 @@ -304,6 +305,7 @@ importers: less-loader: 10.2.0_less@4.1.2+webpack@5.73.0 lodash: 4.17.21 mini-css-extract-plugin: 2.6.0_webpack@5.73.0 + ora: 5.4.1 postcss-loader: 6.2.1_x2aj2q6umelkzhlylaf35s6ot4 postcss-modules: 4.3.1_postcss@8.4.12 postcss-nested: 5.0.6_postcss@8.4.12 @@ -7448,7 +7450,11 @@ packages: engines: {node: '>=8'} dependencies: restore-cursor: 3.1.0 - dev: false + + /cli-spinners/2.6.1: + resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} + engines: {node: '>=6'} + dev: true /cli-table3/0.6.2: resolution: {integrity: sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==} @@ -7491,6 +7497,11 @@ packages: dependencies: mimic-response: 1.0.1 + /clone/1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + /clsx/1.1.1: resolution: {integrity: sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==} engines: {node: '>=6'} @@ -8476,6 +8487,12 @@ packages: dependencies: execa: 5.1.1 + /defaults/1.0.3: + resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==} + dependencies: + clone: 1.0.4 + dev: true + /defer-to-connect/1.1.3: resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==} @@ -11285,6 +11302,11 @@ packages: global-dirs: 3.0.0 is-path-inside: 3.0.3 + /is-interactive/1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + /is-ip/3.1.0: resolution: {integrity: sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==} engines: {node: '>=8'} @@ -12646,6 +12668,21 @@ packages: word-wrap: 1.2.3 dev: true + /ora/5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.6.1 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + /os-tmpdir/1.0.2: resolution: {integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=} engines: {node: '>=0.10.0'} @@ -15259,7 +15296,6 @@ packages: dependencies: onetime: 5.1.2 signal-exit: 3.0.7 - dev: false /retry/0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} @@ -17390,6 +17426,12 @@ packages: dependencies: minimalistic-assert: 1.0.1 + /wcwidth/1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.3 + dev: true + /web-namespaces/1.1.4: resolution: {integrity: sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==} From 59aed85a5467600a0ed767d43b7151d61fac14dc Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Thu, 14 Jul 2022 09:56:56 +0800 Subject: [PATCH 10/13] feat: support swc options for plugin-rax-compat and onappear on rax-compat (#349) * feat: support swc options for plugin-rax-compat * chore: example * test: fix test case * test: fix test case * test: fix test case * fix: outputdir * fix: onappear for no ref cases * fix: merge options * fix: appear polyfill * chore: remove appear polyfill dependency * fix: add swc helpers * fix: onappear on rax-compat * refactor: format code and not to use react.frowardRef Co-authored-by: ZeroLing --- examples/basic-project/ice.config.mts | 3 +- examples/basic-project/package.json | 5 - examples/rax-project/.browserslistrc | 1 + examples/rax-project/ice.config.mts | 9 + examples/rax-project/package.json | 30 + examples/rax-project/public/favicon.ico | Bin 0 -> 2719 bytes examples/rax-project/src/app.tsx | 7 + .../src/components/Logo/index.jsx | 0 .../src/components/Logo/index.module.css | 0 examples/rax-project/src/document.tsx | 22 + examples/rax-project/src/global.css | 3 + .../src/pages/index.jsx} | 0 .../rax-project/src/pages/index.module.css | 25 + examples/rax-project/src/typings.d.ts | 14 + examples/rax-project/tsconfig.json | 32 + packages/plugin-pha/src/index.ts | 2 +- packages/plugin-rax-compat/package.json | 1 + packages/plugin-rax-compat/src/index.ts | 15 + packages/rax-compat/package.json | 2 +- packages/rax-compat/src/create-element.ts | 100 +- .../rax-compat/src/intersection-observer.js | 652 +++++++ packages/rax-compat/src/visibility.ts | 124 ++ .../rax-compat/tests/createElement.test.tsx | 2 +- packages/types/package.json | 5 +- packages/types/src/config.ts | 2 + .../src/unPlugins/compilation.ts | 4 +- pnpm-lock.yaml | 1601 ++++++++++------- tests/integration/rax-project.test.ts | 41 + tests/utils/build.ts | 7 +- 29 files changed, 1968 insertions(+), 741 deletions(-) create mode 100644 examples/rax-project/.browserslistrc create mode 100644 examples/rax-project/ice.config.mts create mode 100644 examples/rax-project/package.json create mode 100644 examples/rax-project/public/favicon.ico create mode 100644 examples/rax-project/src/app.tsx rename examples/{basic-project => rax-project}/src/components/Logo/index.jsx (100%) rename examples/{basic-project => rax-project}/src/components/Logo/index.module.css (100%) create mode 100644 examples/rax-project/src/document.tsx create mode 100644 examples/rax-project/src/global.css rename examples/{basic-project/src/pages/rax.jsx => rax-project/src/pages/index.jsx} (100%) create mode 100644 examples/rax-project/src/pages/index.module.css create mode 100644 examples/rax-project/src/typings.d.ts create mode 100644 examples/rax-project/tsconfig.json create mode 100644 packages/rax-compat/src/intersection-observer.js create mode 100644 packages/rax-compat/src/visibility.ts create mode 100644 tests/integration/rax-project.test.ts diff --git a/examples/basic-project/ice.config.mts b/examples/basic-project/ice.config.mts index 4586ac1cc..90c4f9d03 100644 --- a/examples/basic-project/ice.config.mts +++ b/examples/basic-project/ice.config.mts @@ -1,7 +1,6 @@ import { defineConfig } from '@ice/app'; import SpeedMeasurePlugin from 'speed-measure-webpack-plugin'; import auth from '@ice/plugin-auth'; -import compatRax from '@ice/plugin-rax-compat'; export default defineConfig({ publicPath: '/', @@ -22,6 +21,6 @@ export default defineConfig({ return webpackConfig; }, dropLogLevel: 'warn', - plugins: [auth(), compatRax()], + plugins: [auth()], eslint: true, }); diff --git a/examples/basic-project/package.json b/examples/basic-project/package.json index 7c13ea4bd..dc1fd2aae 100644 --- a/examples/basic-project/package.json +++ b/examples/basic-project/package.json @@ -14,11 +14,6 @@ "@ice/plugin-rax-compat": "workspace:*", "@ice/runtime": "workspace:*", "ahooks": "^3.3.8", - "rax": "^1.2.2", - "rax-image": "^2.4.1", - "rax-is-valid-element": "^1.0.0", - "rax-text": "^2.2.0", - "rax-view": "^2.3.0", "react": "^18.0.0", "react-dom": "^18.0.0" }, diff --git a/examples/rax-project/.browserslistrc b/examples/rax-project/.browserslistrc new file mode 100644 index 000000000..7637baddc --- /dev/null +++ b/examples/rax-project/.browserslistrc @@ -0,0 +1 @@ +chrome 55 \ No newline at end of file diff --git a/examples/rax-project/ice.config.mts b/examples/rax-project/ice.config.mts new file mode 100644 index 000000000..de6cbd325 --- /dev/null +++ b/examples/rax-project/ice.config.mts @@ -0,0 +1,9 @@ +import { defineConfig } from '@ice/app'; +import compatRax from '@ice/plugin-rax-compat'; + +export default defineConfig({ + ssr: false, + ssg: false, + publicPath: '/', + plugins: [compatRax()], +}); diff --git a/examples/rax-project/package.json b/examples/rax-project/package.json new file mode 100644 index 000000000..98d2eb2b7 --- /dev/null +++ b/examples/rax-project/package.json @@ -0,0 +1,30 @@ +{ + "name": "rax-project", + "version": "1.0.0", + "scripts": { + "start": "ice start", + "build": "ice build" + }, + "description": "", + "author": "", + "license": "MIT", + "dependencies": { + "@ice/app": "workspace:*", + "@ice/plugin-rax-compat": "workspace:*", + "@ice/runtime": "workspace:*", + "rax": "^1.2.2", + "rax-image": "^2.4.1", + "rax-is-valid-element": "^1.0.0", + "rax-text": "^2.2.0", + "rax-view": "^2.3.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.2", + "browserslist": "^4.19.3", + "regenerator-runtime": "^0.13.9", + "webpack": "^5.73.0" + } +} diff --git a/examples/rax-project/public/favicon.ico b/examples/rax-project/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a2605c57e9d85aabd689ff5c565286dee148ab6d GIT binary patch literal 2719 zcmbVO`8yMiA9svQv58DRxk@YN91}_`b4{U4xk7!C`zZN1)+bw`g+vn_YM5h6q=V&5 zY&mjF?i^!|S(r95*X&b&!uR`np7;CpJg?XDeqPV>{^^x+*4bW0T3K2|L_`MVVB`9m z^Z$&LFJVfVn*0@o`Uz6v;qRJkbcT zDz0Q12lTZ%`ghogFZaE+CzC-?b?9FC>?D|Pkd}eIbR7dOXL}DpS5J}aua3Bq7}H>3 z8Og;>eXE)t$2j*0A8+@``?d@C5+r!O_l|zaGtfJqEVzm*-TcP@xe{qr(<>BvWYfnOA_I+w&Y*YLR6D?M(%fv^^ylDNyqy>P1;<>wK^T+^*ewX1F*_vqxLT{VuTwPl_xOnH+!=f&y+_wjGs5N)( zIwZ0G zVGDjn#KgnB&u8q{TCQ(JV{CoGszvgBKP2U=F>)r@Dd4e=_(ruDP;4@M8F1kb3KIcNh8el;^6SjxPb7UgHpr7VfQ{=QKLXR9T}an41j9LX(*&x z-s#Okyn>i7`hll*yEa0SH(77uC0SJod(1wZCZLG$IX8 zgg3YePH-pHznZz=(oROkAeRf08LlBU$+*P0OW%>UC7k&8KMHpwmfDk`%76o_!Ai5Q zv)lzh<8xj&BbK%Y*OQ66ME|)KPtGM~9a&2KcW&o<8==OD`^n_3dOjy-R&Dl$5-+l* zJk2a{$R7I*qYCI3d|S*C82Dj`%fgc&G38RV+WC_$Yb{Uz={03hE-uD{=}iJUvPZc@ zt@}G;<>y$*@SltoJE~focFsZ_%Vbscb&wTfMg7u*ewX*sdAFmh*0k%&US4YBUcE7I zS*M!n8G80JPMI?e(Kh;8I!0u|uubOc~y^z<%yrpt0`9F!ItogT=I31$ZGr>Mw-+qHLv=|9sm zqSffY$EJ3d$F3s{wZ^iI$ORCwgCovV*z7IJR_1c20|(Pu``hy5BR9x; zj`h)HANSU`uiHrH1al^C++E+4k-F#40F8fOzDsC(0Xs_TfF_ULf!|_ydeL)|a1Jro z`}oH|*+3cJgt{U(L5hV1`U2z}RHY)-m_|6j3|=SDC%ammwfd@xib@hygHkVx9b`lO z?$3^18)@?D*+AOx0ZjHT`-U6{Gw5FzvfmkN3 z>iM1+Vy@*`o~eUlNbT~YRw;AfVZk*Rzhw{rfS>9?r{1t{Jz0+mb{haKPbYZv5|eNn z{VNt9&hCNNqdZGqsVPQ278pp2rceA9wQu#Hu@5G@9)y1mxhlAJgx^x41b|O)>(hC6 zxd+|P4EGtQlBdYei{4G+%Yjm*!k3gG4k^VNrm%6MB+4qxbr8fSZ)yPg8T}_ZJT+IP zPp>P*QW*+sNU72cez@>5*Y{~{N`ykK-2%RGGE`#c5`~cR(bxhgHm7@CaT!_8+Mjy; zHnG=2&MHd)7E?Cz8+Avg7#vT&{UEqr*A$6pnRzmfOtWn~ryvDmrNp@=;|j;Q`*Pf~ z0wA-DHO_2Rx{kE?x=eA}-pcZLRF1s-8H3LN$F?iILXGiax~+Tq(*AT!Z$j3GqT~QM zDJ`F4Bhc|j5w71Oqzj^ZTcN0e;k$t-6jDX82_cvM&yKe5hu z{TF*|*%zp_PJCQ=e=%NMFhSpL9&+)wS_~GOdp1WOv0%r%V44FAam3hgp7A%Eqw9j7 zIXBU3EgbRndo#+!1Zz8t$)d)OHLuyV&l1PAn?smen<&|-$OZu2@8QTn+MFr)m3y5- zfPE&Ulh$|uf)x((@(gCxmst)n0lNsHVHV1vQ#pvcm1a`CF zS@fp^M4vE;eKx|G*CXdsmp&Wt1mx%QJo>M(<&}@+-#Hn(j8=1Slj$Qe+2o-f9!SL> zEHKc%kW6BqCu-JR%k3tZRt?x>Bi-k>>pFEKlwy7na65EDm3*q_CZ5vQlsF&RSHHAk zHG23^LvvqA)%5Kw(48PmI=s$K?gnb-%=m$(j$Z$1A5lTUkx;d$vpI=C9~KSm?z_~c z#SXvKTSJ~$>E(6?fHXpHU_&wdoa3=(dgo@B&oO~(nr*w#-l#{yhr6ZiG zDK@Pu;rBB-zUnG5K`1`LFFgGPx93J zo=uIxw8w{%Ah89CE zG%Z{%x-c=Q%W~)VcuxU+8@pZ@!$84eF)sG~iycG%+E-hae$E0JnM{rKv6SObgAvd= zaAXfwR)*@t?uUq zrv8D1TZTqxkCAXZq(WAY7Ogs8eUtXYJ4IS4%)&D|9^+Qd3!h**T4=;BlDsFb@~YaS zs8Ks~*8$jS{|`e^1EWtdZ4QHH1}etRcJfqc7dId05z9J`2!%ttHP;`wI>YxHjW8Z1 ztxy7L7%x$L(!+>)q|FupVfw;o&5+IA4Oi_6Kadib+iKTi>Ozfzo9y&%QVVV literal 0 HcmV?d00001 diff --git a/examples/rax-project/src/app.tsx b/examples/rax-project/src/app.tsx new file mode 100644 index 000000000..1ceb78f30 --- /dev/null +++ b/examples/rax-project/src/app.tsx @@ -0,0 +1,7 @@ +import { defineAppConfig } from 'ice'; + +export default defineAppConfig({ + app: { + rootId: 'app', + }, +}); diff --git a/examples/basic-project/src/components/Logo/index.jsx b/examples/rax-project/src/components/Logo/index.jsx similarity index 100% rename from examples/basic-project/src/components/Logo/index.jsx rename to examples/rax-project/src/components/Logo/index.jsx diff --git a/examples/basic-project/src/components/Logo/index.module.css b/examples/rax-project/src/components/Logo/index.module.css similarity index 100% rename from examples/basic-project/src/components/Logo/index.module.css rename to examples/rax-project/src/components/Logo/index.module.css diff --git a/examples/rax-project/src/document.tsx b/examples/rax-project/src/document.tsx new file mode 100644 index 000000000..c4cb093d9 --- /dev/null +++ b/examples/rax-project/src/document.tsx @@ -0,0 +1,22 @@ +import { Meta, Title, Links, Main, Scripts } from 'ice'; + +function Document() { + return ( + + + + + + + + <Links /> + </head> + <body> + <Main /> + <Scripts /> + </body> + </html> + ); +} + +export default Document; diff --git a/examples/rax-project/src/global.css b/examples/rax-project/src/global.css new file mode 100644 index 000000000..604282adc --- /dev/null +++ b/examples/rax-project/src/global.css @@ -0,0 +1,3 @@ +body { + font-size: 14px; +} diff --git a/examples/basic-project/src/pages/rax.jsx b/examples/rax-project/src/pages/index.jsx similarity index 100% rename from examples/basic-project/src/pages/rax.jsx rename to examples/rax-project/src/pages/index.jsx diff --git a/examples/rax-project/src/pages/index.module.css b/examples/rax-project/src/pages/index.module.css new file mode 100644 index 000000000..679273d44 --- /dev/null +++ b/examples/rax-project/src/pages/index.module.css @@ -0,0 +1,25 @@ +.title { + color: red; + margin-left: 10rpx; +} + +.data { + margin-top: 10px; +} + +.homeContainer { + align-items: center; + margin-top: 200rpx; +} + +.homeTitle { + font-size: 45rpx; + font-weight: bold; + margin: 20rpx 0; +} + +.homeInfo { + font-size: 36rpx; + margin: 8rpx 0; + color: #555; +} diff --git a/examples/rax-project/src/typings.d.ts b/examples/rax-project/src/typings.d.ts new file mode 100644 index 000000000..b2780a236 --- /dev/null +++ b/examples/rax-project/src/typings.d.ts @@ -0,0 +1,14 @@ +declare module '*.module.less' { + const classes: { [key: string]: string }; + export default classes; +} + +declare module '*.module.css' { + const classes: { [key: string]: string }; + export default classes; +} + +declare module '*.module.scss' { + const classes: { [key: string]: string }; + export default classes; +} diff --git a/examples/rax-project/tsconfig.json b/examples/rax-project/tsconfig.json new file mode 100644 index 000000000..7f2f2ffce --- /dev/null +++ b/examples/rax-project/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compileOnSave": false, + "buildOnSave": false, + "compilerOptions": { + "baseUrl": ".", + "outDir": "build", + "module": "esnext", + "target": "es6", + "jsx": "react-jsx", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "lib": ["es6", "dom"], + "sourceMap": true, + "allowJs": true, + "rootDir": "./", + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": false, + "importHelpers": true, + "strictNullChecks": true, + "suppressImplicitAnyIndexErrors": true, + "noUnusedLocals": true, + "skipLibCheck": true, + "paths": { + "@/*": ["./src/*"], + "ice": [".ice"] + } + }, + "include": ["src", ".ice", "ice.config.*"], + "exclude": ["node_modules", "build", "public"] +} \ No newline at end of file diff --git a/packages/plugin-pha/src/index.ts b/packages/plugin-pha/src/index.ts index bc71c3abc..07ef0eeca 100644 --- a/packages/plugin-pha/src/index.ts +++ b/packages/plugin-pha/src/index.ts @@ -43,7 +43,7 @@ const plugin: Plugin<PluginOptions> = ({ onGetConfig, onHook, context, generator // Get server compiler by hooks onHook(`before.${command as 'start' | 'build'}.run`, async ({ serverCompiler, taskConfigs, urls }) => { const taskConfig = taskConfigs.find(({ name }) => name === 'web').config; - outputDir = taskConfig.outputDir; + outputDir = path.isAbsolute(taskConfig.outputDir) ? taskConfig.outputDir : path.join(rootDir, taskConfig.outputDir); // Need absolute path for pha dev. publicPath = command === 'start' ? getDevPath(urls.lanUrlForTerminal) : (taskConfig.publicPath || '/'); diff --git a/packages/plugin-rax-compat/package.json b/packages/plugin-rax-compat/package.json index 471d23046..0bbc0d14d 100644 --- a/packages/plugin-rax-compat/package.json +++ b/packages/plugin-rax-compat/package.json @@ -18,6 +18,7 @@ ], "dependencies": { "consola": "^2.15.3", + "lodash.merge": "^4.6.2", "rax-compat": "^0.1.0", "stylesheet-loader": "^0.9.1" }, diff --git a/packages/plugin-rax-compat/src/index.ts b/packages/plugin-rax-compat/src/index.ts index 91f17d9a4..3c8611da6 100644 --- a/packages/plugin-rax-compat/src/index.ts +++ b/packages/plugin-rax-compat/src/index.ts @@ -2,6 +2,7 @@ import { createRequire } from 'module'; import type { Plugin } from '@ice/types'; import type { RuleSetRule } from 'webpack'; import consola from 'consola'; +import merge from 'lodash.merge'; const require = createRequire(import.meta.url); @@ -33,6 +34,20 @@ let warnOnce = false; function getPlugin(options: CompatRaxOptions): Plugin { return ({ onGetConfig }) => { onGetConfig((config) => { + // Reset jsc.transform.react.runtime to classic. + config.swcOptions = merge(config.swcOptions || {}, { + compilationConfig: { + jsc: { + transform: { + react: { + runtime: 'classic', + pragma: 'createElement', + pragmaFrag: 'Fragment', + }, + }, + }, + }, + }); Object.assign(config.alias, alias); if (options.inlineStyle) { if (!warnOnce) { diff --git a/packages/rax-compat/package.json b/packages/rax-compat/package.json index 2ec88271a..404cc5e2d 100644 --- a/packages/rax-compat/package.json +++ b/packages/rax-compat/package.json @@ -45,7 +45,7 @@ "compat" ], "dependencies": { - "appear-polyfill": "^0.1.2", + "@swc/helpers": "^0.4.3", "style-unit": "^3.0.4", "create-react-class": "^15.7.0" }, diff --git a/packages/rax-compat/src/create-element.ts b/packages/rax-compat/src/create-element.ts index 340a9863f..3d23bc5f7 100644 --- a/packages/rax-compat/src/create-element.ts +++ b/packages/rax-compat/src/create-element.ts @@ -5,19 +5,11 @@ import type { ReactNode, RefObject, } from 'react'; -import { createElement as _createElement, useEffect, forwardRef } from 'react'; -import { setupAppear } from 'appear-polyfill'; +import { createElement as _createElement, useEffect, useCallback, useRef } from 'react'; import { cached, convertUnit } from 'style-unit'; +import { observerElement } from './visibility'; import { isFunction, isObject, isNumber } from './type'; -let appearSetup = false; -function setupAppearOnce() { - if (!appearSetup) { - setupAppear(); - appearSetup = true; - } -} - // https://github.com/alibaba/rax/blob/master/packages/driver-dom/src/index.js // opacity -> opa // fontWeight -> ntw @@ -34,7 +26,6 @@ function setupAppearOnce() { // borderImageOutset|borderImageSlice|borderImageWidth -> erim const NON_DIMENSIONAL_REG = /opa|ntw|ne[ch]|ex(?:s|g|n|p|$)|^ord|zoo|grid|orp|ows|mnc|^columns$|bs|erim|onit/i; - /** * Compat createElement for rax export. * Reference: https://github.com/alibaba/rax/blob/master/packages/rax/src/createElement.js#L13 @@ -53,8 +44,11 @@ export function createElement<P extends { type: FunctionComponent<P> | string, props?: Attributes & P | null, ...children: ReactNode[]): ReactElement { + // Get a shallow copy of props, to avoid mutating the original object. const rest = Object.assign({}, props); const { onAppear, onDisappear } = rest; + + // Delete props that are not allowed in react. delete rest.onAppear; delete rest.onDisappear; @@ -64,21 +58,53 @@ export function createElement<P extends { rest.style = compatStyleProps; } - // Create backend element. - const args = [type, rest]; - let element: any = _createElement.apply(null, args.concat(children as any)); - - // Polyfill for appear and disappear event. + // Compat for visibility events. if (isFunction(onAppear) || isFunction(onDisappear)) { - setupAppearOnce(); - element = _createElement(forwardRef(AppearOrDisappear), { - onAppear: onAppear, - onDisappear: onDisappear, - ref: rest.ref, - }, element); + return _createElement( + VisibilityChange, + { + onAppear, + onDisappear, + // Passing child ref to `VisibilityChange` to avoid creating a new ref. + childRef: rest.ref, + // Using forwardedRef as a prop to the backend react element. + forwardRef: (ref: RefObject<any>) => _createElement(type, Object.assign({ ref }, rest), ...children), + }, + ); + } else { + return _createElement(type, rest, ...children); } +} + +function VisibilityChange({ + onAppear, + onDisappear, + childRef, + forwardRef, +}: any) { + const fallbackRef = useRef(null); // `fallbackRef` used if `childRef` is not provided. + const ref = childRef || fallbackRef; + + const listen = useCallback((eventName: string, handler: Function) => { + const { current } = ref; + if (current != null) { + if (isFunction(handler)) { + observerElement(current as HTMLElement); + current.addEventListener(eventName, handler); + } + } + return () => { + const { current } = ref; + if (current) { + current.removeEventListener(eventName, handler); + } + }; + }, [ref]); + + useEffect(() => listen('appear', onAppear), [ref, onAppear, listen]); + useEffect(() => listen('disappear', onDisappear), [ref, onDisappear, listen]); - return element; + return forwardRef(ref); } const isDimensionalProp = cached((prop: string) => !NON_DIMENSIONAL_REG.test(prop)); @@ -102,31 +128,3 @@ function compatStyle<S = object>(style?: S): S | void { } return style; } - -// Appear HOC Component. -function AppearOrDisappear(props: any, ref: RefObject<EventTarget>) { - const { onAppear, onDisappear } = props; - - listen('appear', onAppear); - listen('disappear', onDisappear); - - function listen(eventName: string, handler: EventListenerOrEventListenerObject) { - if (isFunction(handler) && ref) { - // eslint-disable-next-line react-hooks/rules-of-hooks - useEffect(() => { - const { current } = ref; - if (current != null) { - current.addEventListener(eventName, handler); - } - return () => { - const { current } = ref; - if (current) { - current.removeEventListener(eventName, handler); - } - }; - }, [ref, handler]); - } - } - - return props.children; -} diff --git a/packages/rax-compat/src/intersection-observer.js b/packages/rax-compat/src/intersection-observer.js new file mode 100644 index 000000000..73c2ceffa --- /dev/null +++ b/packages/rax-compat/src/intersection-observer.js @@ -0,0 +1,652 @@ +/** + * An IntersectionObserver registry. This registry exists to hold a strong + * reference to IntersectionObserver instances currently observing a target + * element. Without this registry, instances without another reference may be + * garbage collected. + */ +const registry = []; + + +/** + * Creates the global IntersectionObserverEntry constructor. + * https://w3c.github.io/IntersectionObserver/#intersection-observer-entry + * @param {Object} entry A dictionary of instance properties. + * @constructor + */ +export function IntersectionObserverEntry(entry) { + this.time = entry.time; + this.target = entry.target; + this.rootBounds = entry.rootBounds; + this.boundingClientRect = entry.boundingClientRect; + this.intersectionRect = entry.intersectionRect || getEmptyRect(); + this.isIntersecting = !!entry.intersectionRect; + + // Calculates the intersection ratio. + const targetRect = this.boundingClientRect; + const targetArea = targetRect.width * targetRect.height; + const { intersectionRect } = this; + const intersectionArea = intersectionRect.width * intersectionRect.height; + + // Sets intersection ratio. + if (targetArea) { + // Round the intersection ratio to avoid floating point math issues: + // https://github.com/w3c/IntersectionObserver/issues/324 + this.intersectionRatio = Number((intersectionArea / targetArea).toFixed(4)); + } else { + // If area is zero and is intersecting, sets to 1, otherwise to 0 + this.intersectionRatio = this.isIntersecting ? 1 : 0; + } +} + +export default class IntersectionObserver { + /** + * The minimum interval within which the document will be checked for + * intersection changes. + */ + THROTTLE_TIMEOUT = 100; + + /** + * The frequency in which the polyfill polls for intersection changes. + * this can be updated on a per instance basis and must be set prior to + * calling `observe` on the first target. + */ + POLL_INTERVAL = null; + + /** + * Use a mutation observer on the root element + * to detect intersection changes. + */ + USE_MUTATION_OBSERVER = true; + + /** + * Creates the global IntersectionObserver constructor. + * https://w3c.github.io/IntersectionObserver/#intersection-observer-interface + * @param {Function} callback The function to be invoked after intersection + * changes have queued. The function is not invoked if the queue has + * been emptied by calling the `takeRecords` method. + * @param {Object=} optOptions Optional configuration options. + * @constructor + */ + constructor(callback, optOptions) { + const options = optOptions || {}; + + if (typeof callback != 'function') { + throw new Error('callback must be a function'); + } + + if (options.root && options.root.nodeType != 1) { + throw new Error('root must be an Element'); + } + + // Throttles `this._checkForIntersections`. + this._checkForIntersections = throttle(this._checkForIntersections, this.THROTTLE_TIMEOUT); + + // Private properties. + this._callback = callback; + this._observationTargets = []; + this._queuedEntries = []; + this._rootMarginValues = this._parseRootMargin(options.rootMargin); + + // Public properties. + this.thresholds = this._initThresholds(options.threshold); + this.root = options.root || null; + this.rootMargin = this._rootMarginValues.map((margin) => margin.value + margin.unit).join(' '); + } + + /** + * Starts observing a target element for intersection changes based on + * the thresholds values. + * @param {Element} target The DOM element to observe. + */ + observe(target) { + const isTargetAlreadyObserved = this._observationTargets.some((item) => item.element === target); + + if (isTargetAlreadyObserved) { + return; + } + + if (!(target && target.nodeType == 1)) { + throw new Error('target must be an Element'); + } + + this._registerInstance(); + this._observationTargets.push({ element: target, entry: null }); + this._monitorIntersections(); + this._checkForIntersections(); + } + + /** + * Stops observing a target element for intersection changes. + * @param {Element} target The DOM element to observe. + */ + unobserve(target) { + this._observationTargets = + this._observationTargets.filter((item) => { + return item.element !== target; + }); + if (!this._observationTargets.length) { + this._unmonitorIntersections(); + this._unregisterInstance(); + } + } + + /** + * Stops observing all target elements for intersection changes. + */ + disconnect() { + this._observationTargets = []; + this._unmonitorIntersections(); + this._unregisterInstance(); + } + + /** + * Returns any queue entries that have not yet been reported to the + * callback and clears the queue. This can be used in conjunction with the + * callback to obtain the absolute most up-to-date intersection information. + * @return {Array} The currently queued entries. + */ + takeRecords() { + const records = this._queuedEntries.slice(); + this._queuedEntries = []; + return records; + } + + /** + * Accepts the threshold value from the user configuration object and + * returns a sorted array of unique threshold values. If a value is not + * between 0 and 1 and error is thrown. + * @private + * @param {Array|number=} optThreshold An optional threshold value or + * a list of threshold values, defaulting to [0]. + * @return {Array} A sorted list of unique and valid threshold values. + */ + _initThresholds(optThreshold) { + let threshold = optThreshold || [0]; + if (!Array.isArray(threshold)) threshold = [threshold]; + + return threshold.sort().filter((t, i, a) => { + if (typeof t != 'number' || isNaN(t) || t < 0 || t > 1) { + throw new Error('threshold must be a number between 0 and 1 inclusively'); + } + return t !== a[i - 1]; + }); + } + + /** + * Accepts the rootMargin value from the user configuration object + * and returns an array of the four margin values as an object containing + * the value and unit properties. If any of the values are not properly + * formatted or use a unit other than px or %, and error is thrown. + * @private + * @param {string=} optRootMargin An optional rootMargin value, + * defaulting to '0px'. + * @return {Array<Object>} An array of margin objects with the keys + * value and unit. + */ + _parseRootMargin(optRootMargin) { + let marginString = optRootMargin || '0px'; + let margins = marginString.split(/\s+/).map((margin) => { + let parts = /^(-?\d*\.?\d+)(px|%)$/.exec(margin); + if (!parts) { + throw new Error('rootMargin must be specified in pixels or percent'); + } + return { value: parseFloat(parts[1]), unit: parts[2] }; + }); + + // Handles shorthand. + margins[1] = margins[1] || margins[0]; + margins[2] = margins[2] || margins[0]; + margins[3] = margins[3] || margins[1]; + + return margins; + } + + /** + * Starts polling for intersection changes if the polling is not already + * happening, and if the page's visibility state is visible. + * @private + */ + _monitorIntersections() { + if (!this._monitoringIntersections) { + this._monitoringIntersections = true; + + // If a poll interval is set, use polling instead of listening to + // resize and scroll events or DOM mutations. + if (this.POLL_INTERVAL) { + this._monitoringInterval = setInterval(this._checkForIntersections, this.POLL_INTERVAL); + } else { + addEvent(window, 'resize', this._checkForIntersections, true); + addEvent(document, 'scroll', this._checkForIntersections, true); + + if (this.USE_MUTATION_OBSERVER && 'MutationObserver' in window) { + this._domObserver = new MutationObserver(this._checkForIntersections); + this._domObserver.observe(document, { + attributes: true, + childList: true, + characterData: true, + subtree: true, + }); + } + } + } + } + + /** + * Stops polling for intersection changes. + * @private + */ + _unmonitorIntersections() { + if (this._monitoringIntersections) { + this._monitoringIntersections = false; + + clearInterval(this._monitoringInterval); + this._monitoringInterval = null; + + removeEvent(window, 'resize', this._checkForIntersections, true); + removeEvent(document, 'scroll', this._checkForIntersections, true); + + if (this._domObserver) { + this._domObserver.disconnect(); + this._domObserver = null; + } + } + } + + /** + * Scans each observation target for intersection changes and adds them + * to the internal entries queue. If new entries are found, it + * schedules the callback to be invoked. + * @NOTE Using arrow function to bind to `this` instance. + * @private + */ + _checkForIntersections = () => { + let rootIsInDom = this._rootIsInDom(); + let rootRect = rootIsInDom ? this._getRootRect() : getEmptyRect(); + + this._observationTargets.forEach(function (item) { + let target = item.element; + let targetRect = getBoundingClientRect(target); + let rootContainsTarget = this._rootContainsTarget(target); + let oldEntry = item.entry; + let intersectionRect = rootIsInDom && rootContainsTarget && + this._computeTargetAndRootIntersection(target, rootRect); + + let newEntry = item.entry = new IntersectionObserverEntry({ + time: now(), + target: target, + boundingClientRect: targetRect, + rootBounds: rootRect, + intersectionRect: intersectionRect, + }); + + if (!oldEntry) { + this._queuedEntries.push(newEntry); + } else if (rootIsInDom && rootContainsTarget) { + // If the new entry intersection ratio has crossed any of the + // thresholds, add a new entry. + if (this._hasCrossedThreshold(oldEntry, newEntry)) { + this._queuedEntries.push(newEntry); + } + } else { + // If the root is not in the DOM or target is not contained within + // root but the previous entry for this target had an intersection, + // add a new record indicating removal. + if (oldEntry && oldEntry.isIntersecting) { + this._queuedEntries.push(newEntry); + } + } + }, this); + + if (this._queuedEntries.length) { + this._callback(this.takeRecords(), this); + } + }; + + /** + * Accepts a target and root rect computes the intersection between then + * following the algorithm in the spec. + * TODO(philipwalton): at this time clip-path is not considered. + * https://w3c.github.io/IntersectionObserver/#calculate-intersection-rect-algo + * @param {Element} target The target DOM element + * @param {Object} rootRect The bounding rect of the root after being + * expanded by the rootMargin value. + * @return {?Object} The final intersection rect object or undefined if no + * intersection is found. + * @private + */ + _computeTargetAndRootIntersection(target, rootRect) { + // If the element isn't displayed, an intersection can't happen. + if (window.getComputedStyle(target).display == 'none') return; + + let targetRect = getBoundingClientRect(target); + let intersectionRect = targetRect; + let parent = getParentNode(target); + let atRoot = false; + + while (!atRoot) { + let parentRect = null; + let parentComputedStyle = parent.nodeType == 1 + ? window.getComputedStyle(parent) : {}; + + // If the parent isn't displayed, an intersection can't happen. + if (parentComputedStyle.display === 'none') return; + + if (parent === this.root || parent === document) { + atRoot = true; + parentRect = rootRect; + } else { + // If the element has a non-visible overflow, and it's not the <body> + // or <html> element, update the intersection rect. + // Note: <body> and <html> cannot be clipped to a rect that's not also + // the document rect, so no need to compute a new intersection. + if (parent !== document.body && + parent !== document.documentElement && + parentComputedStyle.overflow !== 'visible') { + parentRect = getBoundingClientRect(parent); + } + } + + // If either of the above conditionals set a new parentRect, + // calculate new intersection data. + if (parentRect) { + intersectionRect = computeRectIntersection(parentRect, intersectionRect); + + if (!intersectionRect) break; + } + parent = getParentNode(parent); + } + return intersectionRect; + } + + /** + * Returns the root rect after being expanded by the rootMargin value. + * @return {Object} The expanded root rect. + * @private + */ + _getRootRect() { + let rootRect; + if (this.root) { + rootRect = getBoundingClientRect(this.root); + } else { + // Use <html>/<body> instead of window since scroll bars affect size. + let html = document.documentElement; + let { body } = document; + rootRect = { + top: 0, + left: 0, + right: html.clientWidth || body.clientWidth, + width: html.clientWidth || body.clientWidth, + bottom: html.clientHeight || body.clientHeight, + height: html.clientHeight || body.clientHeight, + }; + } + return this._expandRectByRootMargin(rootRect); + } + + /** + * Accepts a rect and expands it by the rootMargin value. + * @param {Object} rect The rect object to expand. + * @return {Object} The expanded rect. + * @private + */ + _expandRectByRootMargin(rect) { + let margins = this._rootMarginValues.map((margin, i) => { + return margin.unit === 'px' ? margin.value + : margin.value * (i % 2 ? rect.width : rect.height) / 100; + }); + let newRect = { + top: rect.top - margins[0], + right: rect.right + margins[1], + bottom: rect.bottom + margins[2], + left: rect.left - margins[3], + }; + newRect.width = newRect.right - newRect.left; + newRect.height = newRect.bottom - newRect.top; + + return newRect; + } + + /** + * Accepts an old and new entry and returns true if at least one of the + * threshold values has been crossed. + * @param {?IntersectionObserverEntry} oldEntry The previous entry for a + * particular target element or null if no previous entry exists. + * @param {IntersectionObserverEntry} newEntry The current entry for a + * particular target element. + * @return {boolean} Returns true if a any threshold has been crossed. + * @private + */ + _hasCrossedThreshold(oldEntry, newEntry) { + // To make comparing easier, an entry that has a ratio of 0 + // but does not actually intersect is given a value of -1 + const oldRatio = oldEntry && oldEntry.isIntersecting + ? oldEntry.intersectionRatio || 0 : -1; + const newRatio = newEntry.isIntersecting + ? newEntry.intersectionRatio || 0 : -1; + + // Ignore unchanged ratios + if (oldRatio === newRatio) return; + + for (let i = 0; i < this.thresholds.length; i++) { + const threshold = this.thresholds[i]; + + // Return true if an entry matches a threshold or if the new ratio + // and the old ratio are on the opposite sides of a threshold. + if (threshold == oldRatio || threshold == newRatio || + threshold < oldRatio !== threshold < newRatio) { + return true; + } + } + } + + /** + * Returns whether or not the root element is an element and is in the DOM. + * @return {boolean} True if the root element is an element and is in the DOM. + * @private + */ + _rootIsInDom() { + return !this.root || containsDeep(document, this.root); + } + + /** + * Returns whether or not the target element is a child of root. + * @param {Element} target The target element to check. + * @return {boolean} True if the target element is a child of root. + * @private + */ + _rootContainsTarget(target) { + return containsDeep(this.root || document, target); + } + + /** + * Adds the instance to the global IntersectionObserver registry if it isn't + * already present. + * @private + */ + _registerInstance() { + if (registry.indexOf(this) < 0) { + registry.push(this); + } + } + + /** + * Removes the instance from the global IntersectionObserver registry. + * @private + */ + _unregisterInstance() { + const index = registry.indexOf(this); + if (index !== -1) registry.splice(index, 1); + } +} + +/** + * Returns the result of the performance.now() method or null in browsers + * that don't support the API. + * @return {number} The elapsed time since the page was requested. + */ +function now() { + return window.performance && performance.now && performance.now(); +} + + +/** + * Throttles a function and delays its execution, so it's only called at most + * once within a given time period. + * @param {Function} fn The function to throttle. + * @param {number} timeout The amount of time that must pass before the + * function can be called again. + * @return {Function} The throttled function. + */ +function throttle(fn, timeout) { + let timer = null; + return function () { + if (!timer) { + timer = setTimeout(() => { + fn(); + timer = null; + }, timeout); + } + }; +} + + +/** + * Adds an event handler to a DOM node ensuring cross-browser compatibility. + * @param {Node} node The DOM node to add the event handler to. + * @param {string} event The event name. + * @param {Function} fn The event handler to add. + * @param {boolean} opt_useCapture Optionally adds the even to the capture + * phase. Note: this only works in modern browsers. + */ +function addEvent(node, event, fn, opt_useCapture) { + if (typeof node.addEventListener == 'function') { + node.addEventListener(event, fn, opt_useCapture || false); + } else if (typeof node.attachEvent == 'function') { + node.attachEvent(`on${event}`, fn); + } +} + + +/** + * Removes a previously added event handler from a DOM node. + * @param {Node} node The DOM node to remove the event handler from. + * @param {string} event The event name. + * @param {Function} fn The event handler to remove. + * @param {boolean} opt_useCapture If the event handler was added with this + * flag set to true, it should be set to true here in order to remove it. + */ +function removeEvent(node, event, fn, opt_useCapture) { + if (typeof node.removeEventListener == 'function') { + node.removeEventListener(event, fn, opt_useCapture || false); + } else if (typeof node.detatchEvent == 'function') { + node.detatchEvent(`on${event}`, fn); + } +} + + +/** + * Returns the intersection between two rect objects. + * @param {Object} rect1 The first rect. + * @param {Object} rect2 The second rect. + * @return {?Object} The intersection rect or undefined if no intersection + * is found. + */ +function computeRectIntersection(rect1, rect2) { + const top = Math.max(rect1.top, rect2.top); + const bottom = Math.min(rect1.bottom, rect2.bottom); + const left = Math.max(rect1.left, rect2.left); + const right = Math.min(rect1.right, rect2.right); + const width = right - left; + const height = bottom - top; + + return width >= 0 && height >= 0 && { top, bottom, left, right, width, height }; +} + + +/** + * Shims the native getBoundingClientRect for compatibility with older IE. + * @param {Element} el The element whose bounding rect to get. + * @return {Object} The (possibly shimmed) rect of the element. + */ +function getBoundingClientRect(el) { + let rect; + + try { + rect = el.getBoundingClientRect(); + } catch (err) { + // Ignore Windows 7 IE11 "Unspecified error" + // https://github.com/w3c/IntersectionObserver/pull/205 + } + + if (!rect) return getEmptyRect(); + + // Older IE + if (!(rect.width && rect.height)) { + rect = { + top: rect.top, + right: rect.right, + bottom: rect.bottom, + left: rect.left, + width: rect.right - rect.left, + height: rect.bottom - rect.top, + }; + } + return rect; +} + + +/** + * Returns an empty rect object. An empty rect is returned when an element + * is not in the DOM. + * @return {Object} The empty rect. + */ +function getEmptyRect() { + return { + top: 0, + bottom: 0, + left: 0, + right: 0, + width: 0, + height: 0, + }; +} + +/** + * Checks to see if a parent element contains a child element (including inside + * shadow DOM). + * @param {Node} parent The parent element. + * @param {Node} child The child element. + * @return {boolean} True if the parent node contains the child node. + */ +function containsDeep(parent, child) { + let node = child; + while (node) { + if (node === parent) return true; + + node = getParentNode(node); + } + return false; +} + + +/** + * Gets the parent node of an element or its host element if the parent node + * is a shadow root. + * @param {Node} node The node whose parent to get. + * @return {Node|null} The parent node or null if no parent exists. + */ +function getParentNode(node) { + let parent = node.parentNode; + + if (parent && parent.nodeType == 11 && parent.host) { + // If the parent is a shadow root, return the host element. + return parent.host; + } + + if (parent && parent.assignedSlot) { + // If the parent is distributed in a <slot>, return the parent of a slot. + return parent.assignedSlot.parentNode; + } + + return parent; +} diff --git a/packages/rax-compat/src/visibility.ts b/packages/rax-compat/src/visibility.ts new file mode 100644 index 000000000..6c7b8a20e --- /dev/null +++ b/packages/rax-compat/src/visibility.ts @@ -0,0 +1,124 @@ +// Handle appear and disappear event. +// Fork from https://github.com/raxjs/appear-polyfill +// @ts-ignore +import PolyfilledIntersectionObserver from './intersection-observer'; + +enum VisibilityChangeEvent { + appear = 'appear', + disappear = 'disappear', +} + +enum VisibilityChangeDirection { + up = 'up', + down = 'down', +} + +// Shared intersectionObserver instance. +let intersectionObserver: any; +const IntersectionObserver = (function () { + if (typeof window !== 'undefined' && + 'IntersectionObserver' in window && + 'IntersectionObserverEntry' in window && + 'intersectionRatio' in window.IntersectionObserverEntry.prototype) { + // features are natively supported + return window.IntersectionObserver; + } else { + // polyfilled IntersectionObserver + return PolyfilledIntersectionObserver; + } +})(); + +function generateThreshold(number: number) { + const thresholds = []; + for (let index = 0; index < number; index++) { + thresholds.push(index / number); + } + + return thresholds; +} + +const defaultOptions = { + // @ts-ignore + root: null, + rootMargin: '0px', + threshold: generateThreshold(10), +}; + +export function createIntersectionObserver(options = defaultOptions) { + intersectionObserver = new IntersectionObserver(handleIntersect, options); +} + +export function destroyIntersectionObserver() { + if (intersectionObserver) { + intersectionObserver.disconnect(); + intersectionObserver = null; + } +} + +export function observerElement(element: HTMLElement | Node) { + if (!intersectionObserver) createIntersectionObserver(); + + if (element === document) element = document.documentElement; + + intersectionObserver.observe(element); +} + +function handleIntersect(entries: IntersectionObserverEntry[]) { + entries.forEach((entry) => { + const { + target, + boundingClientRect, + intersectionRatio, + } = entry; + // No `top` value in polyfill. + const currentY = boundingClientRect.y || boundingClientRect.top; + const beforeY = parseInt(target.getAttribute('data-before-current-y')) || currentY; + + // is in view + if ( + intersectionRatio > 0.01 && + !isTrue(target.getAttribute('data-appeared')) && + !appearOnce(target as HTMLElement, VisibilityChangeEvent.appear) + ) { + target.setAttribute('data-appeared', 'true'); + target.setAttribute('data-has-appeared', 'true'); + target.dispatchEvent(createEvent(VisibilityChangeEvent.appear, { + direction: currentY > beforeY ? VisibilityChangeDirection.up : VisibilityChangeDirection.down, + })); + } else if ( + intersectionRatio === 0 && + isTrue(target.getAttribute('data-appeared')) && + !appearOnce(target as HTMLElement, VisibilityChangeEvent.disappear) + ) { + target.setAttribute('data-appeared', 'false'); + target.setAttribute('data-has-disappeared', 'true'); + target.dispatchEvent(createEvent(VisibilityChangeEvent.appear, { + direction: currentY > beforeY ? VisibilityChangeDirection.up : VisibilityChangeDirection.down, + })); + } + + target.setAttribute('data-before-current-y', String(currentY)); + }); +} + +/** + * need appear again when node has isonce or data-once + */ +function appearOnce(node: HTMLElement, type: VisibilityChangeEvent) { + const isOnce = isTrue(node.getAttribute('isonce')) || isTrue(node.getAttribute('data-once')); + const appearType = type === VisibilityChangeEvent.appear ? 'data-has-appeared' : 'data-has-disappeared'; + + return isOnce && isTrue(node.getAttribute(appearType)); +} + +function isTrue(flag: any) { + return flag && flag !== 'false'; +} + +function createEvent(eventName: string, data: any) { + return new CustomEvent(eventName, { + bubbles: false, + cancelable: true, + detail: data, + }); +} diff --git a/packages/rax-compat/tests/createElement.test.tsx b/packages/rax-compat/tests/createElement.test.tsx index f1b9fb549..1ba5c9dc1 100644 --- a/packages/rax-compat/tests/createElement.test.tsx +++ b/packages/rax-compat/tests/createElement.test.tsx @@ -40,7 +40,7 @@ describe('createElement', () => { render(createElement( 'div', { - onDisappear: func + onDisappear: func, }, str )); diff --git a/packages/types/package.json b/packages/types/package.json index dce2b44f3..55110e1cf 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -30,6 +30,7 @@ "bugs": "https://github.com/ice-lab/ice-next/issues", "homepage": "https://next.ice.work", "devDependencies": { + "@builder/swc": "^0.2.0", "@ice/route-manifest": "^1.0.0", "@ice/runtime": "^1.0.0", "build-scripts": "^2.0.0-23", @@ -39,9 +40,9 @@ "fork-ts-checker-webpack-plugin": "7.2.6", "react": "^18.0.0", "terser": "^5.12.1", + "typescript": "^4.6.4", "unplugin": "^0.3.2", "webpack": "^5.73.0", - "webpack-dev-server": "^4.7.4", - "typescript": "^4.6.4" + "webpack-dev-server": "^4.7.4" } } diff --git a/packages/types/src/config.ts b/packages/types/src/config.ts index 91eddba50..148a2fc8c 100644 --- a/packages/types/src/config.ts +++ b/packages/types/src/config.ts @@ -6,6 +6,7 @@ import type { ForkTsCheckerWebpackPluginOptions } from 'fork-ts-checker-webpack- import type { UnpluginOptions } from 'unplugin'; import type Server from 'webpack-dev-server'; import type { ECMA } from 'terser'; +import type { Config as CompilationConfig } from '@builder/swc'; // get type definitions from terser-webpack-plugin interface CustomOptions { @@ -27,6 +28,7 @@ interface ConfigurationCtx extends Config { interface SwcOptions { jsxTransform?: boolean; removeExportExprs?: string[]; + compilationConfig?: CompilationConfig; } type Experimental = Pick<Configuration, 'experiments'>; diff --git a/packages/webpack-config/src/unPlugins/compilation.ts b/packages/webpack-config/src/unPlugins/compilation.ts index 842b25b6e..7c345b8a5 100644 --- a/packages/webpack-config/src/unPlugins/compilation.ts +++ b/packages/webpack-config/src/unPlugins/compilation.ts @@ -49,7 +49,7 @@ const compilationPlugin = (options: Options): UnpluginOptions => { filename: id, }; - const { jsxTransform, removeExportExprs } = swcOptions; + const { jsxTransform, removeExportExprs, compilationConfig } = swcOptions; let needTransform = false; @@ -81,7 +81,7 @@ const compilationPlugin = (options: Options): UnpluginOptions => { } try { - const output = await transform(source, programmaticOptions); + const output = await transform(source, merge(programmaticOptions, compilationConfig || {})); const { code } = output; let { map } = output; // FIXME: swc transform should return the sourcemap which the type is object diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 15cd6879e..a3cca334d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -88,11 +88,6 @@ importers: '@types/react-dom': ^18.0.2 ahooks: ^3.3.8 browserslist: ^4.19.3 - rax: ^1.2.2 - rax-image: ^2.4.1 - rax-is-valid-element: ^1.0.0 - rax-text: ^2.2.0 - rax-view: ^2.3.0 react: ^18.0.0 react-dom: ^18.0.0 regenerator-runtime: ^0.13.9 @@ -104,11 +99,6 @@ importers: '@ice/plugin-rax-compat': link:../../packages/plugin-rax-compat '@ice/runtime': link:../../packages/runtime ahooks: 3.4.0_react@18.0.0 - rax: 1.2.2 - rax-image: 2.4.1_rax@1.2.2 - rax-is-valid-element: 1.0.0 - rax-text: 2.2.0_rax@1.2.2 - rax-view: 2.3.0_rax@1.2.2 react: 18.0.0 react-dom: 18.0.0_react@18.0.0 devDependencies: @@ -148,6 +138,41 @@ importers: speed-measure-webpack-plugin: 1.5.0_webpack@5.73.0 webpack: 5.73.0 + examples/rax-project: + specifiers: + '@ice/app': workspace:* + '@ice/plugin-rax-compat': workspace:* + '@ice/runtime': workspace:* + '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.2 + browserslist: ^4.19.3 + rax: ^1.2.2 + rax-image: ^2.4.1 + rax-is-valid-element: ^1.0.0 + rax-text: ^2.2.0 + rax-view: ^2.3.0 + react: ^18.0.0 + react-dom: ^18.0.0 + regenerator-runtime: ^0.13.9 + webpack: ^5.73.0 + dependencies: + '@ice/app': link:../../packages/ice + '@ice/plugin-rax-compat': link:../../packages/plugin-rax-compat + '@ice/runtime': link:../../packages/runtime + rax: 1.2.2 + rax-image: 2.4.1_rax@1.2.2 + rax-is-valid-element: 1.0.0 + rax-text: 2.2.0_rax@1.2.2 + rax-view: 2.3.0_rax@1.2.2 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + devDependencies: + '@types/react': 18.0.8 + '@types/react-dom': 18.0.3 + browserslist: 4.20.3 + regenerator-runtime: 0.13.9 + webpack: 5.73.0 + examples/routes-generate: specifiers: '@ice/app': workspace:* @@ -504,10 +529,12 @@ importers: '@ice/types': ^1.0.0 '@types/webpack': ^5.28.0 consola: ^2.15.3 + lodash.merge: ^4.6.2 rax-compat: ^0.1.0 stylesheet-loader: ^0.9.1 dependencies: consola: 2.15.3 + lodash.merge: 4.6.2 rax-compat: link:../rax-compat stylesheet-loader: 0.9.1 devDependencies: @@ -519,10 +546,10 @@ importers: '@ice/pkg': ^1.0.0-rc.0 '@ice/pkg-plugin-docusaurus': ^1.0.0-rc.0 '@iceworks/spec': ^1.0.0 + '@swc/helpers': ^0.4.3 '@types/rax': ^1.0.8 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - appear-polyfill: ^0.1.2 create-react-class: ^15.7.0 eslint: ^7.0.0 react: ^18.0.0 @@ -530,7 +557,7 @@ importers: style-unit: ^3.0.4 stylelint: ^13.7.2 dependencies: - appear-polyfill: 0.1.2 + '@swc/helpers': registry.npmjs.org/@swc/helpers/0.4.3 create-react-class: 15.7.0 style-unit: 3.0.4 devDependencies: @@ -574,6 +601,7 @@ importers: packages/types: specifiers: + '@builder/swc': ^0.2.0 '@ice/route-manifest': ^1.0.0 '@ice/runtime': ^1.0.0 build-scripts: ^2.0.0-23 @@ -588,6 +616,7 @@ importers: webpack: ^5.73.0 webpack-dev-server: ^4.7.4 devDependencies: + '@builder/swc': 0.2.0 '@ice/route-manifest': link:../route-manifest '@ice/runtime': link:../runtime build-scripts: 2.0.0-23 @@ -2526,109 +2555,21 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true - /@builder/swc-darwin-arm64/0.2.0: - resolution: {integrity: sha512-+nmnScnq40eMKqCLpVwl7P/JCHrzm9q1ECvD/nGTNATweMB0hhTjX7V/5DfHELl1RHGnw7NchAuVJDesNa9daw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@builder/swc-darwin-x64/0.2.0: - resolution: {integrity: sha512-vR9H+o5WmrasoAgMmL9HA2DfUosreGt0Pak54iOIyu3V6hSXaLxKuSidqEMcWBG1nN2wEYBvlzP8s04WusqPRQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@builder/swc-linux-arm64-gnu/0.2.0: - resolution: {integrity: sha512-O18+aSQ7ZGcBwongjsatQ7OcJo9D0YDsBujPkQfQ0sBwnxmzGTw4kkXHr/K9Bou9wcy8TEpXRfaauaLHzzecAA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@builder/swc-linux-arm64-musl/0.2.0: - resolution: {integrity: sha512-0vkGpqmJNOfsWh7qb3Mqga0gJPsAomxPitWapRlFQ736Q0qHL4Bb270/VZO3xcjA0zZKaN8VdwVw+Pxqg3ziQA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@builder/swc-linux-x64-gnu/0.2.0: - resolution: {integrity: sha512-6gPaiwQq1l/eeNthOBvWInHU5i2bfbnGuw4YDsTF2pHhbHd7eR++N5viTROJLjFaZevWrNUbfMc47IMRGQg7WA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@builder/swc-linux-x64-musl/0.2.0: - resolution: {integrity: sha512-01zpp3sHM48x1Tl1fzM6si1E6ZIooJkXts+vPu36v265gXEb1winhFHCXXtQXvSHZ/XEyRFD1BcgdCm3goSJRw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@builder/swc-win32-arm64-msvc/0.2.0: - resolution: {integrity: sha512-+06kFldeVV1Yzy2tfkeClwsglW50j6qG2vpTA3Tqwp5kEAGFNT1tUwsoWcbySJSCRlGBAVHDZxJlsUMqSK34Yw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@builder/swc-win32-ia32-msvc/0.2.0: - resolution: {integrity: sha512-wc9GA1YWv5ZxVYl73KDdRuX3All8reNIUbtPEKz2LwQ5locUX6gb7pdDzDz0et/xXjshZRGka7wDU2wzgi8Giw==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@builder/swc-win32-x64-msvc/0.2.0: - resolution: {integrity: sha512-l8eMGTigKHrA46HAkXWblYwxQeT/SEe9yKrIYi2kfngWHNUALUFlPnnoJOSmLCGwPRZTHUgcx45Ta+15ahj5DQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - /@builder/swc/0.2.0: resolution: {integrity: sha512-XYo9NCDQ8i8wG6TwrO+zxevJ6Icuj+F+LlwN5SP5lFC8foqi04gtY6Ogu3jKGW9YsfZLZ25ExhY03uFoy87dHg==} engines: {node: '>= 12'} dependencies: '@napi-rs/triples': 1.1.0 optionalDependencies: - '@builder/swc-darwin-arm64': 0.2.0 - '@builder/swc-darwin-x64': 0.2.0 - '@builder/swc-linux-arm64-gnu': 0.2.0 - '@builder/swc-linux-arm64-musl': 0.2.0 - '@builder/swc-linux-x64-gnu': 0.2.0 - '@builder/swc-linux-x64-musl': 0.2.0 - '@builder/swc-win32-arm64-msvc': 0.2.0 - '@builder/swc-win32-ia32-msvc': 0.2.0 - '@builder/swc-win32-x64-msvc': 0.2.0 - dev: false - - /@colors/colors/1.5.0: - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} - requiresBuild: true - optional: true + '@builder/swc-darwin-arm64': registry.npmjs.org/@builder/swc-darwin-arm64/0.2.0 + '@builder/swc-darwin-x64': registry.npmjs.org/@builder/swc-darwin-x64/0.2.0 + '@builder/swc-linux-arm64-gnu': registry.npmjs.org/@builder/swc-linux-arm64-gnu/0.2.0 + '@builder/swc-linux-arm64-musl': registry.npmjs.org/@builder/swc-linux-arm64-musl/0.2.0 + '@builder/swc-linux-x64-gnu': registry.npmjs.org/@builder/swc-linux-x64-gnu/0.2.0 + '@builder/swc-linux-x64-musl': registry.npmjs.org/@builder/swc-linux-x64-musl/0.2.0 + '@builder/swc-win32-arm64-msvc': registry.npmjs.org/@builder/swc-win32-arm64-msvc/0.2.0 + '@builder/swc-win32-ia32-msvc': registry.npmjs.org/@builder/swc-win32-ia32-msvc/0.2.0 + '@builder/swc-win32-x64-msvc': registry.npmjs.org/@builder/swc-win32-x64-msvc/0.2.0 /@commitlint/cli/16.2.3: resolution: {integrity: sha512-VsJBQLvhhlOgEfxs/Z5liYuK0dXqLE5hz1VJzLBxiOxG31kL/X5Q4OvK292BmO7IGZcm1yJE3XQPWSiFaEHbWA==} @@ -2970,7 +2911,7 @@ packages: react-dev-utils: 12.0.1_ej5kzqlwxufmlid7qwxwr3ivqm react-dom: 18.0.0_react@18.0.0 react-helmet-async: 1.3.0_zpnidt7m3osuk7shl3s4oenomq - react-loadable: /@docusaurus/react-loadable/5.5.2_react@18.0.0 + react-loadable: registry.npmjs.org/@docusaurus/react-loadable/5.5.2_react@18.0.0 react-loadable-ssr-addon-v5-slorber: 1.0.1_5grs2dwrf6hqtfkptfcfoiy4bu react-router: 5.3.3_react@18.0.0 react-router-config: 5.1.1_cjnlnwqdxho3pb5qn7rj77nvqa @@ -3068,7 +3009,7 @@ packages: react-dev-utils: 12.0.1_webpack@5.72.1 react-dom: 18.2.0_react@18.2.0 react-helmet-async: 1.3.0_biqbaboplfbrettd7655fr4n2y - react-loadable: /@docusaurus/react-loadable/5.5.2_react@18.2.0 + react-loadable: registry.npmjs.org/@docusaurus/react-loadable/5.5.2_react@18.2.0 react-loadable-ssr-addon-v5-slorber: 1.0.1_vozs4ks5473aha5pvbrq6fz4gu react-router: 5.3.3_react@18.2.0 react-router-config: 5.1.1_4gumyfmpzq3vvokmq4lwan2qpu @@ -3166,7 +3107,7 @@ packages: react-dev-utils: 12.0.1_webpack@5.72.1 react-dom: 18.2.0_react@18.2.0 react-helmet-async: 1.3.0_biqbaboplfbrettd7655fr4n2y - react-loadable: /@docusaurus/react-loadable/5.5.2_react@18.2.0 + react-loadable: registry.npmjs.org/@docusaurus/react-loadable/5.5.2_react@18.2.0 react-loadable-ssr-addon-v5-slorber: 1.0.1_vozs4ks5473aha5pvbrq6fz4gu react-router: 5.3.3_react@18.2.0 react-router-config: 5.1.1_4gumyfmpzq3vvokmq4lwan2qpu @@ -4707,142 +4648,24 @@ packages: /@napi-rs/triples/1.1.0: resolution: {integrity: sha512-XQr74QaLeMiqhStEhLn1im9EOMnkypp7MZOwQhGzqp2Weu5eQJbpPxWxixxlYRKWPOmJjsk6qYfYH9kq43yc2w==} - dev: false - - /@node-rs/jieba-android-arm-eabi/1.6.1: - resolution: {integrity: sha512-R1YQfsPr7sK3Tq1sM0//6lNAGJK9RnMT0ShITT+7EJYr5OufUBb38lf/mRhrLxR0NF1pycEsMjdCAwrWrHd8rA==} - engines: {node: '>= 10'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-android-arm64/1.6.1: - resolution: {integrity: sha512-hBRbj2uLmRFYDw2lWppTAPoyjeXkBKUT84h4fHUQj7CMU94Gc1IWkE4ocCqhvUhbaUXlCpocS9mB0/fc2641bw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-darwin-arm64/1.6.1: - resolution: {integrity: sha512-GeoDe7XVTF6z8JUtD98QvwudsMaHV5EBXs5uO43SobeIkShH3Nujq5gLMD5kWoJXTxDrTgJe4wT42EwUaBEH2Q==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-darwin-x64/1.6.1: - resolution: {integrity: sha512-ENHYIS8b8JdMaUXEm0f8Y3+sHXu2UdukG1D/XGUNx+q5cn07HbwIg6L0tlGhE8dw4AhqoWHsExVaZ241Igh4iA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-freebsd-x64/1.6.1: - resolution: {integrity: sha512-chwB/9edtxqS8Jm3j4RMaJjH9AlXmijUgKv02oMw36e77HKpko+tENUN25Vrn/9GKsKGqIPeXpmCjeXCN1HVQA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-linux-arm-gnueabihf/1.6.1: - resolution: {integrity: sha512-tsb5fMGj4p8bHGfkf7bJ+HE2jxaixLTp3YnGg5D+kp8+HQRq8cp3ScG5cn8cq0phnJS/zfAp8rVfWInDagzKKQ==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-linux-arm64-gnu/1.6.1: - resolution: {integrity: sha512-bSInORkJFfeZNR+i4rFoSZGbwkQtQlnZ0XfT/noTK9JUBDYErqQZPFjoaYAU45NWTk7p6Zkg30SuV1NTdWLaPw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-linux-arm64-musl/1.6.1: - resolution: {integrity: sha512-qphL6xM7owfU8Hsh7GX73SDr/iApbnc+35mSLxbibAfCQnY89+WcBeWUUOSGM/Ov3VFaq4pyVlDFj0YjR01W2w==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-linux-x64-gnu/1.6.1: - resolution: {integrity: sha512-f6hhlrbi2wel0xZG7m3Wvksimt9MSu1f3aYO2Kwavf4qjMRZqJzLz9HlCJAal6AXB9Qgg+685P+gftsWve47qw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-linux-x64-musl/1.6.1: - resolution: {integrity: sha512-cTVcdR6zWqpnmdEUyWEII9zfE5lTeWN53TbiOPx8TCA+291/31Vqd7GA8YEPndUO8qgCx5uShSDFStBAEIhYNQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-win32-arm64-msvc/1.6.1: - resolution: {integrity: sha512-YuOTrjHazDraXcGXRHgPQ53nyJuH8QtTCngYKjAzxsdt8uN+txb1AY69OLMLBBZqLTOwY9dgcW70vGiLQMCTeg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-win32-ia32-msvc/1.6.1: - resolution: {integrity: sha512-4+E843ImGpVlZ+LlT9E/13NHmmUg3UHQx419D6fFMorJUUQuK4cZJfE1z4tCgcrbV8S5Wew5LIFywlJeJLu0LQ==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@node-rs/jieba-win32-x64-msvc/1.6.1: - resolution: {integrity: sha512-veXNwm2VlseOzl7vaC7A/nZ4okp5/6edN7/Atj6mXnUbze/m/my5Rv5zUcW3U1D9VElnQ3srCHCa5vXljJuk6g==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true /@node-rs/jieba/1.6.1: resolution: {integrity: sha512-pISKu8NIYKRvZp7mhYZYA8VCjJMqTsCe+mQcFFnAi3GNJsijGjef2peMFeDcvP72X8MsnNeYeg3rHkAybtefyQ==} engines: {node: '>= 10'} optionalDependencies: - '@node-rs/jieba-android-arm-eabi': 1.6.1 - '@node-rs/jieba-android-arm64': 1.6.1 - '@node-rs/jieba-darwin-arm64': 1.6.1 - '@node-rs/jieba-darwin-x64': 1.6.1 - '@node-rs/jieba-freebsd-x64': 1.6.1 - '@node-rs/jieba-linux-arm-gnueabihf': 1.6.1 - '@node-rs/jieba-linux-arm64-gnu': 1.6.1 - '@node-rs/jieba-linux-arm64-musl': 1.6.1 - '@node-rs/jieba-linux-x64-gnu': 1.6.1 - '@node-rs/jieba-linux-x64-musl': 1.6.1 - '@node-rs/jieba-win32-arm64-msvc': 1.6.1 - '@node-rs/jieba-win32-ia32-msvc': 1.6.1 - '@node-rs/jieba-win32-x64-msvc': 1.6.1 + '@node-rs/jieba-android-arm-eabi': registry.npmjs.org/@node-rs/jieba-android-arm-eabi/1.6.1 + '@node-rs/jieba-android-arm64': registry.npmjs.org/@node-rs/jieba-android-arm64/1.6.1 + '@node-rs/jieba-darwin-arm64': registry.npmjs.org/@node-rs/jieba-darwin-arm64/1.6.1 + '@node-rs/jieba-darwin-x64': registry.npmjs.org/@node-rs/jieba-darwin-x64/1.6.1 + '@node-rs/jieba-freebsd-x64': registry.npmjs.org/@node-rs/jieba-freebsd-x64/1.6.1 + '@node-rs/jieba-linux-arm-gnueabihf': registry.npmjs.org/@node-rs/jieba-linux-arm-gnueabihf/1.6.1 + '@node-rs/jieba-linux-arm64-gnu': registry.npmjs.org/@node-rs/jieba-linux-arm64-gnu/1.6.1 + '@node-rs/jieba-linux-arm64-musl': registry.npmjs.org/@node-rs/jieba-linux-arm64-musl/1.6.1 + '@node-rs/jieba-linux-x64-gnu': registry.npmjs.org/@node-rs/jieba-linux-x64-gnu/1.6.1 + '@node-rs/jieba-linux-x64-musl': registry.npmjs.org/@node-rs/jieba-linux-x64-musl/1.6.1 + '@node-rs/jieba-win32-arm64-msvc': registry.npmjs.org/@node-rs/jieba-win32-arm64-msvc/1.6.1 + '@node-rs/jieba-win32-ia32-msvc': registry.npmjs.org/@node-rs/jieba-win32-ia32-msvc/1.6.1 + '@node-rs/jieba-win32-x64-msvc': registry.npmjs.org/@node-rs/jieba-win32-x64-msvc/1.6.1 dev: false /@nodelib/fs.scandir/2.1.5: @@ -5374,154 +5197,50 @@ packages: transitivePeerDependencies: - supports-color - /@swc/core-android-arm-eabi/1.2.168: - resolution: {integrity: sha512-RjjudVdJxm1KoNrbFxQIppJQjB1mzMYKW6+HYKVl8ktc7i/mnjwcl0cXVBWGbw1xsRWbTjHMHPs/kJ3hOESoeg==} + /@swc/core/1.2.168: + resolution: {integrity: sha512-O/PzeeSBqNQcpT/+62AGjXJ/TGQ2/jAkJc5aRtT/SyvwA/wQ+gSMOGc3mdFobD7SvgnXX+oS4/I/es84HhrhUA==} engines: {node: '>=10'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true + hasBin: true + optionalDependencies: + '@swc/core-android-arm-eabi': registry.npmjs.org/@swc/core-android-arm-eabi/1.2.168 + '@swc/core-android-arm64': registry.npmjs.org/@swc/core-android-arm64/1.2.168 + '@swc/core-darwin-arm64': registry.npmjs.org/@swc/core-darwin-arm64/1.2.168 + '@swc/core-darwin-x64': registry.npmjs.org/@swc/core-darwin-x64/1.2.168 + '@swc/core-freebsd-x64': registry.npmjs.org/@swc/core-freebsd-x64/1.2.168 + '@swc/core-linux-arm-gnueabihf': registry.npmjs.org/@swc/core-linux-arm-gnueabihf/1.2.168 + '@swc/core-linux-arm64-gnu': registry.npmjs.org/@swc/core-linux-arm64-gnu/1.2.168 + '@swc/core-linux-arm64-musl': registry.npmjs.org/@swc/core-linux-arm64-musl/1.2.168 + '@swc/core-linux-x64-gnu': registry.npmjs.org/@swc/core-linux-x64-gnu/1.2.168 + '@swc/core-linux-x64-musl': registry.npmjs.org/@swc/core-linux-x64-musl/1.2.168 + '@swc/core-win32-arm64-msvc': registry.npmjs.org/@swc/core-win32-arm64-msvc/1.2.168 + '@swc/core-win32-ia32-msvc': registry.npmjs.org/@swc/core-win32-ia32-msvc/1.2.168 + '@swc/core-win32-x64-msvc': registry.npmjs.org/@swc/core-win32-x64-msvc/1.2.168 - /@swc/core-android-arm64/1.2.168: - resolution: {integrity: sha512-K83gxb578LJid4GI047oSdaK90REnaXfXa+f+DT3Ud5hKFDrF7zkpyF6oxfHJGTl9LCUMXhijwg8aRXaFZFqWQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true + /@swc/helpers/0.3.17: + resolution: {integrity: sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==} + dependencies: + tslib: 2.4.0 + dev: true - /@swc/core-darwin-arm64/1.2.168: - resolution: {integrity: sha512-/kciTqYbEryg3e2C+/Twpww7LBc+zaF7yhz2AmxOrA7nQKuUNHA3Q/Y4sXthSXD2BLqPABJETbRmfmumNi8gQA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true + /@szmarczak/http-timer/1.1.2: + resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==} + engines: {node: '>=6'} + dependencies: + defer-to-connect: 1.1.3 - /@swc/core-darwin-x64/1.2.168: - resolution: {integrity: sha512-PbciVgB24OX6QCUmJmkD2hfZQh9LostC89vALfasUwT/wj3rHeg2SD2rvoPlIf0lYZjUPNfpbhDoxkUeEt+SEg==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@swc/core-freebsd-x64/1.2.168: - resolution: {integrity: sha512-lp3lNrjF2vNSOtsRFVRDs0EBpwoXQSD0MeZugX9EwHbHXavPlY+Kmo6cNqHfdrxIVOoVOYMlqQn+kO3/4mwYAQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - - /@swc/core-linux-arm-gnueabihf/1.2.168: - resolution: {integrity: sha512-TVYXoITQTCPOthHXhmBHFR77mXKE3tGN8CRAHtFYC0mUb42LY5nUQ8yc6peNpcvSqAUzK9K079koDltWIDfWKw==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@swc/core-linux-arm64-gnu/1.2.168: - resolution: {integrity: sha512-Xw7Vj/4EJA5V8kQ5cziUbj3qZQSt8n5Pr2TnFCZ3NkCL8og2JYf2N1mOTAI+PIknaDqh1boz+k9xEs1araQ2lA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@swc/core-linux-arm64-musl/1.2.168: - resolution: {integrity: sha512-71HHYhyNxpv1Maiqv/U5cHFMitU3MP2TN77vTi5ifPw+6H7A3fG86aqE8zr7YEGsSmOzgQUrMMblqvwe52IrlQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@swc/core-linux-x64-gnu/1.2.168: - resolution: {integrity: sha512-kEP3VN6Seoz73Fyu+80qkKtIURl/FvlT6NNju55uTMqeeiF3su0CRC60A2/IWHwAZ8sjlorgcXQeaiNTyJmWBQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@swc/core-linux-x64-musl/1.2.168: - resolution: {integrity: sha512-IEDB4T5KyUB0BEdIsSJuFm1CV9Y1wIEG15870J0dONkvO1iv5lqWZ7GwA52w/YaI61iNC8+cZYWqfwr4MWj1EQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@swc/core-win32-arm64-msvc/1.2.168: - resolution: {integrity: sha512-cBiYhBdrW+GdfKJdNhIE/7Pw+45Kn7SKZ78TPc/0ibGXDdx2IkuDhO7x1eZy0eLlS+Br6OLUs9FkgbcMrpZAGw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@swc/core-win32-ia32-msvc/1.2.168: - resolution: {integrity: sha512-ShbX43+hFqDWLU4R8FnDFIPXR8OzC0zBwJBj8QPV3YmeoQD+wyA7NGBccm/8UbnEY5uE2t7P4Pz8891d6TW3Ww==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@swc/core-win32-x64-msvc/1.2.168: - resolution: {integrity: sha512-e+SPSiBHSlAI4+RM+Fcz8HVqpHQaGFiDL4b8LwguVgRdoDVeJAjamw53r2UJ23X++9PXamT3rhzPs5XEH0PQhg==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /@swc/core/1.2.168: - resolution: {integrity: sha512-O/PzeeSBqNQcpT/+62AGjXJ/TGQ2/jAkJc5aRtT/SyvwA/wQ+gSMOGc3mdFobD7SvgnXX+oS4/I/es84HhrhUA==} - engines: {node: '>=10'} - hasBin: true - optionalDependencies: - '@swc/core-android-arm-eabi': 1.2.168 - '@swc/core-android-arm64': 1.2.168 - '@swc/core-darwin-arm64': 1.2.168 - '@swc/core-darwin-x64': 1.2.168 - '@swc/core-freebsd-x64': 1.2.168 - '@swc/core-linux-arm-gnueabihf': 1.2.168 - '@swc/core-linux-arm64-gnu': 1.2.168 - '@swc/core-linux-arm64-musl': 1.2.168 - '@swc/core-linux-x64-gnu': 1.2.168 - '@swc/core-linux-x64-musl': 1.2.168 - '@swc/core-win32-arm64-msvc': 1.2.168 - '@swc/core-win32-ia32-msvc': 1.2.168 - '@swc/core-win32-x64-msvc': 1.2.168 - - /@swc/helpers/0.3.17: - resolution: {integrity: sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==} - dependencies: - tslib: 2.4.0 - dev: true - - /@szmarczak/http-timer/1.1.2: - resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==} - engines: {node: '>=6'} - dependencies: - defer-to-connect: 1.1.3 - - /@testing-library/dom/8.14.0: - resolution: {integrity: sha512-m8FOdUo77iMTwVRCyzWcqxlEIk+GnopbrRI15a0EaLbpZSCinIVI4kSQzWhkShK83GogvEFJSsHF3Ws0z1vrqA==} - engines: {node: '>=12'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/runtime': 7.18.3 - '@types/aria-query': 4.2.2 - aria-query: 5.0.0 - chalk: 4.1.2 - dom-accessibility-api: 0.5.14 - lz-string: 1.4.4 - pretty-format: 27.5.1 - dev: true + /@testing-library/dom/8.14.0: + resolution: {integrity: sha512-m8FOdUo77iMTwVRCyzWcqxlEIk+GnopbrRI15a0EaLbpZSCinIVI4kSQzWhkShK83GogvEFJSsHF3Ws0z1vrqA==} + engines: {node: '>=12'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/runtime': 7.18.3 + '@types/aria-query': 4.2.2 + aria-query: 5.0.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.14 + lz-string: 1.4.4 + pretty-format: 27.5.1 + dev: true /@testing-library/react/13.3.0_zpnidt7m3osuk7shl3s4oenomq: resolution: {integrity: sha512-DB79aA426+deFgGSjnf5grczDPiL4taK3hFaa+M5q7q20Kcve9eQottOG5kZ74KEr55v0tU2CQormSSDK87zYQ==} @@ -5838,7 +5557,7 @@ packages: resolution: {integrity: sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.0.8 + '@types/react': registry.npmjs.org/@types/react/18.0.8 /@types/react/18.0.8: resolution: {integrity: sha512-+j2hk9BzCOrrOSJASi5XiOyBbERk9jG5O73Ya4M0env5Ixi6vUNli4qy994AINcEF+1IEHISYFfIT4zwr++LKw==} @@ -5918,7 +5637,7 @@ packages: dev: true /@types/webpack/5.28.0: - resolution: {integrity: sha512-8cP0CzcxUiFuA9xGJkfeVpqmWTk9nx6CWwamRGCj95ph1SmlRRk9KlCZ6avhCbZd4L68LvYT6l1kpdEnQXrF8w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/@types/webpack/-/webpack-5.28.0.tgz} + resolution: {integrity: sha512-8cP0CzcxUiFuA9xGJkfeVpqmWTk9nx6CWwamRGCj95ph1SmlRRk9KlCZ6avhCbZd4L68LvYT6l1kpdEnQXrF8w==} dependencies: '@types/node': 17.0.27 tapable: 2.2.1 @@ -5935,14 +5654,6 @@ packages: dependencies: '@types/node': 17.0.27 - /@types/yauzl/2.10.0: - resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} - requiresBuild: true - dependencies: - '@types/node': 17.0.27 - dev: true - optional: true - /@typescript-eslint/eslint-plugin/5.21.0_3pkyrc4fw5t5novybddanxmrai: resolution: {integrity: sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -6560,7 +6271,7 @@ packages: engines: {node: '>=12'} /ansi-styles/2.2.1: - resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/ansi-styles/-/ansi-styles-2.2.1.tgz} + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} engines: {node: '>=0.10.0'} dev: false @@ -6649,13 +6360,6 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 - /appear-polyfill/0.1.2: - resolution: {integrity: sha512-s2113Awjp9pyyczgFqNK7DTjKCwfzwkerhHqa6YbsSQvi5ZuRYgirjzuPn9JJi/b0GE2R4lY9LrhoW5YDa65Ug==} - engines: {npm: '>=3.0.0'} - peerDependencies: - rax: ^1.0.0 - dev: false - /append-field/1.0.0: resolution: {integrity: sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=} dev: false @@ -6801,7 +6505,7 @@ packages: engines: {node: '>= 4.0.0'} /atob/2.1.2: - resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/atob/-/atob-2.1.2.tgz} + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} hasBin: true dev: false @@ -7012,7 +6716,7 @@ packages: resolution: {integrity: sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=} /big.js/5.2.2: - resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/big.js/-/big.js-5.2.2.tgz} + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} /big.js/6.2.0: resolution: {integrity: sha512-paIKvJiAaOYdLt6MfnvxkDo64lTOV257XYJyX3oJnJQocIclUn+48k6ZerH/c5FxWE6DGJu1TKDYis7tqHg9kg==} @@ -7285,7 +6989,7 @@ packages: dev: true /camelcase/3.0.0: - resolution: {integrity: sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/camelcase/-/camelcase-3.0.0.tgz} + resolution: {integrity: sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==} engines: {node: '>=0.10.0'} dev: false @@ -7328,7 +7032,7 @@ packages: dev: true /chalk/1.1.3: - resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/chalk/-/chalk-1.1.3.tgz} + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} dependencies: ansi-styles: 2.2.1 @@ -7405,7 +7109,7 @@ packages: normalize-path: 3.0.0 readdirp: 3.6.0 optionalDependencies: - fsevents: 2.3.2 + fsevents: registry.npmjs.org/fsevents/2.3.2 /chownr/1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -7462,7 +7166,7 @@ packages: dependencies: string-width: 4.2.3 optionalDependencies: - '@colors/colors': 1.5.0 + '@colors/colors': registry.npmjs.org/@colors/colors/1.5.0 /cli-width/3.0.0: resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} @@ -8110,7 +7814,7 @@ packages: engines: {node: '>=8.0.0'} dependencies: mdn-data: 2.0.14 - source-map: 0.6.1 + source-map: registry.npmjs.org/source-map/0.6.1 /css-what/3.4.2: resolution: {integrity: sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==} @@ -8122,7 +7826,7 @@ packages: engines: {node: '>= 6'} /css/2.2.4: - resolution: {integrity: sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/css/-/css-2.2.4.tgz} + resolution: {integrity: sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==} dependencies: inherits: 2.0.4 source-map: 0.6.1 @@ -8452,7 +8156,7 @@ packages: dev: true /decode-uri-component/0.2.0: - resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz} + resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==} engines: {node: '>=0.10'} dev: false @@ -8830,7 +8534,7 @@ packages: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} /emojis-list/3.0.0: - resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/emojis-list/-/emojis-list-3.0.0.tgz} + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} engines: {node: '>= 4'} /emoticon/3.2.0: @@ -8874,14 +8578,6 @@ packages: resolution: {integrity: sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==} engines: {node: '>=0.12'} - /errno/0.1.8: - resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} - hasBin: true - requiresBuild: true - dependencies: - prr: 1.0.1 - optional: true - /error-ex/1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: @@ -8972,140 +8668,12 @@ packages: is-date-object: 1.0.5 is-symbol: 1.0.4 - /esbuild-android-64/0.14.38: - resolution: {integrity: sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true - - /esbuild-android-arm64/0.14.38: - resolution: {integrity: sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - - /esbuild-darwin-64/0.14.38: - resolution: {integrity: sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /esbuild-darwin-arm64/0.14.38: - resolution: {integrity: sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /esbuild-freebsd-64/0.14.38: - resolution: {integrity: sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - - /esbuild-freebsd-arm64/0.14.38: - resolution: {integrity: sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - - /esbuild-linux-32/0.14.38: - resolution: {integrity: sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - optional: true - - /esbuild-linux-64/0.14.38: - resolution: {integrity: sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /esbuild-linux-arm/0.14.38: - resolution: {integrity: sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /esbuild-linux-arm64/0.14.38: - resolution: {integrity: sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /esbuild-linux-mips64le/0.14.38: - resolution: {integrity: sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - optional: true - - /esbuild-linux-ppc64le/0.14.38: - resolution: {integrity: sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - optional: true - - /esbuild-linux-riscv64/0.14.38: - resolution: {integrity: sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true - - /esbuild-linux-s390x/0.14.38: - resolution: {integrity: sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true - - /esbuild-netbsd-64/0.14.38: - resolution: {integrity: sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true - /esbuild-node-loader/0.6.5: resolution: {integrity: sha512-uPP+dllWm38cFvDysdocutN3lfe5pTIbddAHp1ENyLzpHYqE2r+3Wo+pfg9X3p8DFWwzIisft5YkeBIthIcixw==} dependencies: esbuild: 0.14.38 dev: true - /esbuild-openbsd-64/0.14.38: - resolution: {integrity: sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true - /esbuild-register/3.3.2_esbuild@0.14.38: resolution: {integrity: sha512-jceAtTO6zxPmCfSD5cBb3rgIK1vmuqCKYwgylHiS1BF4pq0jJiJb4K2QMuqF4BEw7XDBRatYzip0upyTzfkgsQ==} peerDependencies: @@ -9113,64 +8681,32 @@ packages: dependencies: esbuild: 0.14.38 - /esbuild-sunos-64/0.14.38: - resolution: {integrity: sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true - - /esbuild-windows-32/0.14.38: - resolution: {integrity: sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /esbuild-windows-64/0.14.38: - resolution: {integrity: sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - - /esbuild-windows-arm64/0.14.38: - resolution: {integrity: sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - /esbuild/0.14.38: resolution: {integrity: sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - esbuild-android-64: 0.14.38 - esbuild-android-arm64: 0.14.38 - esbuild-darwin-64: 0.14.38 - esbuild-darwin-arm64: 0.14.38 - esbuild-freebsd-64: 0.14.38 - esbuild-freebsd-arm64: 0.14.38 - esbuild-linux-32: 0.14.38 - esbuild-linux-64: 0.14.38 - esbuild-linux-arm: 0.14.38 - esbuild-linux-arm64: 0.14.38 - esbuild-linux-mips64le: 0.14.38 - esbuild-linux-ppc64le: 0.14.38 - esbuild-linux-riscv64: 0.14.38 - esbuild-linux-s390x: 0.14.38 - esbuild-netbsd-64: 0.14.38 - esbuild-openbsd-64: 0.14.38 - esbuild-sunos-64: 0.14.38 - esbuild-windows-32: 0.14.38 - esbuild-windows-64: 0.14.38 - esbuild-windows-arm64: 0.14.38 + esbuild-android-64: registry.npmjs.org/esbuild-android-64/0.14.38 + esbuild-android-arm64: registry.npmjs.org/esbuild-android-arm64/0.14.38 + esbuild-darwin-64: registry.npmjs.org/esbuild-darwin-64/0.14.38 + esbuild-darwin-arm64: registry.npmjs.org/esbuild-darwin-arm64/0.14.38 + esbuild-freebsd-64: registry.npmjs.org/esbuild-freebsd-64/0.14.38 + esbuild-freebsd-arm64: registry.npmjs.org/esbuild-freebsd-arm64/0.14.38 + esbuild-linux-32: registry.npmjs.org/esbuild-linux-32/0.14.38 + esbuild-linux-64: registry.npmjs.org/esbuild-linux-64/0.14.38 + esbuild-linux-arm: registry.npmjs.org/esbuild-linux-arm/0.14.38 + esbuild-linux-arm64: registry.npmjs.org/esbuild-linux-arm64/0.14.38 + esbuild-linux-mips64le: registry.npmjs.org/esbuild-linux-mips64le/0.14.38 + esbuild-linux-ppc64le: registry.npmjs.org/esbuild-linux-ppc64le/0.14.38 + esbuild-linux-riscv64: registry.npmjs.org/esbuild-linux-riscv64/0.14.38 + esbuild-linux-s390x: registry.npmjs.org/esbuild-linux-s390x/0.14.38 + esbuild-netbsd-64: registry.npmjs.org/esbuild-netbsd-64/0.14.38 + esbuild-openbsd-64: registry.npmjs.org/esbuild-openbsd-64/0.14.38 + esbuild-sunos-64: registry.npmjs.org/esbuild-sunos-64/0.14.38 + esbuild-windows-32: registry.npmjs.org/esbuild-windows-32/0.14.38 + esbuild-windows-64: registry.npmjs.org/esbuild-windows-64/0.14.38 + esbuild-windows-arm64: registry.npmjs.org/esbuild-windows-arm64/0.14.38 /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -9206,7 +8742,7 @@ packages: esutils: 2.0.3 optionator: 0.8.3 optionalDependencies: - source-map: 0.6.1 + source-map: registry.npmjs.org/source-map/0.6.1 dev: true /eslint-config-ali/13.1.0_eslint@7.32.0: @@ -9822,7 +9358,7 @@ packages: get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: - '@types/yauzl': 2.10.0 + '@types/yauzl': registry.npmjs.org/@types/yauzl/2.10.0 transitivePeerDependencies: - supports-color dev: true @@ -10231,13 +9767,6 @@ packages: /fs.realpath/1.0.0: resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} - /fsevents/2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - optional: true - /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} @@ -10571,7 +10100,7 @@ packages: source-map: 0.6.1 wordwrap: 1.0.0 optionalDependencies: - uglify-js: 3.15.5 + uglify-js: registry.npmjs.org/uglify-js/3.15.5 dev: true /hard-rejection/2.1.0: @@ -10580,7 +10109,7 @@ packages: dev: true /has-ansi/2.0.0: - resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/has-ansi/-/has-ansi-2.0.0.tgz} + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} engines: {node: '>=0.10.0'} dependencies: ansi-regex: 2.1.1 @@ -11032,13 +10561,6 @@ packages: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} - /image-size/0.5.5: - resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} - engines: {node: '>=0.10.0'} - hasBin: true - requiresBuild: true - optional: true - /image-size/1.0.1: resolution: {integrity: sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==} engines: {node: '>=12.0.0'} @@ -11661,7 +11183,7 @@ packages: dev: true /json5/1.0.1: - resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/json5/-/json5-1.0.1.tgz} + resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true dependencies: minimist: 1.2.6 @@ -11674,14 +11196,14 @@ packages: /jsonfile/4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: - graceful-fs: 4.2.10 + graceful-fs: registry.npmjs.org/graceful-fs/4.2.10 /jsonfile/6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: universalify: 2.0.0 optionalDependencies: - graceful-fs: 4.2.10 + graceful-fs: registry.npmjs.org/graceful-fs/4.2.10 /jsonparse/1.3.1: resolution: {integrity: sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=} @@ -11772,13 +11294,13 @@ packages: parse-node-version: 1.0.1 tslib: 2.4.0 optionalDependencies: - errno: 0.1.8 - graceful-fs: 4.2.10 - image-size: 0.5.5 - make-dir: 2.1.0 - mime: 1.6.0 - needle: 2.9.1 - source-map: 0.6.1 + errno: registry.npmjs.org/errno/0.1.8 + graceful-fs: registry.npmjs.org/graceful-fs/4.2.10 + image-size: registry.npmjs.org/image-size/0.5.5 + make-dir: registry.npmjs.org/make-dir/2.1.0 + mime: registry.npmjs.org/mime/1.6.0 + needle: registry.npmjs.org/needle/2.9.1 + source-map: registry.npmjs.org/source-map/0.6.1 transitivePeerDependencies: - supports-color @@ -11821,7 +11343,7 @@ packages: engines: {node: '>=6.11.5'} /loader-utils/1.4.0: - resolution: {integrity: sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/loader-utils/-/loader-utils-1.4.0.tgz} + resolution: {integrity: sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==} engines: {node: '>=4.0.0'} dependencies: big.js: 5.2.2 @@ -11895,7 +11417,6 @@ packages: /lodash.merge/4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true /lodash.truncate/4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} @@ -11981,15 +11502,6 @@ packages: sourcemap-codec: 1.4.8 dev: false - /make-dir/2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - requiresBuild: true - dependencies: - pify: 4.0.1 - semver: 5.7.1 - optional: true - /make-dir/3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -12394,19 +11906,6 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /needle/2.9.1: - resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} - engines: {node: '>= 4.4.x'} - hasBin: true - requiresBuild: true - dependencies: - debug: 3.2.7 - iconv-lite: 0.4.24 - sax: 1.2.4 - transitivePeerDependencies: - - supports-color - optional: true - /negotiator/0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -14772,7 +14271,7 @@ packages: webpack: '>=4.41.1 || 5.x' dependencies: '@babel/runtime': 7.17.9 - react-loadable: /@docusaurus/react-loadable/5.5.2_react@18.0.0 + react-loadable: registry.npmjs.org/@docusaurus/react-loadable/5.5.2_react@18.0.0 webpack: 5.72.0 dev: true @@ -14784,7 +14283,7 @@ packages: webpack: '>=4.41.1 || 5.x' dependencies: '@babel/runtime': 7.17.9 - react-loadable: /@docusaurus/react-loadable/5.5.2_react@18.2.0 + react-loadable: registry.npmjs.org/@docusaurus/react-loadable/5.5.2_react@18.2.0 webpack: 5.72.1 dev: false @@ -15261,7 +14760,7 @@ packages: resolution: {integrity: sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==} /resolve-url/0.2.1: - resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/resolve-url/-/resolve-url-0.2.1.tgz} + resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} deprecated: https://github.com/lydell/resolve-url#deprecated dev: false @@ -15353,7 +14852,7 @@ packages: engines: {node: '>=10.0.0'} hasBin: true optionalDependencies: - fsevents: 2.3.2 + fsevents: registry.npmjs.org/fsevents/2.3.2 dev: true /rtl-detect/1.0.4: @@ -15786,7 +15285,7 @@ packages: engines: {node: '>=0.10.0'} /source-map-resolve/0.5.3: - resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz} + resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} deprecated: See https://github.com/lydell/source-map-resolve#deprecated dependencies: atob: 2.1.2 @@ -15803,7 +15302,7 @@ packages: source-map: 0.6.1 /source-map-url/0.4.1: - resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/source-map-url/-/source-map-url-0.4.1.tgz} + resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} deprecated: See https://github.com/lydell/source-map-url#deprecated dev: false @@ -16272,7 +15771,7 @@ packages: dev: true /stylesheet-loader/0.9.1: - resolution: {integrity: sha512-GDdV3oYsuO8VkmCCFsqNKjo42iRcf3mMhLhvEqktJajJ7HDxj/YAureXCZVqzu6YRgtc/Fhq4WtlaNUaGpz3/g==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/stylesheet-loader/-/stylesheet-loader-0.9.1.tgz} + resolution: {integrity: sha512-GDdV3oYsuO8VkmCCFsqNKjo42iRcf3mMhLhvEqktJajJ7HDxj/YAureXCZVqzu6YRgtc/Fhq4WtlaNUaGpz3/g==} dependencies: camelcase: 3.0.0 chalk: 1.1.3 @@ -16287,7 +15786,7 @@ packages: dev: true /supports-color/2.0.0: - resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/supports-color/-/supports-color-2.0.0.tgz} + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} engines: {node: '>=0.8.0'} dev: false @@ -16824,14 +16323,6 @@ packages: /ua-parser-js/0.7.31: resolution: {integrity: sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==} - /uglify-js/3.15.5: - resolution: {integrity: sha512-hNM5q5GbBRB5xB+PMqVRcgYe4c8jbyZ1pzZhS6jbq54/4F2gFK869ZheiE5A8/t+W5jtTNpWef/5Q9zk639FNQ==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - /unbox-primitive/1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -17040,7 +16531,7 @@ packages: punycode: 2.1.1 /urix/0.1.0: - resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.com/urix/-/urix-0.1.0.tgz} + resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} deprecated: Please see https://github.com/lydell/urix#deprecated dev: false @@ -17298,7 +16789,7 @@ packages: resolve: 1.22.0 rollup: 2.70.2 optionalDependencies: - fsevents: 2.3.2 + fsevents: registry.npmjs.org/fsevents/2.3.2 dev: true /vitest/0.15.2_c8@7.11.2+jsdom@20.0.0: @@ -18240,3 +17731,767 @@ packages: /zwitch/1.0.5: resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==} + + registry.npmjs.org/@builder/swc-darwin-arm64/0.2.0: + resolution: {integrity: sha512-+nmnScnq40eMKqCLpVwl7P/JCHrzm9q1ECvD/nGTNATweMB0hhTjX7V/5DfHELl1RHGnw7NchAuVJDesNa9daw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-darwin-arm64/-/swc-darwin-arm64-0.2.0.tgz} + name: '@builder/swc-darwin-arm64' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + registry.npmjs.org/@builder/swc-darwin-x64/0.2.0: + resolution: {integrity: sha512-vR9H+o5WmrasoAgMmL9HA2DfUosreGt0Pak54iOIyu3V6hSXaLxKuSidqEMcWBG1nN2wEYBvlzP8s04WusqPRQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-darwin-x64/-/swc-darwin-x64-0.2.0.tgz} + name: '@builder/swc-darwin-x64' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + registry.npmjs.org/@builder/swc-linux-arm64-gnu/0.2.0: + resolution: {integrity: sha512-O18+aSQ7ZGcBwongjsatQ7OcJo9D0YDsBujPkQfQ0sBwnxmzGTw4kkXHr/K9Bou9wcy8TEpXRfaauaLHzzecAA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-0.2.0.tgz} + name: '@builder/swc-linux-arm64-gnu' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@builder/swc-linux-arm64-musl/0.2.0: + resolution: {integrity: sha512-0vkGpqmJNOfsWh7qb3Mqga0gJPsAomxPitWapRlFQ736Q0qHL4Bb270/VZO3xcjA0zZKaN8VdwVw+Pxqg3ziQA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-linux-arm64-musl/-/swc-linux-arm64-musl-0.2.0.tgz} + name: '@builder/swc-linux-arm64-musl' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@builder/swc-linux-x64-gnu/0.2.0: + resolution: {integrity: sha512-6gPaiwQq1l/eeNthOBvWInHU5i2bfbnGuw4YDsTF2pHhbHd7eR++N5viTROJLjFaZevWrNUbfMc47IMRGQg7WA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-linux-x64-gnu/-/swc-linux-x64-gnu-0.2.0.tgz} + name: '@builder/swc-linux-x64-gnu' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@builder/swc-linux-x64-musl/0.2.0: + resolution: {integrity: sha512-01zpp3sHM48x1Tl1fzM6si1E6ZIooJkXts+vPu36v265gXEb1winhFHCXXtQXvSHZ/XEyRFD1BcgdCm3goSJRw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-linux-x64-musl/-/swc-linux-x64-musl-0.2.0.tgz} + name: '@builder/swc-linux-x64-musl' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@builder/swc-win32-arm64-msvc/0.2.0: + resolution: {integrity: sha512-+06kFldeVV1Yzy2tfkeClwsglW50j6qG2vpTA3Tqwp5kEAGFNT1tUwsoWcbySJSCRlGBAVHDZxJlsUMqSK34Yw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-0.2.0.tgz} + name: '@builder/swc-win32-arm64-msvc' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/@builder/swc-win32-ia32-msvc/0.2.0: + resolution: {integrity: sha512-wc9GA1YWv5ZxVYl73KDdRuX3All8reNIUbtPEKz2LwQ5locUX6gb7pdDzDz0et/xXjshZRGka7wDU2wzgi8Giw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-0.2.0.tgz} + name: '@builder/swc-win32-ia32-msvc' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/@builder/swc-win32-x64-msvc/0.2.0: + resolution: {integrity: sha512-l8eMGTigKHrA46HAkXWblYwxQeT/SEe9yKrIYi2kfngWHNUALUFlPnnoJOSmLCGwPRZTHUgcx45Ta+15ahj5DQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@builder/swc-win32-x64-msvc/-/swc-win32-x64-msvc-0.2.0.tgz} + name: '@builder/swc-win32-x64-msvc' + version: 0.2.0 + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/@colors/colors/1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz} + name: '@colors/colors' + version: 1.5.0 + engines: {node: '>=0.1.90'} + requiresBuild: true + optional: true + + registry.npmjs.org/@docusaurus/react-loadable/5.5.2_react@18.0.0: + resolution: {integrity: sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz} + id: registry.npmjs.org/@docusaurus/react-loadable/5.5.2 + name: '@docusaurus/react-loadable' + version: 5.5.2 + peerDependencies: + react: '*' + dependencies: + '@types/react': registry.npmjs.org/@types/react/18.0.8 + prop-types: registry.npmjs.org/prop-types/15.8.1 + react: 18.0.0 + dev: true + + registry.npmjs.org/@docusaurus/react-loadable/5.5.2_react@18.2.0: + resolution: {integrity: sha512-A3dYjdBGuy0IGT+wyLIGIKLRE+sAk1iNk0f1HjNDysO7u8lhL4N3VEm+FAubmJbAztn94F7MxBTPmnixbiyFdQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-5.5.2.tgz} + id: registry.npmjs.org/@docusaurus/react-loadable/5.5.2 + name: '@docusaurus/react-loadable' + version: 5.5.2 + peerDependencies: + react: '*' + dependencies: + '@types/react': registry.npmjs.org/@types/react/18.0.8 + prop-types: registry.npmjs.org/prop-types/15.8.1 + react: 18.2.0 + dev: false + + registry.npmjs.org/@node-rs/jieba-android-arm-eabi/1.6.1: + resolution: {integrity: sha512-R1YQfsPr7sK3Tq1sM0//6lNAGJK9RnMT0ShITT+7EJYr5OufUBb38lf/mRhrLxR0NF1pycEsMjdCAwrWrHd8rA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-android-arm-eabi/-/jieba-android-arm-eabi-1.6.1.tgz} + name: '@node-rs/jieba-android-arm-eabi' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-android-arm64/1.6.1: + resolution: {integrity: sha512-hBRbj2uLmRFYDw2lWppTAPoyjeXkBKUT84h4fHUQj7CMU94Gc1IWkE4ocCqhvUhbaUXlCpocS9mB0/fc2641bw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-android-arm64/-/jieba-android-arm64-1.6.1.tgz} + name: '@node-rs/jieba-android-arm64' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-darwin-arm64/1.6.1: + resolution: {integrity: sha512-GeoDe7XVTF6z8JUtD98QvwudsMaHV5EBXs5uO43SobeIkShH3Nujq5gLMD5kWoJXTxDrTgJe4wT42EwUaBEH2Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-darwin-arm64/-/jieba-darwin-arm64-1.6.1.tgz} + name: '@node-rs/jieba-darwin-arm64' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-darwin-x64/1.6.1: + resolution: {integrity: sha512-ENHYIS8b8JdMaUXEm0f8Y3+sHXu2UdukG1D/XGUNx+q5cn07HbwIg6L0tlGhE8dw4AhqoWHsExVaZ241Igh4iA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-darwin-x64/-/jieba-darwin-x64-1.6.1.tgz} + name: '@node-rs/jieba-darwin-x64' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-freebsd-x64/1.6.1: + resolution: {integrity: sha512-chwB/9edtxqS8Jm3j4RMaJjH9AlXmijUgKv02oMw36e77HKpko+tENUN25Vrn/9GKsKGqIPeXpmCjeXCN1HVQA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-freebsd-x64/-/jieba-freebsd-x64-1.6.1.tgz} + name: '@node-rs/jieba-freebsd-x64' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-linux-arm-gnueabihf/1.6.1: + resolution: {integrity: sha512-tsb5fMGj4p8bHGfkf7bJ+HE2jxaixLTp3YnGg5D+kp8+HQRq8cp3ScG5cn8cq0phnJS/zfAp8rVfWInDagzKKQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-linux-arm-gnueabihf/-/jieba-linux-arm-gnueabihf-1.6.1.tgz} + name: '@node-rs/jieba-linux-arm-gnueabihf' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-linux-arm64-gnu/1.6.1: + resolution: {integrity: sha512-bSInORkJFfeZNR+i4rFoSZGbwkQtQlnZ0XfT/noTK9JUBDYErqQZPFjoaYAU45NWTk7p6Zkg30SuV1NTdWLaPw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-linux-arm64-gnu/-/jieba-linux-arm64-gnu-1.6.1.tgz} + name: '@node-rs/jieba-linux-arm64-gnu' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-linux-arm64-musl/1.6.1: + resolution: {integrity: sha512-qphL6xM7owfU8Hsh7GX73SDr/iApbnc+35mSLxbibAfCQnY89+WcBeWUUOSGM/Ov3VFaq4pyVlDFj0YjR01W2w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-linux-arm64-musl/-/jieba-linux-arm64-musl-1.6.1.tgz} + name: '@node-rs/jieba-linux-arm64-musl' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-linux-x64-gnu/1.6.1: + resolution: {integrity: sha512-f6hhlrbi2wel0xZG7m3Wvksimt9MSu1f3aYO2Kwavf4qjMRZqJzLz9HlCJAal6AXB9Qgg+685P+gftsWve47qw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-linux-x64-gnu/-/jieba-linux-x64-gnu-1.6.1.tgz} + name: '@node-rs/jieba-linux-x64-gnu' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-linux-x64-musl/1.6.1: + resolution: {integrity: sha512-cTVcdR6zWqpnmdEUyWEII9zfE5lTeWN53TbiOPx8TCA+291/31Vqd7GA8YEPndUO8qgCx5uShSDFStBAEIhYNQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-linux-x64-musl/-/jieba-linux-x64-musl-1.6.1.tgz} + name: '@node-rs/jieba-linux-x64-musl' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-win32-arm64-msvc/1.6.1: + resolution: {integrity: sha512-YuOTrjHazDraXcGXRHgPQ53nyJuH8QtTCngYKjAzxsdt8uN+txb1AY69OLMLBBZqLTOwY9dgcW70vGiLQMCTeg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-win32-arm64-msvc/-/jieba-win32-arm64-msvc-1.6.1.tgz} + name: '@node-rs/jieba-win32-arm64-msvc' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-win32-ia32-msvc/1.6.1: + resolution: {integrity: sha512-4+E843ImGpVlZ+LlT9E/13NHmmUg3UHQx419D6fFMorJUUQuK4cZJfE1z4tCgcrbV8S5Wew5LIFywlJeJLu0LQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-win32-ia32-msvc/-/jieba-win32-ia32-msvc-1.6.1.tgz} + name: '@node-rs/jieba-win32-ia32-msvc' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@node-rs/jieba-win32-x64-msvc/1.6.1: + resolution: {integrity: sha512-veXNwm2VlseOzl7vaC7A/nZ4okp5/6edN7/Atj6mXnUbze/m/my5Rv5zUcW3U1D9VElnQ3srCHCa5vXljJuk6g==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@node-rs/jieba-win32-x64-msvc/-/jieba-win32-x64-msvc-1.6.1.tgz} + name: '@node-rs/jieba-win32-x64-msvc' + version: 1.6.1 + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + registry.npmjs.org/@swc/core-android-arm-eabi/1.2.168: + resolution: {integrity: sha512-RjjudVdJxm1KoNrbFxQIppJQjB1mzMYKW6+HYKVl8ktc7i/mnjwcl0cXVBWGbw1xsRWbTjHMHPs/kJ3hOESoeg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-android-arm-eabi/-/core-android-arm-eabi-1.2.168.tgz} + name: '@swc/core-android-arm-eabi' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-android-arm64/1.2.168: + resolution: {integrity: sha512-K83gxb578LJid4GI047oSdaK90REnaXfXa+f+DT3Ud5hKFDrF7zkpyF6oxfHJGTl9LCUMXhijwg8aRXaFZFqWQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-android-arm64/-/core-android-arm64-1.2.168.tgz} + name: '@swc/core-android-arm64' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-darwin-arm64/1.2.168: + resolution: {integrity: sha512-/kciTqYbEryg3e2C+/Twpww7LBc+zaF7yhz2AmxOrA7nQKuUNHA3Q/Y4sXthSXD2BLqPABJETbRmfmumNi8gQA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.168.tgz} + name: '@swc/core-darwin-arm64' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-darwin-x64/1.2.168: + resolution: {integrity: sha512-PbciVgB24OX6QCUmJmkD2hfZQh9LostC89vALfasUwT/wj3rHeg2SD2rvoPlIf0lYZjUPNfpbhDoxkUeEt+SEg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.2.168.tgz} + name: '@swc/core-darwin-x64' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-freebsd-x64/1.2.168: + resolution: {integrity: sha512-lp3lNrjF2vNSOtsRFVRDs0EBpwoXQSD0MeZugX9EwHbHXavPlY+Kmo6cNqHfdrxIVOoVOYMlqQn+kO3/4mwYAQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.168.tgz} + name: '@swc/core-freebsd-x64' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-linux-arm-gnueabihf/1.2.168: + resolution: {integrity: sha512-TVYXoITQTCPOthHXhmBHFR77mXKE3tGN8CRAHtFYC0mUb42LY5nUQ8yc6peNpcvSqAUzK9K079koDltWIDfWKw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.168.tgz} + name: '@swc/core-linux-arm-gnueabihf' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-linux-arm64-gnu/1.2.168: + resolution: {integrity: sha512-Xw7Vj/4EJA5V8kQ5cziUbj3qZQSt8n5Pr2TnFCZ3NkCL8og2JYf2N1mOTAI+PIknaDqh1boz+k9xEs1araQ2lA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.168.tgz} + name: '@swc/core-linux-arm64-gnu' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-linux-arm64-musl/1.2.168: + resolution: {integrity: sha512-71HHYhyNxpv1Maiqv/U5cHFMitU3MP2TN77vTi5ifPw+6H7A3fG86aqE8zr7YEGsSmOzgQUrMMblqvwe52IrlQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.168.tgz} + name: '@swc/core-linux-arm64-musl' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-linux-x64-gnu/1.2.168: + resolution: {integrity: sha512-kEP3VN6Seoz73Fyu+80qkKtIURl/FvlT6NNju55uTMqeeiF3su0CRC60A2/IWHwAZ8sjlorgcXQeaiNTyJmWBQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.168.tgz} + name: '@swc/core-linux-x64-gnu' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-linux-x64-musl/1.2.168: + resolution: {integrity: sha512-IEDB4T5KyUB0BEdIsSJuFm1CV9Y1wIEG15870J0dONkvO1iv5lqWZ7GwA52w/YaI61iNC8+cZYWqfwr4MWj1EQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.168.tgz} + name: '@swc/core-linux-x64-musl' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-win32-arm64-msvc/1.2.168: + resolution: {integrity: sha512-cBiYhBdrW+GdfKJdNhIE/7Pw+45Kn7SKZ78TPc/0ibGXDdx2IkuDhO7x1eZy0eLlS+Br6OLUs9FkgbcMrpZAGw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.168.tgz} + name: '@swc/core-win32-arm64-msvc' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-win32-ia32-msvc/1.2.168: + resolution: {integrity: sha512-ShbX43+hFqDWLU4R8FnDFIPXR8OzC0zBwJBj8QPV3YmeoQD+wyA7NGBccm/8UbnEY5uE2t7P4Pz8891d6TW3Ww==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.168.tgz} + name: '@swc/core-win32-ia32-msvc' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/core-win32-x64-msvc/1.2.168: + resolution: {integrity: sha512-e+SPSiBHSlAI4+RM+Fcz8HVqpHQaGFiDL4b8LwguVgRdoDVeJAjamw53r2UJ23X++9PXamT3rhzPs5XEH0PQhg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.168.tgz} + name: '@swc/core-win32-x64-msvc' + version: 1.2.168 + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/@swc/helpers/0.4.3: + resolution: {integrity: sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.3.tgz} + name: '@swc/helpers' + version: 0.4.3 + dependencies: + tslib: registry.npmjs.org/tslib/2.4.0 + dev: false + + registry.npmjs.org/@types/prop-types/15.7.5: + resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz} + name: '@types/prop-types' + version: 15.7.5 + + registry.npmjs.org/@types/react/18.0.8: + resolution: {integrity: sha512-+j2hk9BzCOrrOSJASi5XiOyBbERk9jG5O73Ya4M0env5Ixi6vUNli4qy994AINcEF+1IEHISYFfIT4zwr++LKw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/react/-/react-18.0.8.tgz} + name: '@types/react' + version: 18.0.8 + dependencies: + '@types/prop-types': registry.npmjs.org/@types/prop-types/15.7.5 + '@types/scheduler': registry.npmjs.org/@types/scheduler/0.16.2 + csstype: registry.npmjs.org/csstype/3.0.11 + + registry.npmjs.org/@types/scheduler/0.16.2: + resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz} + name: '@types/scheduler' + version: 0.16.2 + + registry.npmjs.org/@types/yauzl/2.10.0: + resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz} + name: '@types/yauzl' + version: 2.10.0 + requiresBuild: true + dependencies: + '@types/node': 17.0.27 + dev: true + optional: true + + registry.npmjs.org/csstype/3.0.11: + resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz} + name: csstype + version: 3.0.11 + + registry.npmjs.org/errno/0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/errno/-/errno-0.1.8.tgz} + name: errno + version: 0.1.8 + hasBin: true + requiresBuild: true + dependencies: + prr: 1.0.1 + optional: true + + registry.npmjs.org/esbuild-android-64/0.14.38: + resolution: {integrity: sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz} + name: esbuild-android-64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-android-arm64/0.14.38: + resolution: {integrity: sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz} + name: esbuild-android-arm64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-darwin-64/0.14.38: + resolution: {integrity: sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz} + name: esbuild-darwin-64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-darwin-arm64/0.14.38: + resolution: {integrity: sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz} + name: esbuild-darwin-arm64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-freebsd-64/0.14.38: + resolution: {integrity: sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz} + name: esbuild-freebsd-64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-freebsd-arm64/0.14.38: + resolution: {integrity: sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz} + name: esbuild-freebsd-arm64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-linux-32/0.14.38: + resolution: {integrity: sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz} + name: esbuild-linux-32 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-linux-64/0.14.38: + resolution: {integrity: sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz} + name: esbuild-linux-64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-linux-arm/0.14.38: + resolution: {integrity: sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz} + name: esbuild-linux-arm + version: 0.14.38 + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-linux-arm64/0.14.38: + resolution: {integrity: sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz} + name: esbuild-linux-arm64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-linux-mips64le/0.14.38: + resolution: {integrity: sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz} + name: esbuild-linux-mips64le + version: 0.14.38 + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-linux-ppc64le/0.14.38: + resolution: {integrity: sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz} + name: esbuild-linux-ppc64le + version: 0.14.38 + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-linux-riscv64/0.14.38: + resolution: {integrity: sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz} + name: esbuild-linux-riscv64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-linux-s390x/0.14.38: + resolution: {integrity: sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz} + name: esbuild-linux-s390x + version: 0.14.38 + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-netbsd-64/0.14.38: + resolution: {integrity: sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz} + name: esbuild-netbsd-64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-openbsd-64/0.14.38: + resolution: {integrity: sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz} + name: esbuild-openbsd-64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-sunos-64/0.14.38: + resolution: {integrity: sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz} + name: esbuild-sunos-64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-windows-32/0.14.38: + resolution: {integrity: sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz} + name: esbuild-windows-32 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-windows-64/0.14.38: + resolution: {integrity: sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz} + name: esbuild-windows-64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/esbuild-windows-arm64/0.14.38: + resolution: {integrity: sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz} + name: esbuild-windows-arm64 + version: 0.14.38 + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + registry.npmjs.org/fsevents/2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz} + name: fsevents + version: 2.3.2 + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + optional: true + + registry.npmjs.org/graceful-fs/4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz} + name: graceful-fs + version: 4.2.10 + requiresBuild: true + optional: true + + registry.npmjs.org/image-size/0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz} + name: image-size + version: 0.5.5 + engines: {node: '>=0.10.0'} + hasBin: true + requiresBuild: true + optional: true + + registry.npmjs.org/js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz} + name: js-tokens + version: 4.0.0 + + registry.npmjs.org/loose-envify/1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz} + name: loose-envify + version: 1.4.0 + hasBin: true + dependencies: + js-tokens: registry.npmjs.org/js-tokens/4.0.0 + + registry.npmjs.org/make-dir/2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz} + name: make-dir + version: 2.1.0 + engines: {node: '>=6'} + requiresBuild: true + dependencies: + pify: 4.0.1 + semver: 5.7.1 + optional: true + + registry.npmjs.org/mime/1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/mime/-/mime-1.6.0.tgz} + name: mime + version: 1.6.0 + engines: {node: '>=4'} + hasBin: true + requiresBuild: true + optional: true + + registry.npmjs.org/needle/2.9.1: + resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/needle/-/needle-2.9.1.tgz} + name: needle + version: 2.9.1 + engines: {node: '>= 4.4.x'} + hasBin: true + requiresBuild: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.4.24 + sax: 1.2.4 + transitivePeerDependencies: + - supports-color + optional: true + + registry.npmjs.org/object-assign/4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz} + name: object-assign + version: 4.1.1 + engines: {node: '>=0.10.0'} + + registry.npmjs.org/prop-types/15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz} + name: prop-types + version: 15.8.1 + dependencies: + loose-envify: registry.npmjs.org/loose-envify/1.4.0 + object-assign: registry.npmjs.org/object-assign/4.1.1 + react-is: registry.npmjs.org/react-is/16.13.1 + + registry.npmjs.org/react-is/16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz} + name: react-is + version: 16.13.1 + + registry.npmjs.org/source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz} + name: source-map + version: 0.6.1 + engines: {node: '>=0.10.0'} + + registry.npmjs.org/tslib/2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz} + name: tslib + version: 2.4.0 + dev: false + + registry.npmjs.org/uglify-js/3.15.5: + resolution: {integrity: sha512-hNM5q5GbBRB5xB+PMqVRcgYe4c8jbyZ1pzZhS6jbq54/4F2gFK869ZheiE5A8/t+W5jtTNpWef/5Q9zk639FNQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.5.tgz} + name: uglify-js + version: 3.15.5 + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: true + optional: true diff --git a/tests/integration/rax-project.test.ts b/tests/integration/rax-project.test.ts new file mode 100644 index 000000000..bac98f21c --- /dev/null +++ b/tests/integration/rax-project.test.ts @@ -0,0 +1,41 @@ +import { expect, test, describe, afterAll } from 'vitest'; +import { buildFixture, setupBrowser } from '../utils/build'; +import { startFixture, setupStartBrowser } from '../utils/start'; +import { Page } from '../utils/browser'; + +const example = 'rax-project'; + +describe(`build ${example}`, () => { + let page: Page = null; + let browser = null; + + test('open /', async () => { + await buildFixture(example); + const res = await setupBrowser({ example }); + + page = res.page; + browser = res.browser; + expect(await page.$$text('div')).toStrictEqual(['']); + }, 120000); + + afterAll(async () => { + await browser.close(); + }); +}); + +describe(`start ${example}`, () => { + let page: Page = null; + let browser = null; + + test('setup devServer', async () => { + const { devServer, port } = await startFixture(example); + const res = await setupStartBrowser({ server: devServer, port }); + page = res.page; + browser = res.browser; + expect((await page.$$text('span'))[0]).toStrictEqual('Welcome to Your Rax App'); + }, 120000); + + afterAll(async () => { + await browser.close(); + }); +}); diff --git a/tests/utils/build.ts b/tests/utils/build.ts index 6c8b4ff0c..9ca748ce5 100644 --- a/tests/utils/build.ts +++ b/tests/utils/build.ts @@ -12,6 +12,7 @@ interface SetupBrowser { example: string; outputDir?: string; defaultHtml?: string; + disableJS?: boolean; }): Promise<ReturnValue>; } @@ -29,12 +30,12 @@ export const buildFixture = async function(example: string) { } export const setupBrowser: SetupBrowser = async (options) => { - const { example, outputDir = 'build', defaultHtml = 'index.html' } = options; + const { example, outputDir = 'build', defaultHtml = 'index.html', disableJS = true } = options; const rootDir = path.join(__dirname, `../../examples/${example}`); const port = await getPort(); const browser = new Browser({ cwd: path.join(rootDir, outputDir), port }); - await browser.start(); - const disableJS = true; + await browser.start('disableJS', disableJS); + console.log() // when preview html generate by build, the path will not match the router info, so hydrate will not found the route component const page = await browser.page(`http://127.0.0.1:${port}/${defaultHtml}`, disableJS); return { From cfe7833cfd169535fe436c6b7b9ffe947f4edde2 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Thu, 14 Jul 2022 09:57:11 +0800 Subject: [PATCH 11/13] fix: deprecate multer package version (#353) --- packages/ice/package.json | 2 +- pnpm-lock.yaml | 53 +++++++++++---------------------------- 2 files changed, 16 insertions(+), 39 deletions(-) diff --git a/packages/ice/package.json b/packages/ice/package.json index f0ed6ede2..d9318bb41 100644 --- a/packages/ice/package.json +++ b/packages/ice/package.json @@ -55,7 +55,7 @@ "magic-string": "^0.26.1", "micromatch": "^4.0.5", "mrmime": "^1.0.0", - "multer": "^1.4.4", + "multer": "^1.4.5-lts.1", "open": "^8.4.0", "path-to-regexp": "^6.2.0", "prettier": "^2.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a3cca334d..c5615bf5e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -383,7 +383,7 @@ importers: magic-string: ^0.26.1 micromatch: ^4.0.5 mrmime: ^1.0.0 - multer: ^1.4.4 + multer: ^1.4.5-lts.1 open: ^8.4.0 path-to-regexp: ^6.2.0 prettier: ^2.5.1 @@ -425,7 +425,7 @@ importers: magic-string: 0.26.1 micromatch: 4.0.5 mrmime: 1.0.0 - multer: 1.4.4 + multer: 1.4.5-lts.1 open: 8.4.0 path-to-regexp: 6.2.1 prettier: 2.6.2 @@ -6361,7 +6361,7 @@ packages: picomatch: 2.3.1 /append-field/1.0.0: - resolution: {integrity: sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=} + resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} dev: false /aproba/1.2.0: @@ -6881,12 +6881,11 @@ packages: semver: 7.3.7 dev: true - /busboy/0.2.14: - resolution: {integrity: sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=} - engines: {node: '>=0.8.0'} + /busboy/1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} dependencies: - dicer: 0.2.5 - readable-stream: 1.1.14 + streamsearch: 1.1.0 dev: false /bytes/3.0.0: @@ -8327,14 +8326,6 @@ packages: resolution: {integrity: sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==} dev: true - /dicer/0.2.5: - resolution: {integrity: sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=} - engines: {node: '>=0.8.0'} - dependencies: - readable-stream: 1.1.14 - streamsearch: 0.1.2 - dev: false - /diff/4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -11867,16 +11858,15 @@ packages: /ms/2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - /multer/1.4.4: - resolution: {integrity: sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==} - engines: {node: '>= 0.10.0'} + /multer/1.4.5-lts.1: + resolution: {integrity: sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==} + engines: {node: '>= 6.0.0'} dependencies: append-field: 1.0.0 - busboy: 0.2.14 + busboy: 1.6.0 concat-stream: 1.6.2 mkdirp: 0.5.6 object-assign: 4.1.1 - on-finished: 2.4.1 type-is: 1.6.18 xtend: 4.0.2 dev: false @@ -14483,15 +14473,6 @@ packages: type-fest: 0.6.0 dev: true - /readable-stream/1.1.14: - resolution: {integrity: sha1-fPTFTvZI44EwhMY23SB54WbAgdk=} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 0.0.1 - string_decoder: 0.10.31 - dev: false - /readable-stream/2.3.7: resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} dependencies: @@ -15436,9 +15417,9 @@ packages: /std-env/3.1.1: resolution: {integrity: sha512-/c645XdExBypL01TpFKiG/3RAa/Qmu+zRi0MwAmrdEkwHNuN0ebo8ccAXBBDa5Z0QOJgBskUIbuCK91x0sCVEw==} - /streamsearch/0.1.2: - resolution: {integrity: sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=} - engines: {node: '>=0.8.0'} + /streamsearch/1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} dev: false /string-hash/1.1.3: @@ -15510,10 +15491,6 @@ packages: es-abstract: 1.20.1 dev: false - /string_decoder/0.10.31: - resolution: {integrity: sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=} - dev: false - /string_decoder/1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: @@ -16305,7 +16282,7 @@ packages: is-typedarray: 1.0.0 /typedarray/0.0.6: - resolution: {integrity: sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=} + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: false /typescript/4.6.4: From 4d186e68dc816b568374a6c0cf021bfd989ae930 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Thu, 14 Jul 2022 11:14:05 +0800 Subject: [PATCH 12/13] chore: set app.strict default value to false (#319) --- packages/runtime/src/appConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime/src/appConfig.ts b/packages/runtime/src/appConfig.ts index 9764fd757..0c87f8a0b 100644 --- a/packages/runtime/src/appConfig.ts +++ b/packages/runtime/src/appConfig.ts @@ -2,7 +2,7 @@ import type { AppConfig, AppExport } from './types.js'; const defaultAppConfig: AppConfig = { app: { - strict: true, + strict: false, rootId: 'ice-container', }, router: { From fa56813982d81e7a82ef82018c76678b6ffdf70c Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Thu, 14 Jul 2022 11:31:40 +0800 Subject: [PATCH 13/13] chore: remove prettier dependency (#315) * chore: remove prettier * feat: format routes.ts file * chore: rename function * chore: update the function param name * chore: remove unused param * fix: test --- packages/ice/package.json | 1 - packages/ice/src/routes.ts | 68 +++++++++++--------- packages/ice/src/service/runtimeGenerator.ts | 32 +++------ packages/ice/templates/data-loader.ts.ejs | 2 +- packages/ice/templates/entry.server.ts.ejs | 2 +- packages/ice/templates/index.ts.ejs | 13 ++-- packages/ice/templates/routes-config.ts.ejs | 2 +- packages/ice/templates/runtimeModules.ts.ejs | 18 +++--- packages/ice/templates/types.ts.ejs | 10 ++- packages/ice/tests/generator.test.ts | 2 +- pnpm-lock.yaml | 3 +- 11 files changed, 73 insertions(+), 80 deletions(-) diff --git a/packages/ice/package.json b/packages/ice/package.json index d9318bb41..f45d30486 100644 --- a/packages/ice/package.json +++ b/packages/ice/package.json @@ -58,7 +58,6 @@ "multer": "^1.4.5-lts.1", "open": "^8.4.0", "path-to-regexp": "^6.2.0", - "prettier": "^2.5.1", "react-router": "^6.3.0", "resolve": "^1.22.0", "resolve.exports": "^1.1.0", diff --git a/packages/ice/src/routes.ts b/packages/ice/src/routes.ts index 8e3e3e94c..eef29ab50 100644 --- a/packages/ice/src/routes.ts +++ b/packages/ice/src/routes.ts @@ -28,7 +28,7 @@ export async function generateRoutesInfo(rootDir: string, routesConfig: UserConf } const routes = formatNestedRouteManifest(routeManifest); - const str = generateNestRoutesStr(routes); + const routesStr = generateRoutesStr(routes); let routesCount = 0; Object.keys(routeManifest).forEach((key) => { const routeItem = routeManifest[key]; @@ -40,55 +40,63 @@ export async function generateRoutesInfo(rootDir: string, routesConfig: UserConf return { routesCount, routeManifest, - routesStr: `[${str}]`, + routesStr, routes, loaders: generateRouteConfig(routes, 'getData', (str, imports) => { return `${str} - const loaders = { - ${ - imports.map(([routeId, importKey]) => { - return `'${routeId}': ${importKey},`; - }).join('\n') - } - };`; +const loaders = { + ${imports.map(([routeId, importKey]) => `'${routeId}': ${importKey},`).join('\n ')} +};`; }), routesConfig: generateRouteConfig(routes, 'getConfig', (str, imports) => { return `${str} - export default { - ${ - imports.map(([, importKey, routePath]) => { - return `'${routePath}': ${importKey},`; - }).join('\n') - } - };`; +export default { + ${imports.map(([, importKey, routePath]) => `'${routePath}': ${importKey},`).join('\n ')} +};`; }), }; } -function generateNestRoutesStr(nestRouteManifest: NestedRouteManifest[]) { +function generateRoutesStr(nestRouteManifest: NestedRouteManifest[]) { + return `[ + ${recurseRoutesStr(nestRouteManifest)} +]`; +} + +function recurseRoutesStr(nestRouteManifest: NestedRouteManifest[], depth = 0) { return nestRouteManifest.reduce((prev, route) => { const { children, path: routePath, index, componentName, file, id, layout, exports } = route; const componentPath = id.startsWith('__') ? file : `@/pages/${file}`.replace(new RegExp(`${path.extname(file)}$`), ''); - let str = `{ - path: '${routePath || ''}', - load: () => import(/* webpackChunkName: "${componentName}" */ '${componentPath}'), - componentName: '${componentName}', - index: ${index}, - id: '${id}', - exact: true, - exports: ${JSON.stringify(exports)}, - ${layout ? 'layout: true,' : ''} - `; + const routeProperties: string[] = [ + `path: '${routePath || ''}',`, + `load: () => import(/* webpackChunkName: "${componentName}" */ '${componentPath}'),`, + `componentName: '${componentName}',`, + `index: ${index},`, + `id: '${id}',`, + 'exact: true,', + `exports: ${JSON.stringify(exports)},`, + ]; + if (layout) { + routeProperties.push('layout: true,'); + } if (children) { - str += `children: [${generateNestRoutesStr(children)}],`; + routeProperties.push(`children: [${recurseRoutesStr(children, depth + 1)}]`); } - str += '},'; - prev += str; + + prev += formatRoutesStr(depth, routeProperties); return prev; }, ''); } +function formatRoutesStr(deep: number, strs: string[]) { + const identSpaces = ' '.repeat(2 * (deep + 1)); + const twoSpaces = ' '.repeat(2); + return `{ +${identSpaces + twoSpaces}${strs.join(`\n${`${identSpaces + twoSpaces}`}`)} +${identSpaces}},`; +} + function createDefaultNotFoundRoute(routeManifest: RouteManifest): ConfigRoute { return { path: '*', diff --git a/packages/ice/src/service/runtimeGenerator.ts b/packages/ice/src/service/runtimeGenerator.ts index e58dca1d9..ccfad710b 100644 --- a/packages/ice/src/service/runtimeGenerator.ts +++ b/packages/ice/src/service/runtimeGenerator.ts @@ -3,7 +3,6 @@ import fse from 'fs-extra'; import consola from 'consola'; import fg from 'fast-glob'; import ejs from 'ejs'; -import prettier from 'prettier'; import lodash from '@ice/bundles/compiled/lodash/index.js'; import type { AddExport, @@ -55,7 +54,14 @@ export function generateExports(exportList: ExportData[]) { }); return { importStr: importStatements.join('\n'), - exportStr: exportStatements.join('\n'), + /** + * Add two whitespace character in order to get the formatted code. For example: + * export { + withAuth, + useAuth, + }; + */ + exportStr: exportStatements.join('\n '), }; } @@ -101,8 +107,6 @@ export default class Generator { private renderDataRegistration: RenderDataRegistration[]; - private showPrettierError: boolean; - private contentTypes: string[]; public constructor(options: Options) { @@ -112,7 +116,6 @@ export default class Generator { this.renderData = defaultRenderData; this.contentRegistration = {}; this.rerender = false; - this.showPrettierError = true; this.renderTemplates = []; this.renderDataRegistration = []; this.contentTypes = ['framework', 'frameworkTypes', 'configTypes']; @@ -252,7 +255,7 @@ export default class Generator { const renderExt = '.ejs'; const realTargetPath = path.isAbsolute(targetPath) ? targetPath : path.join(this.rootDir, targetPath); // example: templatePath = 'routes.ts.ejs' - const { name, ext } = path.parse(templatePath); + const { ext } = path.parse(templatePath); if (ext === renderExt) { const templateContent = fse.readFileSync(templatePath, 'utf-8'); let renderData = { ...this.renderData }; @@ -264,22 +267,7 @@ export default class Generator { ...extraData, }; } - let content = ejs.render(templateContent, renderData); - // example: name = 'routes.ts' - const realExtname = path.extname(name); - if (realExtname === '.ts' || realExtname === '.tsx') { - try { - content = prettier.format(content, { - parser: 'typescript', - singleQuote: true, - }); - } catch (error) { - if (this.showPrettierError) { - consola.warn(`Prettier format error: ${error.message}`); - this.showPrettierError = false; - } - } - } + const content = ejs.render(templateContent, renderData); fse.writeFileSync(realTargetPath.replace(renderExt, ''), content, 'utf-8'); } else { fse.ensureDirSync(path.dirname(realTargetPath)); diff --git a/packages/ice/templates/data-loader.ts.ejs b/packages/ice/templates/data-loader.ts.ejs index 6be171857..6ca96eb1e 100644 --- a/packages/ice/templates/data-loader.ts.ejs +++ b/packages/ice/templates/data-loader.ts.ejs @@ -1,4 +1,4 @@ import { dataLoader } from '@ice/runtime'; <%- loaders %> -dataLoader.init(loaders); \ No newline at end of file +dataLoader.init(loaders); diff --git a/packages/ice/templates/entry.server.ts.ejs b/packages/ice/templates/entry.server.ts.ejs index 5a0a9cfd3..b754bf663 100644 --- a/packages/ice/templates/entry.server.ts.ejs +++ b/packages/ice/templates/entry.server.ts.ejs @@ -59,4 +59,4 @@ export async function renderToResponse(requestContext, options: RenderOptions = documentOnly, renderMode, }); -} \ No newline at end of file +} diff --git a/packages/ice/templates/index.ts.ejs b/packages/ice/templates/index.ts.ejs index 3f42fbe90..bc0c2f37a 100644 --- a/packages/ice/templates/index.ts.ejs +++ b/packages/ice/templates/index.ts.ejs @@ -10,9 +10,10 @@ import { useSearchParamsSingle, useLocationSingle, } from '@ice/runtime'; -<% if (globalStyle) {%> - import '<%= globalStyle %>' -<% } %> + +<% if (globalStyle) {-%> +import '<%= globalStyle %>' +<% } -%> let Link: typeof OriginLink; let Outlet: typeof OriginOutlet; @@ -55,9 +56,9 @@ export { <%- framework.imports %> export { - <% if (framework.exports) { %> +<% if (framework.exports) { -%> <%- framework.exports %> - <% } %> +<% } -%> }; -export * from './types'; \ No newline at end of file +export * from './types'; diff --git a/packages/ice/templates/routes-config.ts.ejs b/packages/ice/templates/routes-config.ts.ejs index d2528665e..457628b5b 100644 --- a/packages/ice/templates/routes-config.ts.ejs +++ b/packages/ice/templates/routes-config.ts.ejs @@ -1 +1 @@ -<%- routesConfig %> \ No newline at end of file +<%- routesConfig %> diff --git a/packages/ice/templates/runtimeModules.ts.ejs b/packages/ice/templates/runtimeModules.ts.ejs index 1eac5a1d3..4251b0996 100644 --- a/packages/ice/templates/runtimeModules.ts.ejs +++ b/packages/ice/templates/runtimeModules.ts.ejs @@ -1,15 +1,15 @@ -<% const moduleNames = []; %> -<% if (runtimeModules.length) {%> - <% runtimeModules.filter((moduleInfo) => !moduleInfo.staticModule).forEach((runtimeModule, index) => { %> +<% const moduleNames = []; -%> +<% if (runtimeModules.length) {-%> + <% runtimeModules.filter((moduleInfo) => !moduleInfo.staticModule).forEach((runtimeModule, index) => { -%> <% moduleNames.push('module' + index) %> - import module<%= index %> from '<%= runtimeModule.path %>'; - <% }) %> -<% } %> +import module<%= index %> from '<%= runtimeModule.path %>'; + <% }) -%> +<% } -%> const modules = [ -<% moduleNames.forEach((moduleName, index) => { %> +<% moduleNames.forEach((moduleName, index) => { -%> <%= moduleName %>, -<% }) %> +<% }) -%> ]; -export default modules; \ No newline at end of file +export default modules; diff --git a/packages/ice/templates/types.ts.ejs b/packages/ice/templates/types.ts.ejs index 9d0eaaafb..ad18deb7f 100644 --- a/packages/ice/templates/types.ts.ejs +++ b/packages/ice/templates/types.ts.ejs @@ -1,10 +1,8 @@ import type { AppConfig as DefaultAppConfig } from '@ice/runtime'; -export type { GetAppConfig, GetAppData } from '@ice/runtime'; +<%- configTypes.imports -%> -<%- configTypes.imports %> - -<% if (configTypes.imports) {%> +<% if (configTypes.imports) {-%> interface ExtendsAppConfig extends DefaultAppConfig { <% if (configTypes.imports) { %> <%- configTypes.exports %> @@ -12,6 +10,6 @@ interface ExtendsAppConfig extends DefaultAppConfig { }; export type AppConfig = ExtendsAppConfig; -<% } else { %> +<% } else { -%> export type AppConfig = DefaultAppConfig; -<% } %> +<% } -%> diff --git a/packages/ice/tests/generator.test.ts b/packages/ice/tests/generator.test.ts index 5918ab9bd..5535cc0de 100644 --- a/packages/ice/tests/generator.test.ts +++ b/packages/ice/tests/generator.test.ts @@ -26,7 +26,7 @@ describe('generateExports', () => { specifier: ['Switch', 'Route'], }]); expect(importStr).toBe('import { Switch, Route } from \'react-router\';'); - expect(exportStr).toBe(['Switch,', 'Route,'].join('\n')); + expect(exportStr).toBe(['Switch,', 'Route,'].join('\n ')); }); it('aliased exports', () => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5615bf5e..60e17ef96 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -386,7 +386,6 @@ importers: multer: ^1.4.5-lts.1 open: ^8.4.0 path-to-regexp: ^6.2.0 - prettier: ^2.5.1 react: ^18.0.0 react-router: ^6.3.0 resolve: ^1.22.0 @@ -428,7 +427,6 @@ importers: multer: 1.4.5-lts.1 open: 8.4.0 path-to-regexp: 6.2.1 - prettier: 2.6.2 react-router: 6.3.0_react@18.0.0 resolve: 1.22.0 resolve.exports: 1.1.0 @@ -13741,6 +13739,7 @@ packages: resolution: {integrity: sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==} engines: {node: '>=10.13.0'} hasBin: true + dev: true /pretty-error/4.0.0: resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==}