From f58e0c16d55062ff3e8cf4c044a6430d3fdfba29 Mon Sep 17 00:00:00 2001 From: spicylemonhaha <81058033+spicylemonhaha@users.noreply.github.com> Date: Fri, 7 Jul 2023 18:02:56 +0800 Subject: [PATCH 01/11] feat: enhance dropLogLevel build config (#6376) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 增强droplog功能 * fix: 修改warn说明 * fix: 补充md文件 --------- Co-authored-by: ClarkXia --- packages/ice/src/config.ts | 72 ++++++++++++++++++---------- packages/ice/src/types/userConfig.ts | 12 +++-- website/docs/guide/basic/config.md | 24 ++++++++-- 3 files changed, 76 insertions(+), 32 deletions(-) diff --git a/packages/ice/src/config.ts b/packages/ice/src/config.ts index 7eb73cb9c8..def093188a 100644 --- a/packages/ice/src/config.ts +++ b/packages/ice/src/config.ts @@ -185,7 +185,7 @@ const userConfig = [ }, { name: 'dropLogLevel', - validation: 'string', + validation: 'boolean|array|string', setConfig: (config: Config, dropLogLevel: UserConfig['dropLogLevel']) => { const levels = { trace: 0, @@ -195,17 +195,38 @@ const userConfig = [ warn: 3, error: 4, }; - const level = levels[dropLogLevel]; - if (typeof level === 'number') { + if (typeof dropLogLevel === 'string') { + const level = levels[dropLogLevel]; + if (typeof level === 'number') { + return mergeDefaultValue(config, 'minimizerOptions', { + compress: { + pure_funcs: Object.keys(levels) + .filter((methodName) => levels[methodName] <= level) + .map((methodName) => `console.${methodName}`), + }, + }); + } else { + logger.warn( + `If you use a string as the attribute value of dropLogLevel you should enter one of the following strings [${Object.keys( + levels, + ).join(',')}]`, + ); + } + } else if (dropLogLevel === true) { return mergeDefaultValue(config, 'minimizerOptions', { compress: { - pure_funcs: Object.keys(levels) - .filter((methodName) => levels[methodName] <= level) - .map(methodName => `console.${methodName}`), + drop_console: true, }, }); - } else { - logger.warn(`dropLogLevel only support [${Object.keys(levels).join(',')}]`); + } else if (Array.isArray(dropLogLevel)) { + const pureFuncs = dropLogLevel.map((method) => `console.${method}`); + return mergeDefaultValue(config, 'minimizerOptions', { + compress: { + pure_funcs: pureFuncs, + }, + }); + } else if (dropLogLevel !== false) { + logger.warn('dropLogLevel support boolean, array and string'); } }, }, @@ -218,16 +239,21 @@ const userConfig = [ if (customValue === true) { compileRegex = /node_modules\/*/; } else if (customValue && customValue.length > 0) { - compileRegex = new RegExp(customValue.map((dep: string | RegExp) => { - if (dep instanceof RegExp) { - return dep.source; - } else if (typeof dep === 'string') { - // add default prefix of node_modules - const matchStr = `node_modules/?.+${dep}/`; - return matchStr; - } - return false; - }).filter(Boolean).join('|')); + compileRegex = new RegExp( + customValue + .map((dep: string | RegExp) => { + if (dep instanceof RegExp) { + return dep.source; + } else if (typeof dep === 'string') { + // add default prefix of node_modules + const matchStr = `node_modules/?.+${dep}/`; + return matchStr; + } + return false; + }) + .filter(Boolean) + .join('|'), + ); } if (compileRegex) { config.compileIncludes = [compileRegex]; @@ -363,7 +389,9 @@ const userConfig = [ setConfig: (config: Config, codeSplitting: UserConfig['codeSplitting'], context: UserConfigContext) => { const { originalUserConfig } = context; if ('splitChunks' in originalUserConfig) { - logger.warn('splitChunks is deprecated, please use codeSplitting instead.https://ice.work/docs/guide/basic/config#codesplitting'); + logger.warn( + 'splitChunks is deprecated, please use codeSplitting instead.https://ice.work/docs/guide/basic/config#codesplitting', + ); } else { // When codeSplitting is set to false / router, do not config splitChunks. if (codeSplitting === false || codeSplitting === 'page') { @@ -466,8 +494,4 @@ function defineConfig(config: UserConfig | (() => UserConfig)) { return config || defaultUserConfig; } -export { - defineConfig, - userConfig, - cliOption, -}; +export { defineConfig, userConfig, cliOption }; diff --git a/packages/ice/src/types/userConfig.ts b/packages/ice/src/types/userConfig.ts index 92fa86cf63..bba6aa2689 100644 --- a/packages/ice/src/types/userConfig.ts +++ b/packages/ice/src/types/userConfig.ts @@ -30,6 +30,8 @@ interface IgnorePattern { type DistType = 'javascript' | 'html'; +type DropType = 'trace' | 'debug' | 'log' | 'info' | 'warn' | 'error'; + interface Fetcher { packageName: string; method?: string; @@ -140,7 +142,7 @@ export interface UserConfig { * `console.*` will be dropped when build. * @see https://v3.ice.work/docs/guide/basic/config#droploglevel */ - dropLogLevel?: 'trace' | 'debug' | 'log' | 'info' | 'warn' | 'error'; + dropLogLevel?: DropType[] | DropType | boolean; /** * Minify build output, it only works in prod mode by default. * @see https://v3.ice.work/docs/guide/basic/config#minify @@ -248,9 +250,11 @@ export interface UserConfig { * generate additional assets for request data, default is true * @see https://v3.ice.work/docs/guide/basic/config#dataloader */ - dataLoader?: { - fetcher?: Fetcher; - } | Boolean; + dataLoader?: + | { + fetcher?: Fetcher; + } + | Boolean; /** * Enable cross-origin loading of chunks. * @see https://v3.ice.work/docs/guide/basic/config#crossoriginloading diff --git a/website/docs/guide/basic/config.md b/website/docs/guide/basic/config.md index abe80c3c9e..d7b305f01d 100644 --- a/website/docs/guide/basic/config.md +++ b/website/docs/guide/basic/config.md @@ -240,11 +240,27 @@ export default defineConfig(() => ({ ### dropLogLevel -- 类型:`'trace' | 'debug' | 'log' | 'warn' | 'error'` -- 默认值:`null`,不移除任何 console 代码 +- 类型:`boolean | DropType[] | DropType` +- 默认值:`false`,不移除任何 console 代码 -压缩代码时移除 console.* 相关代码,比如配置了 log 则会移除 console.trace -、console.debug、console.log 代码。 +压缩代码时移除 console.* 相关代码,配置为true时,移除所有console.*相关代码。当想移除部分console代码,例如想要移除console.log和console.error时,可以配置为 +```js +import { defineConfig } from '@ice/app'; + +export default defineConfig(() => ({ + dropLog: ['error', 'log'], +})); +``` +也可以根据console等级来进行移除 +```js +// console 等级为 trace < debug < log < info < warn < error +// 例如想要移除trace、debug、log时可以像下面这样配置 +import { defineConfig } from '@ice/app'; + +export default defineConfig(() => ({ + dropLog: 'log', +})); +``` ### compileDependencies From 6f3e16ce4dc1a4967aac2b498d5ff4cf4c56c694 Mon Sep 17 00:00:00 2001 From: Linbudu <48507806+linbudu599@users.noreply.github.com> Date: Tue, 11 Jul 2023 19:59:55 +0800 Subject: [PATCH 02/11] feat: support inline style filter (#6380) * feat: support inlineStyle filter * docs: enhance rax-compat desc * chore: update comments * chore: fix comment styles * chore: fix comment styles --- packages/plugin-rax-compat/src/index.ts | 32 +++++++++++++++++--- website/docs/guide/advanced/rax-compat.md | 37 +++++++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/packages/plugin-rax-compat/src/index.ts b/packages/plugin-rax-compat/src/index.ts index 488e694e51..283cb84c99 100644 --- a/packages/plugin-rax-compat/src/index.ts +++ b/packages/plugin-rax-compat/src/index.ts @@ -60,7 +60,7 @@ const ruleSetStylesheetForLess = { let warnOnce = false; export interface CompatRaxOptions { - inlineStyle?: boolean; + inlineStyle?: boolean | ((id: string) => boolean); cssModule?: boolean; } @@ -138,7 +138,14 @@ const plugin: Plugin = (options = {}) => ({ } config.configureWebpack ??= []; - config.configureWebpack.unshift((config) => styleSheetLoaderForClient(config, transformCssModule)); + + // When code enters here, options.inlineStyle is either `true` or filter function. + // If user provide `true`, use a filter which always return true, or, use the filter. + const inlineStyleFilter = options.inlineStyle === true ? () => true : options.inlineStyle; + + config.configureWebpack.unshift((config) => + styleSheetLoaderForClient(config, transformCssModule, inlineStyleFilter), + ); config.transforms = [ ...(config.transforms || []), getClassNameToStyleTransformer(userConfig.syntaxFeatures || {}), @@ -218,18 +225,33 @@ function getClassNameToStyleTransformer(syntaxFeatures) { * StyleSheet Loader for CSR. * Transform css files to inline style by webpack loader. */ -const styleSheetLoaderForClient = (config, transformCssModule) => { +const styleSheetLoaderForClient = (config, transformCssModule, inlineStyleFiler: (id: string) => boolean) => { const { rules } = config.module || {}; if (Array.isArray(rules)) { for (let i = 0, l = rules.length; i < l; i++) { - const rule: RuleSetRule | any = rules[i]; + const rule: RuleSetRule = rules[i]; // Find the css rule, that default to CSS Modules. if (rule.test && rule.test instanceof RegExp && rule.test.source.indexOf('.css') > -1) { - rule.test = transformCssModule ? /(\.module|global)\.css$/i : /(\.global)\.css$/i; + // Apply inlineStyle here as original rule got higher priority, + // the resource doesnot match the filter will be bypassed to stylesheet-loader. + rule.test = (id: string) => { + const inlineStyleFilterEnabled = inlineStyleFiler(id) === true; + + inlineStyleFilterEnabled && consola.warn(`InlineStyle enabled for current css file: ${id}`); + + const matched = + (transformCssModule ? /(\.module|global)\.css$/i : /(\.global)\.css$/i).test(id) && + // If filter returns true, bypass the resource to stylesheet-loader. + !inlineStyleFilterEnabled; + + return matched; + }; rules[i] = { test: /\.css$/i, oneOf: [ + // Handle project css and those module can only work under inlineStyle disabled. rule, + // Handle those module can only work under inlineStyle enabled. ruleSetStylesheet, ], }; diff --git a/website/docs/guide/advanced/rax-compat.md b/website/docs/guide/advanced/rax-compat.md index 6d041ce58b..4ddf2010a0 100644 --- a/website/docs/guide/advanced/rax-compat.md +++ b/website/docs/guide/advanced/rax-compat.md @@ -21,6 +21,8 @@ $ npm i @ice/plugin-rax-compat --save-dev export default defineConfig(() => ({ plugins: [ + compatRax({ inlineStyle: true }), // 是否开启内联样式,这里是开启 ++ // 也可以使用函数形式,根据文件名来判断是否开启内联样式 ++ compatRax({ inlineStyle: (id) => id.includes('some-module') }), ], })); ``` @@ -79,6 +81,41 @@ console.log(styles); // { foo: { color: 'red' } } 此外,当 `width` 等属性没有单位时,如 `width: 300`,在 `inlineStyle` 模式下会自动补齐 `rpx` 单位并最终转化成 `vw`,同理,写了 `rpx` 单位的值也一样会被转化成 `vw`。 +### 兼容 rax-swiper + +由于 [rax-swiper](https://rax.alibaba-inc.com/docs/components/swiper) 仅支持在非内联模式下使用,如果你启用了 `inlineStyle`,则需要在项目的全局 CSS 中新增对其样式的导入: + +```diff title="global.css" ++ @import url('swiper/swiper-bundle.min.css'); +``` + +或者你也可以使用函数形式的 lineStyle,将引用了 `rax-swiper` 的模块排除出内联样式的处理流程: + +```diff title="ice.config.mts" +import compatRax from '@ice/plugin-rax-compat'; + +export default defineConfig(() => ({ + plugins: [ ++ compatRax({ inlineStyle: (id) => !id.includes('feeds-module') }), + ], +})); +``` + + +### 兼容使用内联样式构建的模块 + +Rax 的 inlineStyle 模式是具有传染性的,因此,如果你的项目中存在使用内联样式构建的模块,在 rax-compat 模式下需要确保这些模块也使用内联样式处理,否则会出现样式丢失的问题。此时你可以使用函数形式的 inlineStyle: + +```diff title="ice.config.mts" +import compatRax from '@ice/plugin-rax-compat'; + +export default defineConfig(() => ({ + plugins: [ ++ compatRax({ inlineStyle: (id) => id.includes('inline-style-module') }), + ], +})); +``` + ### DOM 属性差异 在 React 中,原生标签的 `props` 是存在白名单的,而 rax.js 中没有。这导致使用非 dataset 的自定义属性在 React 中会被忽略(Dev 阶段有警告),从而无法从真实节点的 DOM 对象中通过 `getAttribute()` 方法获取。如果用了这些非标自定义属性,推荐使用 dataset(`data-*`) 来标识自定义属性。 From 27a72536948439230ec06c30b4093e010688357a Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Wed, 12 Jul 2023 14:30:56 +0800 Subject: [PATCH 03/11] fix: always external dependencies when get config (#6383) --- .changeset/flat-spies-attack.md | 5 +++++ packages/ice/src/service/config.ts | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 .changeset/flat-spies-attack.md diff --git a/.changeset/flat-spies-attack.md b/.changeset/flat-spies-attack.md new file mode 100644 index 0000000000..c21cbb1252 --- /dev/null +++ b/.changeset/flat-spies-attack.md @@ -0,0 +1,5 @@ +--- +'@ice/app': patch +--- + +fix: always external dependencies when get config diff --git a/packages/ice/src/service/config.ts b/packages/ice/src/service/config.ts index b1303641df..c7be2cbffb 100644 --- a/packages/ice/src/service/config.ts +++ b/packages/ice/src/service/config.ts @@ -53,6 +53,8 @@ class Config { sourcemap: false, logLevel: 'silent', // The main server compiler process will log it. }, { + // Always external dependencies when get config. + externalDependencies: true, swc: { keepExports: { value: keepExports, From 39c92e5b0a8a005c50aef8a26198fdda722943a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=93=E9=99=8C=E5=90=8C=E5=AD=A6?= Date: Wed, 12 Jul 2023 15:27:43 +0800 Subject: [PATCH 04/11] fix: format of dataLoaderConfig loader changed (#6384) * fix: format of dataLoaderConfig loader changed * chore: modify titleId * test: modify test --- .changeset/funny-dolphins-hope.md | 5 ++ packages/plugin-pha/src/manifestHelpers.ts | 22 ++++---- .../plugin-pha/tests/manifestHelper.test.ts | 52 ++++++++++--------- 3 files changed, 45 insertions(+), 34 deletions(-) create mode 100644 .changeset/funny-dolphins-hope.md diff --git a/.changeset/funny-dolphins-hope.md b/.changeset/funny-dolphins-hope.md new file mode 100644 index 0000000000..36ac4e8c6c --- /dev/null +++ b/.changeset/funny-dolphins-hope.md @@ -0,0 +1,5 @@ +--- +'@ice/plugin-pha': patch +--- + +fix: format of dataLoaderConfig loader changed. diff --git a/packages/plugin-pha/src/manifestHelpers.ts b/packages/plugin-pha/src/manifestHelpers.ts index d7c4136ae8..190a8210ea 100644 --- a/packages/plugin-pha/src/manifestHelpers.ts +++ b/packages/plugin-pha/src/manifestHelpers.ts @@ -362,17 +362,18 @@ export async function parseManifest(manifest: Manifest, options: ParseOptions): // Set static dataloader to data_prefetch of page. pageIds.forEach((pageId) => { - if (typeof page === 'string' && dataloaderConfig && dataloaderConfig[pageId]) { + if (typeof page === 'string' && dataloaderConfig && dataloaderConfig[pageId] && dataloaderConfig[pageId].loader) { const staticDataLoaders = []; - if (Array.isArray(dataloaderConfig[pageId])) { - dataloaderConfig[pageId].forEach(item => { + const { loader } = dataloaderConfig[pageId]; + if (Array.isArray(loader)) { + dataloaderConfig[pageId].loader.forEach(item => { if (typeof item === 'object') { staticDataLoaders.push(item); } }); - } else if (typeof dataloaderConfig[pageId] === 'object') { + } else if (typeof loader === 'object') { // Single prefetch loader config. - staticDataLoaders.push(dataloaderConfig[pageId]); + staticDataLoaders.push(loader); } pageManifest.dataPrefetch = [...(pageManifest.dataPrefetch || []), ...staticDataLoaders]; } @@ -386,17 +387,18 @@ export async function parseManifest(manifest: Manifest, options: ParseOptions): const title = frame.title || ''; const titleIds = getRouteIdByPage(routeManifest, title); titleIds.forEach((titleId) => { - if (dataloaderConfig && dataloaderConfig[titleId]) { + if (dataloaderConfig && dataloaderConfig[titleId] && dataloaderConfig[titleId].loader) { const staticDataLoaders = []; - if (Array.isArray(dataloaderConfig[title])) { - dataloaderConfig[title].forEach(item => { + const { loader } = dataloaderConfig[titleId]; + if (Array.isArray(loader)) { + loader.forEach(item => { if (typeof item === 'object') { staticDataLoaders.push(item); } }); - } else if (typeof dataloaderConfig[title] === 'object') { + } else if (typeof loader === 'object') { // Single prefetch loader config. - staticDataLoaders.push(dataloaderConfig[title]); + staticDataLoaders.push(loader); } frame.dataPrefetch = [...(frame.dataPrefetch || []), ...staticDataLoaders]; diff --git a/packages/plugin-pha/tests/manifestHelper.test.ts b/packages/plugin-pha/tests/manifestHelper.test.ts index 6aef92b651..f2ab3a3da9 100644 --- a/packages/plugin-pha/tests/manifestHelper.test.ts +++ b/packages/plugin-pha/tests/manifestHelper.test.ts @@ -722,18 +722,20 @@ describe('parse manifest', async () => { const manifest = await parseManifest(phaManifest, { ...options, dataloaderConfig: { - home: [ - () => { - return new Promise((resolve) => { - setTimeout(() => { - resolve({ - name: 'About', - }); - }, 1 * 100); - }); - }, - staticDataloader, - ], + home: { + loader: [ + () => { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ + name: 'About', + }); + }, 1 * 100); + }); + }, + staticDataloader, + ], + }, }, }); @@ -774,18 +776,20 @@ describe('parse manifest', async () => { const manifest = await parseManifest(phaManifest, { ...options, dataloaderConfig: { - home: [ - () => { - return new Promise((resolve) => { - setTimeout(() => { - resolve({ - name: 'About', - }); - }, 1 * 100); - }); - }, - staticDataloader, - ], + home: { + loader: [ + () => { + return new Promise((resolve) => { + setTimeout(() => { + resolve({ + name: 'About', + }); + }, 1 * 100); + }); + }, + staticDataloader, + ], + }, }, }); From cf8a78e37945c683d871cce647a94b277e7d302a Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Mon, 17 Jul 2023 10:44:15 +0800 Subject: [PATCH 05/11] feat: support code splitting strategy of page-vendors (#6386) * feat: support code splitting strategy of page-vendors * chore: fix type * fix: test case --- .changeset/rotten-hats-mate.md | 6 ++++++ packages/ice/src/createService.ts | 2 +- packages/ice/src/types/userConfig.ts | 2 +- packages/webpack-config/src/config/splitChunks.ts | 10 ++++++---- packages/webpack-config/src/types.ts | 2 +- website/docs/guide/basic/config.md | 3 ++- 6 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 .changeset/rotten-hats-mate.md diff --git a/.changeset/rotten-hats-mate.md b/.changeset/rotten-hats-mate.md new file mode 100644 index 0000000000..3762f5aff0 --- /dev/null +++ b/.changeset/rotten-hats-mate.md @@ -0,0 +1,6 @@ +--- +'@ice/webpack-config': patch +'@ice/app': patch +--- + +feat: support code splitting strategy of page-vendors diff --git a/packages/ice/src/createService.ts b/packages/ice/src/createService.ts index de69a8e14d..4341a5990e 100644 --- a/packages/ice/src/createService.ts +++ b/packages/ice/src/createService.ts @@ -250,7 +250,7 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt const iceRuntimePath = '@ice/runtime'; // Only when code splitting use the default strategy or set to `router`, the router will be lazy loaded. - const lazy = [true, 'chunks', 'page'].includes(userConfig.codeSplitting); + const lazy = [true, 'chunks', 'page', 'page-vendors'].includes(userConfig.codeSplitting); const { routeImports, routeDefinition } = getRoutesDefinition(routesInfo.routes, lazy); // add render data generator.setRenderData({ diff --git a/packages/ice/src/types/userConfig.ts b/packages/ice/src/types/userConfig.ts index bba6aa2689..dd0acca77a 100644 --- a/packages/ice/src/types/userConfig.ts +++ b/packages/ice/src/types/userConfig.ts @@ -245,7 +245,7 @@ export interface UserConfig { * Code splitting strategy, support page and vendors, default value is true (built-in strategy). * @see https://v3.ice.work/docs/guide/basic/config#codesplitting */ - codeSplitting?: 'page' | 'vendors' | boolean; + codeSplitting?: 'page' | 'vendors' | 'page-vendors' | boolean; /** * generate additional assets for request data, default is true * @see https://v3.ice.work/docs/guide/basic/config#dataloader diff --git a/packages/webpack-config/src/config/splitChunks.ts b/packages/webpack-config/src/config/splitChunks.ts index 6f8729d553..43e75939f5 100644 --- a/packages/webpack-config/src/config/splitChunks.ts +++ b/packages/webpack-config/src/config/splitChunks.ts @@ -35,14 +35,15 @@ const isModuleCSS = (module: { type: string }): boolean => { type SplitChunksConfig = webpack.Configuration['optimization']['splitChunks']; // Split all node_modules into a single vendors chunk. -export const getVendorStrategy = (): SplitChunksConfig => { +export const getVendorStrategy = (options: SplitChunksConfig = {}): SplitChunksConfig => { return { + ...options, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: 10, name: 'vendors', - chunks: 'async', + reuseExistingChunk: true, }, }, }; @@ -126,8 +127,9 @@ export const getChunksStrategy = (rootDir: string): SplitChunksConfig => { const getSplitChunksConfig = (rootDir: string, strategy: string | boolean): SplitChunksConfig => { if (strategy === false) { return { minChunks: Infinity, cacheGroups: { default: false } }; - } else if (strategy === 'vendors') { - return getVendorStrategy(); + } else if (typeof strategy === 'string' && ['page-vendors', 'vendors'].includes(strategy)) { + const splitChunksOptions: SplitChunksConfig = strategy === 'page-vendors' ? { chunks: 'all' } : {}; + return getVendorStrategy(splitChunksOptions); } // Default to chunks strategy. return getChunksStrategy(rootDir); diff --git a/packages/webpack-config/src/types.ts b/packages/webpack-config/src/types.ts index 3b04dfa776..148abb72ce 100644 --- a/packages/webpack-config/src/types.ts +++ b/packages/webpack-config/src/types.ts @@ -149,7 +149,7 @@ export interface Config { [key: string]: string; }; - splitChunks?: boolean | 'vendors' | 'chunks' | webpack.Configuration['optimization']['splitChunks']; + splitChunks?: boolean | 'vendors' | 'chunks' | 'page-vendors' | webpack.Configuration['optimization']['splitChunks']; optimization?: Optimization; diff --git a/website/docs/guide/basic/config.md b/website/docs/guide/basic/config.md index d7b305f01d..81f599fe7b 100644 --- a/website/docs/guide/basic/config.md +++ b/website/docs/guide/basic/config.md @@ -600,13 +600,14 @@ export default defineConfig({ ### codeSplitting -- 类型:`boolean | 'vendors' | 'page' | 'chunks'` +- 类型:`boolean | 'vendors' | 'page' | 'chunks' | 'page-vendors'` - 默认值:`true` 框架内置了三种分包策略分别为 `chunks`(默认策略,无需额外设置),`page` 和 `vendors`。 - `vendors` 策略:将异步 chunks 里的三方依赖统一打入到 vendor.js 中,避免重复,在依赖不变的情况下有效利用缓存。缺陷是如果项目过大会导致单文件尺寸过大。 - `page` 策略:所有路由级别组件按需加载,如果需保留原 `splitChunks: false` 的效果,配置该策略 。 +- `page-vendors` 策略:在 `page` 策略的基础上,将异步 chunks 里的三方依赖统一打入到 vendor.js 中,以达到有效利用缓存的结果。 - `chunks` 策略:在路由级别组件按需加载的基础上,根据模块体积大小自动拆分 chunks,为框架默认推荐策略。 如果存在特殊场景期望关闭分包能力,可以设置成 `false`。 From 018238f9041343b8b6040593b0dbcb299bc1acf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=93=E9=99=8C=E5=90=8C=E5=AD=A6?= Date: Mon, 17 Jul 2023 14:07:27 +0800 Subject: [PATCH 06/11] feat: support canvans 2d for cache (#6367) * feat: support canvans 2d for cache * fix: image src hydrate * chore: update lock * fix: img not match when ssr * fix: canvas dispalay * chore: remove runtime * chore: add event for taobao * chore: add window.WindVane * chore: add declare * chore: add changeset * feat: add cacheCanvasToStorage to ref * chore: modify function * feat: add @ice/cache-canvas * feat: replace mounted * chore: add dependence to useCallback * chore: add try to Storage * chore: import CacheCanvas from ice in example * chore: add changeset * chore: add conment * feat: add rendered * feat: add getSnapshot * feat: modify * chore: add import meta * chore: add CacheCanvasProps --- .changeset/dry-rockets-exist.md | 5 + .changeset/tough-lobsters-attend.md | 5 + examples/cavans-project/.browserslistrc | 2 + examples/cavans-project/ice.config.mts | 10 ++ examples/cavans-project/package.json | 25 +++ examples/cavans-project/src/app.tsx | 3 + .../cavans-project/src/components/bar.tsx | 7 + examples/cavans-project/src/document.tsx | 22 +++ examples/cavans-project/src/pages/home.tsx | 65 +++++++ examples/cavans-project/src/pages/ice.png | Bin 0 -> 36061 bytes .../cavans-project/src/pages/index.module.css | 3 + examples/cavans-project/src/types.ts | 3 + examples/cavans-project/src/typings.d.ts | 1 + examples/cavans-project/tsconfig.json | 32 ++++ packages/cache-canvas/README.md | 46 +++++ packages/cache-canvas/package.json | 29 ++++ packages/cache-canvas/src/index.tsx | 161 ++++++++++++++++++ packages/cache-canvas/src/storage.tsx | 26 +++ packages/cache-canvas/src/type.ts | 3 + packages/cache-canvas/tsconfig.json | 12 ++ packages/plugin-cavans/README.md | 16 ++ packages/plugin-cavans/package.json | 49 ++++++ packages/plugin-cavans/src/index.ts | 15 ++ packages/plugin-cavans/tsconfig.json | 10 ++ pnpm-lock.yaml | 57 ++++++- 25 files changed, 600 insertions(+), 7 deletions(-) create mode 100644 .changeset/dry-rockets-exist.md create mode 100644 .changeset/tough-lobsters-attend.md create mode 100644 examples/cavans-project/.browserslistrc create mode 100644 examples/cavans-project/ice.config.mts create mode 100644 examples/cavans-project/package.json create mode 100644 examples/cavans-project/src/app.tsx create mode 100644 examples/cavans-project/src/components/bar.tsx create mode 100644 examples/cavans-project/src/document.tsx create mode 100644 examples/cavans-project/src/pages/home.tsx create mode 100644 examples/cavans-project/src/pages/ice.png create mode 100644 examples/cavans-project/src/pages/index.module.css create mode 100644 examples/cavans-project/src/types.ts create mode 100644 examples/cavans-project/src/typings.d.ts create mode 100644 examples/cavans-project/tsconfig.json create mode 100644 packages/cache-canvas/README.md create mode 100644 packages/cache-canvas/package.json create mode 100644 packages/cache-canvas/src/index.tsx create mode 100644 packages/cache-canvas/src/storage.tsx create mode 100644 packages/cache-canvas/src/type.ts create mode 100644 packages/cache-canvas/tsconfig.json create mode 100644 packages/plugin-cavans/README.md create mode 100644 packages/plugin-cavans/package.json create mode 100644 packages/plugin-cavans/src/index.ts create mode 100644 packages/plugin-cavans/tsconfig.json diff --git a/.changeset/dry-rockets-exist.md b/.changeset/dry-rockets-exist.md new file mode 100644 index 0000000000..845b7d1d95 --- /dev/null +++ b/.changeset/dry-rockets-exist.md @@ -0,0 +1,5 @@ +--- +'@ice/cache-canvas': patch +--- + +feat: support cache of 2d cavans diff --git a/.changeset/tough-lobsters-attend.md b/.changeset/tough-lobsters-attend.md new file mode 100644 index 0000000000..48da8c3e7d --- /dev/null +++ b/.changeset/tough-lobsters-attend.md @@ -0,0 +1,5 @@ +--- +'@ice/plugin-canvas': patch +--- + +feat: support cache of 2d cavans diff --git a/examples/cavans-project/.browserslistrc b/examples/cavans-project/.browserslistrc new file mode 100644 index 0000000000..df80bf2c0f --- /dev/null +++ b/examples/cavans-project/.browserslistrc @@ -0,0 +1,2 @@ +defaults +ios_saf 9 diff --git a/examples/cavans-project/ice.config.mts b/examples/cavans-project/ice.config.mts new file mode 100644 index 0000000000..ec70568bd5 --- /dev/null +++ b/examples/cavans-project/ice.config.mts @@ -0,0 +1,10 @@ +import { defineConfig } from '@ice/app'; +import canvasPlugin from '@ice/plugin-canvas'; + +export default defineConfig(() => ({ + plugins: [ + canvasPlugin(), + ], + ssr: true, + ssg: false, +})); diff --git a/examples/cavans-project/package.json b/examples/cavans-project/package.json new file mode 100644 index 0000000000..bce995ca97 --- /dev/null +++ b/examples/cavans-project/package.json @@ -0,0 +1,25 @@ +{ + "name": "@examples/canvas-project", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "ice start", + "build": "ice build" + }, + "description": "", + "author": "", + "license": "MIT", + "dependencies": { + "@ice/app": "workspace:*", + "@ice/plugin-canvas": "workspace:*", + "@ice/runtime": "workspace:*", + "react": "^18.0.0", + "react-dom": "^18.0.0", + "@ice/cache-canvas": "workspace:*" + }, + "devDependencies": { + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "webpack": "^5.86.0" + } +} diff --git a/examples/cavans-project/src/app.tsx b/examples/cavans-project/src/app.tsx new file mode 100644 index 0000000000..b84dfd61c1 --- /dev/null +++ b/examples/cavans-project/src/app.tsx @@ -0,0 +1,3 @@ +import { defineAppConfig } from 'ice'; + +export default defineAppConfig(() => ({})); diff --git a/examples/cavans-project/src/components/bar.tsx b/examples/cavans-project/src/components/bar.tsx new file mode 100644 index 0000000000..7861bf5cb4 --- /dev/null +++ b/examples/cavans-project/src/components/bar.tsx @@ -0,0 +1,7 @@ +export default function Bar() { + return ( +
+ bar +
+ ); +} diff --git a/examples/cavans-project/src/document.tsx b/examples/cavans-project/src/document.tsx new file mode 100644 index 0000000000..1e7b99c49d --- /dev/null +++ b/examples/cavans-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/cavans-project/src/pages/home.tsx b/examples/cavans-project/src/pages/home.tsx new file mode 100644 index 0000000000..b8d8acf7ee --- /dev/null +++ b/examples/cavans-project/src/pages/home.tsx @@ -0,0 +1,65 @@ +import { definePageConfig, CacheCanvas } from 'ice'; +import { useRef } from 'react'; +import styles from './index.module.css'; + +export type RefCacheCanvas = { + cacheCanvasToStorage: () => void; +}; + +const GAME_CANVAS_ID = 'canvas-id'; + +export default function Home() { + const childRef = useRef<RefCacheCanvas>(); + const initFunc = () => { + return new Promise((resolve) => { + const canvas: HTMLCanvasElement | null = document.getElementById(GAME_CANVAS_ID) as HTMLCanvasElement; + if (canvas && typeof canvas.getContext === 'function') { + let ctx: CanvasRenderingContext2D | null = canvas.getContext('2d'); + + ctx?.fillRect(25, 25, 100, 100); + ctx?.clearRect(45, 45, 60, 60); + ctx?.strokeRect(50, 50, 50, 50); + } + + setTimeout(() => { + console.log('canvas paint ready!'); + resolve(true); + }, 5000); + }); + }; + return ( + <> + <h2 className={styles.title}>Home Page</h2> + <CacheCanvas + ref={childRef} + id={GAME_CANVAS_ID} + init={initFunc} + fallback={() => <div>fallback</div>} + /> + <button + style={{ display: 'block' }} + onClick={() => { + console.log('active cache!'); + childRef.current?.cacheCanvasToStorage(); + }} + >cache canvas</button> + </> + ); +} + +export const pageConfig = definePageConfig(() => { + return { + title: 'Home', + meta: [ + { + name: 'theme-color', + content: '#000', + }, + { + name: 'title-color', + content: '#f00', + }, + ], + auth: ['admin'], + }; +}); diff --git a/examples/cavans-project/src/pages/ice.png b/examples/cavans-project/src/pages/ice.png new file mode 100644 index 0000000000000000000000000000000000000000..e5e98fac1e156e7fef7374d48be9749a7ec0ebe7 GIT binary patch literal 36061 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�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 C1#Ij9 literal 0 HcmV?d00001 diff --git a/examples/cavans-project/src/pages/index.module.css b/examples/cavans-project/src/pages/index.module.css new file mode 100644 index 0000000000..ef450095a5 --- /dev/null +++ b/examples/cavans-project/src/pages/index.module.css @@ -0,0 +1,3 @@ +.title { + color: red; +} \ No newline at end of file diff --git a/examples/cavans-project/src/types.ts b/examples/cavans-project/src/types.ts new file mode 100644 index 0000000000..9f8f9f11e9 --- /dev/null +++ b/examples/cavans-project/src/types.ts @@ -0,0 +1,3 @@ +export interface AppData { + title: string; +} \ No newline at end of file diff --git a/examples/cavans-project/src/typings.d.ts b/examples/cavans-project/src/typings.d.ts new file mode 100644 index 0000000000..1f6ba4ffa6 --- /dev/null +++ b/examples/cavans-project/src/typings.d.ts @@ -0,0 +1 @@ +/// <reference types="@ice/app/types" /> diff --git a/examples/cavans-project/tsconfig.json b/examples/cavans-project/tsconfig.json new file mode 100644 index 0000000000..26fd9ec799 --- /dev/null +++ b/examples/cavans-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": ["build", "public"] +} \ No newline at end of file diff --git a/packages/cache-canvas/README.md b/packages/cache-canvas/README.md new file mode 100644 index 0000000000..b70cb3b328 --- /dev/null +++ b/packages/cache-canvas/README.md @@ -0,0 +1,46 @@ +# @ice/cache-canvas + +React component for supporting canvas for cache. + +## Usage + +```bash +npm i @ice/cache-canvas -S +``` + +```jsx +import MainGame from './game'; // eva.js 的封装 + +const GAME_CANVAS = 'game-canvas'; + +export default (props) => { + useEffect(() => { + const gameEl = document.getElementById(GAME_CANVAS); + new MainGame(gameEl, getGameHeight()); + }, []); + + const init = () => { + return new Promise((resolve) => { + const canvas: HTMLCanvasElement | null = document.getElementById(GAME_CANVAS_ID) as HTMLCanvasElement; + if (canvas && typeof canvas.getContext === 'function') { + let ctx: CanvasRenderingContext2D | null = canvas.getContext('2d'); + + ctx?.fillRect(25, 25, 100, 100); + ctx?.clearRect(45, 45, 60, 60); + ctx?.strokeRect(50, 50, 50, 50); + } + + setTimeout(() => { + console.log('canvas paint ready!'); + resolve(true); + }, 5000); + }); + } + + return ( + <> + <CanvasCache id={GAME_CANVAS} useCache={false} init={init} /> + </> + ); +}; +``` diff --git a/packages/cache-canvas/package.json b/packages/cache-canvas/package.json new file mode 100644 index 0000000000..6626fdd12a --- /dev/null +++ b/packages/cache-canvas/package.json @@ -0,0 +1,29 @@ +{ + "name": "@ice/cache-canvas", + "version": "0.0.8", + "description": "", + "main": "./esm/index.js", + "types": "./esm/index.d.ts", + "scripts": { + "watch": "tsc -w", + "build": "tsc", + "prepublishOnly": "npm run build" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "dependencies": { + "universal-env": "^3.3.3" + }, + "peerDependencies": { + "react": "^18", + "react-dom": "^18" + }, + "publishConfig": { + "access": "public" + } +} \ No newline at end of file diff --git a/packages/cache-canvas/src/index.tsx b/packages/cache-canvas/src/index.tsx new file mode 100644 index 0000000000..69cd7b6067 --- /dev/null +++ b/packages/cache-canvas/src/index.tsx @@ -0,0 +1,161 @@ +import { useEffect, useState, useImperativeHandle, forwardRef, useCallback } from 'react'; +import type { + HTMLAttributes, + ReactElement, +} from 'react'; +import * as React from 'react'; +import { isNode } from 'universal-env'; +import { Storage } from './storage'; + +declare global { + interface ImportMeta { + // The build target for ice.js + // Usually `web` or `node` or `weex` + target: string; + // The renderer for ice.js + renderer: 'client' | 'server'; + // ice.js defined env variables + env: Record<string, string>; + } + + interface Window { + WindVane: { + call: Function; + }; + _windvane_backControl: Function | null; + } +} + +export type RefCacheCanvas = { + // Call the API to store the canvas in storage. + cacheCanvasToStorage: () => void; +}; + +export type CacheCanvasProps = { + id: string; + init: () => Promise<any>; + useCache?: Boolean; + getSnapshot?: () => String; + fallback?: ReactElement; + style?: HTMLAttributes; + className?: HTMLAttributes; +}; + +export const CacheCanvas = forwardRef((props: CacheCanvasProps, ref) => { + const { + id, + init, + useCache = true, + getSnapshot, + fallback, + style, + className, + ...rest + } = props; + + const [renderedCanvas, setRenderedCanvas] = useState(!useCache); + const [mounted, setMounted] = useState(false); + + const cacheKey = `cache-canvas-${id}`; + + const cacheCanvasFunc = useCallback(() => { + // Cache base64 string of canvas. + const canvas: HTMLCanvasElement | null = document.getElementById(id) as HTMLCanvasElement; + let strBase64; + if (typeof getSnapshot === 'function') { + strBase64 = getSnapshot(); + } else { + strBase64 = canvas.toDataURL(); + } + // Cache base64 string when canvas rendered. + if (renderedCanvas && strBase64) { + Storage.setItem(cacheKey, strBase64); + } + }, [id, renderedCanvas, cacheKey, getSnapshot]); + + useImperativeHandle(ref, () => ({ + cacheCanvasToStorage: cacheCanvasFunc, + })); + + useEffect(() => { + setMounted(true); + }, []); + + useEffect(() => { + if (window.WindVane) { + window.WindVane.call('WebAppInterface', 'enableHookNativeBack', {}); + window._windvane_backControl = () => { + cacheCanvasFunc(); + // Windvane must return a string value of true for it to work properly. + return 'true'; + }; + } + document.addEventListener('wvBackClickEvent', cacheCanvasFunc, false); + window.addEventListener('beforeunload', cacheCanvasFunc); + + return () => { + window.removeEventListener('beforeunload', cacheCanvasFunc); + window.removeEventListener('wvBackClickEvent', cacheCanvasFunc); + if (window._windvane_backControl) { + window._windvane_backControl = null; + } + }; + }, [cacheCanvasFunc]); + + useEffect(() => { + if (mounted && typeof init === 'function') { + const res = init(); + if (res instanceof Promise) { + res.then(() => { + setRenderedCanvas(true); + }); + } + } + }, [mounted, init]); + + return ( + <> + <canvas + {...rest} + className={className} + style={renderedCanvas ? style : { ...style, display: 'none' }} + id={id} + /> + { + !renderedCanvas && (<> + <img + className={className} + style={style} + src={Storage.getItem(cacheKey) || ''} + id={`canvas-img-${id}`} + /> + { + (typeof fallback === 'function') && (<div + id={`fallback-${id}`} + style={isNode || Storage.getItem(cacheKey) ? { display: 'none' } : { display: 'block' }} + > + { + fallback() + } + </div>) + } + <script + dangerouslySetInnerHTML={{ + __html: ` + const base64Data = localStorage.getItem('${cacheKey}'); + const fallback = document.getElementById('fallback-${id}'); + if (base64Data) { + const img = document.getElementById('canvas-img-${id}'); + img && (img.src = base64Data); + fallback && (fallback.style.display = 'none'); + } else { + fallback && (fallback.style.display = 'block'); + } + `, + }} + /> + </>) + } + </> + ); +}); diff --git a/packages/cache-canvas/src/storage.tsx b/packages/cache-canvas/src/storage.tsx new file mode 100644 index 0000000000..b20f3f0a4f --- /dev/null +++ b/packages/cache-canvas/src/storage.tsx @@ -0,0 +1,26 @@ +const cache = {}; + +export const Storage = { + setItem: (key, value) => { + try { + if (typeof window === 'object' && window.localStorage) { + return localStorage.setItem(key, value); + } + + return (cache[key] = value); + } catch (e) { + console.error('Storage setItem error:', e); + } + }, + getItem: (key) => { + try { + if (typeof window === 'object' && window.localStorage) { + return localStorage.getItem(key); + } + + return cache[key] || ''; + } catch (e) { + console.error('Storage getItem error:', e); + } + }, +}; \ No newline at end of file diff --git a/packages/cache-canvas/src/type.ts b/packages/cache-canvas/src/type.ts new file mode 100644 index 0000000000..31715de310 --- /dev/null +++ b/packages/cache-canvas/src/type.ts @@ -0,0 +1,3 @@ +export function isFunction(obj: any): obj is Function { + return typeof obj === 'function'; +} \ No newline at end of file diff --git a/packages/cache-canvas/tsconfig.json b/packages/cache-canvas/tsconfig.json new file mode 100644 index 0000000000..ec4381e7d2 --- /dev/null +++ b/packages/cache-canvas/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": "./", + "rootDir": "src", + "outDir": "esm" + }, + "allowJs": true, + "include": [ + "src" + ] +} \ No newline at end of file diff --git a/packages/plugin-cavans/README.md b/packages/plugin-cavans/README.md new file mode 100644 index 0000000000..677c5c2b49 --- /dev/null +++ b/packages/plugin-cavans/README.md @@ -0,0 +1,16 @@ +# @ice/plugin-canvas + +An ice.js plugin for canvas projects. + +## Usage + +Add plugin in `ice.config.mts`: + +```js +import { defineConfig } from 'ice'; +import canvasPlugin from '@ice/plugin-canvas'; + +export default defineConfig(() => ({ + plugins: [canvasPlugin({ /* options */ })], +})); +``` diff --git a/packages/plugin-cavans/package.json b/packages/plugin-cavans/package.json new file mode 100644 index 0000000000..6593e4d4cb --- /dev/null +++ b/packages/plugin-cavans/package.json @@ -0,0 +1,49 @@ +{ + "name": "@ice/plugin-canvas", + "version": "0.0.2", + "description": "Provide canvas render support for ice.js", + "license": "MIT", + "type": "module", + "exports": { + ".": { + "import": "./esm/index.js", + "default": "./esm/index.js" + }, + "./CacheCanvas": { + "types": "./esm/CacheCanvas.d.ts", + "import": "./esm/CacheCanvas.js", + "default": "./esm/CacheCanvas.js" + }, + "./runtime": { + "types": "./esm/runtime.d.ts", + "import": "./esm/runtime.js", + "default": "./esm/runtime.js" + }, + "./*": "./*" + }, + "main": "./esm/index.js", + "types": "./esm/index.d.ts", + "files": [ + "esm", + "!esm/**/*.map" + ], + "dependencies": { + "@ice/cache-canvas": "workspace:*", + "@ice/runtime": "^1.2.4" + }, + "devDependencies": { + "@ice/app": "^3.2.1", + "webpack": "^5.86.0" + }, + "repository": { + "type": "http", + "url": "https://github.com/alibaba/ice/tree/master/packages/plugin-canvas" + }, + "scripts": { + "watch": "tsc -w", + "build": "tsc" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/plugin-cavans/src/index.ts b/packages/plugin-cavans/src/index.ts new file mode 100644 index 0000000000..e76c74f47c --- /dev/null +++ b/packages/plugin-cavans/src/index.ts @@ -0,0 +1,15 @@ +import type { Plugin } from '@ice/app/types'; + +const PLUGIN_NAME = '@ice/plugin-canvas'; + +const plugin: Plugin = () => ({ + name: PLUGIN_NAME, + setup: async ({ generator }) => { + generator.addExport({ + source: '@ice/cache-canvas', + specifier: ['CacheCanvas'], + }); + }, +}); + +export default plugin; diff --git a/packages/plugin-cavans/tsconfig.json b/packages/plugin-cavans/tsconfig.json new file mode 100644 index 0000000000..972f3542f0 --- /dev/null +++ b/packages/plugin-cavans/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": "./", + "rootDir": "src", + "outDir": "esm", + "jsx": "react" + }, + "include": ["src"] +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8e145fbd5..820605c703 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -134,6 +134,29 @@ importers: speed-measure-webpack-plugin: 1.5.0_webpack@5.86.0 webpack: 5.86.0 + examples/cavans-project: + specifiers: + '@ice/app': workspace:* + '@ice/cache-canvas': workspace:* + '@ice/plugin-canvas': workspace:* + '@ice/runtime': workspace:* + '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.0 + react: ^18.0.0 + react-dom: ^18.0.0 + webpack: ^5.86.0 + dependencies: + '@ice/app': link:../../packages/ice + '@ice/cache-canvas': link:../../packages/cache-canvas + '@ice/plugin-canvas': link:../../packages/plugin-cavans + '@ice/runtime': link:../../packages/runtime + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + devDependencies: + '@types/react': 18.0.34 + '@types/react-dom': 18.0.11 + webpack: 5.86.0 + examples/csr-project: specifiers: '@ice/app': workspace:* @@ -1034,6 +1057,17 @@ importers: webpack-dev-server: 4.15.0_webpack@5.86.0 ws: 8.12.1 + packages/cache-canvas: + specifiers: + react: ^18.0.0 + react-dom: ^18.0.0 + universal-env: ^3.3.3 + dependencies: + universal-env: 3.3.3 + devDependencies: + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + packages/create-ice: specifiers: '@iceworks/generate-project': ^2.0.2 @@ -1238,6 +1272,19 @@ importers: '@types/react-dom': 18.0.11 regenerator-runtime: 0.13.11 + packages/plugin-cavans: + specifiers: + '@ice/app': ^3.2.1 + '@ice/cache-canvas': workspace:* + '@ice/runtime': ^1.2.4 + webpack: ^5.86.0 + dependencies: + '@ice/cache-canvas': link:../cache-canvas + '@ice/runtime': link:../runtime + devDependencies: + '@ice/app': link:../ice + webpack: 5.86.0 + packages/plugin-css-assets-local: specifiers: '@ice/app': ^3.1.2 @@ -9670,8 +9717,8 @@ packages: engines: {node: '>=10'} hasBin: true dependencies: - JSONStream: 1.3.5 is-text-path: 1.0.1 + JSONStream: 1.3.5 lodash: 4.17.21 meow: 8.1.2 split2: 3.2.2 @@ -18677,12 +18724,6 @@ packages: /react-dev-utils/12.0.1_y75l3d5in5mgvug53qfq62ncxu: resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} engines: {node: '>=14'} - peerDependencies: - typescript: '>=2.7' - webpack: '>=4' - peerDependenciesMeta: - typescript: - optional: true dependencies: '@babel/code-frame': 7.18.6 address: 1.2.2 @@ -18713,7 +18754,9 @@ packages: transitivePeerDependencies: - eslint - supports-color + - typescript - vue-template-compiler + - webpack /react-dom/17.0.2_react@17.0.2: resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} From b691b9e96ca66cd52508f549d9d6f623c54eb2c4 Mon Sep 17 00:00:00 2001 From: ClarkXia <xiawenwu41@gmail.com> Date: Tue, 18 Jul 2023 15:20:26 +0800 Subject: [PATCH 07/11] feat: support remove router even if route count is greater than 1 (#6382) * feat: support remove router even if route count is greater than 1 * fix: add test case * Update createService.ts * Update createService.ts --- .changeset/tidy-tomatoes-tie.md | 6 +++ examples/single-route/optimization.config.mts | 2 +- examples/single-route/src/pages/home.tsx | 7 +++ packages/ice/src/createService.ts | 5 +- packages/ice/src/types/userConfig.ts | 8 ++- packages/runtime/src/runClientApp.tsx | 10 ++-- packages/runtime/src/singleRouter.tsx | 31 +++++++++--- packages/runtime/tests/singleRoute.test.tsx | 50 ++++++++++++++++++- 8 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 .changeset/tidy-tomatoes-tie.md create mode 100644 examples/single-route/src/pages/home.tsx diff --git a/.changeset/tidy-tomatoes-tie.md b/.changeset/tidy-tomatoes-tie.md new file mode 100644 index 0000000000..b1c5cdf69c --- /dev/null +++ b/.changeset/tidy-tomatoes-tie.md @@ -0,0 +1,6 @@ +--- +'@ice/runtime': patch +'@ice/app': patch +--- + +feat: support remove router even if route count is greater than 1 diff --git a/examples/single-route/optimization.config.mts b/examples/single-route/optimization.config.mts index 6e27ecc934..6ca8677635 100644 --- a/examples/single-route/optimization.config.mts +++ b/examples/single-route/optimization.config.mts @@ -3,6 +3,6 @@ import { defineConfig } from '@ice/app'; export default defineConfig(() => ({ publicPath: '/', optimization: { - router: true, + disableRouter: true, }, })); diff --git a/examples/single-route/src/pages/home.tsx b/examples/single-route/src/pages/home.tsx new file mode 100644 index 0000000000..0d646b173f --- /dev/null +++ b/examples/single-route/src/pages/home.tsx @@ -0,0 +1,7 @@ +const home = () => { + return ( + <>home</> + ); +}; + +export default home; diff --git a/packages/ice/src/createService.ts b/packages/ice/src/createService.ts index 4341a5990e..95993d4c1f 100644 --- a/packages/ice/src/createService.ts +++ b/packages/ice/src/createService.ts @@ -232,9 +232,10 @@ async function createService({ rootDir, command, commandArgs }: CreateServiceOpt const hasExportAppData = (await getFileExports({ rootDir, file: 'src/app' })).includes('dataLoader'); const csr = !userConfig.ssr && !userConfig.ssg; - const disableRouter = userConfig?.optimization?.router && routesInfo.routesCount <= 1; + const disableRouter = (userConfig?.optimization?.router && routesInfo.routesCount <= 1) || + userConfig?.optimization?.disableRouter; if (disableRouter) { - logger.info('`optimization.router` is enabled and only have one route, ice build will remove react-router and history which is unnecessary.'); + logger.info('`optimization.router` is enabled, ice build will remove react-router and history which is unnecessary.'); taskConfigs = mergeTaskConfig(taskConfigs, { alias: { '@ice/runtime/router': '@ice/runtime/single-router', diff --git a/packages/ice/src/types/userConfig.ts b/packages/ice/src/types/userConfig.ts index dd0acca77a..8efced52f2 100644 --- a/packages/ice/src/types/userConfig.ts +++ b/packages/ice/src/types/userConfig.ts @@ -13,9 +13,15 @@ interface SyntaxFeatures { interface Optimization { /** - * Optimize code by remove react-router dependencies when set to true. + * Optimize code by remove react-router dependencies when set to true, + * it only works when route count is 1. */ router?: boolean; + /** + * @private + * Remove react-router dependencies by force, even if route count is greater than 1. + */ + disableRouter?: boolean; } interface MinifyOptions { diff --git a/packages/runtime/src/runClientApp.tsx b/packages/runtime/src/runClientApp.tsx index 4d2016a403..0052ce73d9 100644 --- a/packages/runtime/src/runClientApp.tsx +++ b/packages/runtime/src/runClientApp.tsx @@ -139,7 +139,7 @@ interface RenderOptions { async function render({ history, runtime, needHydrate }: RenderOptions) { const appContext = runtime.getAppContext(); - const { appConfig, loaderData, routes, basename } = appContext; + const { appConfig, loaderData, routes, basename, routePath } = appContext; const appRender = runtime.getRender(); const AppRuntimeProvider = runtime.composeAppProvider() || React.Fragment; const AppRouter = runtime.getAppRouter<ClientAppRouterProps>(); @@ -154,8 +154,9 @@ async function render({ history, runtime, needHydrate }: RenderOptions) { } const hydrationData = needHydrate ? { loaderData } : undefined; const routeModuleCache = {}; + const location = history.location ? history.location : { pathname: routePath || window.location.pathname }; if (needHydrate) { - const lazyMatches = matchRoutes(routes, history.location, basename).filter((m) => m.route.lazy); + const lazyMatches = matchRoutes(routes, location, basename).filter((m) => m.route.lazy); if (lazyMatches?.length > 0) { // Load the lazy matches and update the routes before creating your router // so we can hydrate the SSR-rendered content synchronously. @@ -182,8 +183,9 @@ async function render({ history, runtime, needHydrate }: RenderOptions) { let singleComponent = null; let routeData = null; if (process.env.ICE_CORE_ROUTER !== 'true') { - const { Component, loader } = await loadRouteModule(routes[0], routeModuleCache); - singleComponent = Component || routes[0].Component; + const singleRoute = matchRoutes(routes, location, basename)[0]; + const { Component, loader } = await loadRouteModule(singleRoute.route, routeModuleCache); + singleComponent = Component || singleRoute.route.Component; routeData = loader && await loader(); } const renderRoot = appRender( diff --git a/packages/runtime/src/singleRouter.tsx b/packages/runtime/src/singleRouter.tsx index ce20e796d1..46260345c5 100644 --- a/packages/runtime/src/singleRouter.tsx +++ b/packages/runtime/src/singleRouter.tsx @@ -42,15 +42,30 @@ export const createHistory = (): History => { }; }; -export const matchRoutes = (routes: any[]) => { - return routes.map(item => { - return { - params: {}, - pathname: '', - pathnameBase: '', - route: item, - }; +const stripString = (str: string) => { + const regexForSlash = /^\/|\/$/g; + return str.replace(regexForSlash, ''); +}; + +export const matchRoutes = (routes: any[], location: Partial<Location> | string, basename: string) => { + const stripedBasename = stripString(basename); + const pathname = typeof location === 'string' ? location : location.pathname; + let stripedPathname = stripString(pathname); + if (stripedBasename) { + stripedPathname = stripedPathname.replace(new RegExp(`^${stripedBasename}/`), ''); + } + const route = routes.length === 1 ? routes[0] : routes.find(item => { + return stripString(item.path || '') === stripedPathname; }); + if (!route) { + throw new Error(`No route matched pathname: ${pathname}`); + } + return [{ + route, + params: {}, + pathname, + pathnameBase: '', + }]; }; export const Link = () => null; diff --git a/packages/runtime/tests/singleRoute.test.tsx b/packages/runtime/tests/singleRoute.test.tsx index 7f5975b07a..9f6452d7ca 100644 --- a/packages/runtime/tests/singleRoute.test.tsx +++ b/packages/runtime/tests/singleRoute.test.tsx @@ -37,8 +37,54 @@ describe('single route api', () => { expect(createHistory().location).toBe(''); }); - it('matchRoutes', () => { - expect(matchRoutes([{}])[0].pathname).toBe(''); + it('matchRoutes - single route', () => { + const routes = [ + { + path: 'users', + element: <div>user</div>, + }, + ]; + const location = { + pathname: '/test', + }; + const matchedRoutes = matchRoutes(routes, location, '/'); + expect(matchedRoutes).toHaveLength(1); + expect(matchedRoutes[0].route.path).toBe('users'); + }); + + it('matchRoutes - mutiple route', () => { + const routes = [ + { + path: 'users', + element: <div>user</div>, + }, + { + path: 'posts', + element: <div>post</div>, + }, + ]; + const location = { + pathname: '/posts', + }; + const matchedRoutes = matchRoutes(routes, location, '/'); + expect(matchedRoutes).toHaveLength(1); + expect(matchedRoutes[0].route.path).toBe('posts'); + }); + + it('matchRoutes - basename', () => { + const routes = [ + { + path: 'users', + element: <div>user</div>, + }, + { + path: 'posts', + element: <div>post</div>, + }, + ]; + const matchedRoutes = matchRoutes(routes, '/basename/posts', '/basename'); + expect(matchedRoutes).toHaveLength(1); + expect(matchedRoutes[0].route.path).toBe('posts'); }); it('Link', () => { From 902558e2d3daee844b5eb2ffb678deb0420424fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jul 2023 17:13:11 +0800 Subject: [PATCH 08/11] chore(deps-dev): bump stylelint from 14.16.1 to 15.10.1 (#6378) Bumps [stylelint](https://github.com/stylelint/stylelint) from 14.16.1 to 15.10.1. - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](https://github.com/stylelint/stylelint/compare/14.16.1...15.10.1) --- updated-dependencies: - dependency-name: stylelint dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 298 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 233 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index aa57443cdb..b23991dbaf 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "rimraf": "^3.0.2", - "stylelint": "^14.10.0", + "stylelint": "^15.10.1", "tsx": "^3.12.1", "typescript": "^4.7.4", "vitest": "^0.15.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 820605c703..0dd088e17c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,13 +36,13 @@ importers: react: ^18.2.0 react-dom: ^18.2.0 rimraf: ^3.0.2 - stylelint: ^14.10.0 + stylelint: ^15.10.1 tsx: ^3.12.1 typescript: ^4.7.4 vitest: ^0.15.2 devDependencies: '@actions/exec': 1.1.1 - '@applint/spec': 1.2.3_2rmdvng2abj4ynagd7mmfkgabm + '@applint/spec': 1.2.3_rq3f74y76ouqd6o4mk7bsba7uy '@changesets/cli': 2.26.0 '@commitlint/cli': 16.3.0 '@ice/bundles': link:packages/bundles @@ -73,7 +73,7 @@ importers: react: 18.2.0 react-dom: 18.2.0_react@18.2.0 rimraf: 3.0.2 - stylelint: 14.16.1 + stylelint: 15.10.1 tsx: 3.12.3 typescript: 4.9.5 vitest: 0.15.2_c8@7.13.0+jsdom@20.0.3 @@ -1989,7 +1989,7 @@ packages: resolution: {integrity: sha512-E9j36XUQQ61ghAzosPORABOB8GGMtZ/ZRHOBjsQ7Cr4PgU7zhNbClsoaie6wimRSZfOt9OUR/rAPR4u3rY43Hg==} dev: true - /@applint/spec/1.2.3_2rmdvng2abj4ynagd7mmfkgabm: + /@applint/spec/1.2.3_rq3f74y76ouqd6o4mk7bsba7uy: resolution: {integrity: sha512-6Wx4FHYB71NYywVi7zu1JAkRCGP73bH1mjQIHVhTp0JWenC0bs1210ofjrjwJntuRYMc+JF22XA1YVwbiRmXbw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1999,7 +1999,7 @@ packages: '@applint/commitlint-config': 1.0.2 '@applint/eslint-config': 1.1.12_iqs4awvhuo7d5qfalrm5goz2ja '@applint/prettier-config': 1.0.1 - '@applint/stylelint-config': 1.0.2_c4jl5v2irl4uepdjfeoqpam4ne + '@applint/stylelint-config': 1.0.2_l27tme7gmbb6czcwbj7ki3rooy '@babel/core': 7.21.0 '@babel/eslint-parser': 7.19.1_zt6cfucldurvbyn2isj445jria '@babel/preset-react': 7.18.6_@babel+core@7.21.0 @@ -2019,8 +2019,8 @@ packages: postcss-less: 6.0.0_postcss@8.4.21 postcss-scss: 4.0.6_postcss@8.4.21 require-all: 3.0.0 - stylelint: 14.16.1 - stylelint-scss: 4.4.0_stylelint@14.16.1 + stylelint: 15.10.1 + stylelint-scss: 4.4.0_stylelint@15.10.1 vue-eslint-parser: 8.3.0_eslint@8.35.0 transitivePeerDependencies: - eslint-import-resolver-typescript @@ -2029,7 +2029,7 @@ packages: - typescript dev: true - /@applint/stylelint-config/1.0.2_c4jl5v2irl4uepdjfeoqpam4ne: + /@applint/stylelint-config/1.0.2_l27tme7gmbb6czcwbj7ki3rooy: resolution: {integrity: sha512-qJGy/91OIj2YA6mF21UC0O7Ab1TT28fUt4OgZXZ/kdrgvEHek7/2njoN1f4RRNM9Q0R/+fQYjfGc2mrN+M47Kw==} peerDependencies: postcss: '>=8.0.0' @@ -2041,8 +2041,8 @@ packages: postcss: 8.4.21 postcss-less: 6.0.0_postcss@8.4.21 postcss-scss: 4.0.6_postcss@8.4.21 - stylelint: 14.16.1 - stylelint-scss: 4.4.0_stylelint@14.16.1 + stylelint: 15.10.1 + stylelint-scss: 4.4.0_stylelint@15.10.1 dev: true /@appworks/constant/0.1.4: @@ -3744,6 +3744,31 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true + /@csstools/css-parser-algorithms/2.3.0_gdfqdfecdiaxr4x3xd7wxrvuhq: + resolution: {integrity: sha512-dTKSIHHWc0zPvcS5cqGP+/TPFUJB0ekJ9dGKvMAFoNuBFhDPBt9OMGNZiIA5vTiNdGHHBeScYPXIGBMnVOahsA==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-tokenizer': ^2.1.1 + dependencies: + '@csstools/css-tokenizer': 2.1.1 + dev: true + + /@csstools/css-tokenizer/2.1.1: + resolution: {integrity: sha512-GbrTj2Z8MCTUv+52GE0RbFGM527xuXZ0Xa5g0Z+YN573uveS4G0qi6WNOMyz3yrFM/jaILTTwJ0+umx81EzqfA==} + engines: {node: ^14 || ^16 || >=18} + dev: true + + /@csstools/media-query-list-parser/2.1.2_jbsnjf4bbpbvuoxaajyf7saxw4: + resolution: {integrity: sha512-M8cFGGwl866o6++vIY7j1AKuq9v57cf+dGepScwCcbut9ypJNr4Cj+LLTWligYUZ0uyhEoJDKt5lvyBfh2L3ZQ==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + '@csstools/css-parser-algorithms': ^2.3.0 + '@csstools/css-tokenizer': ^2.1.1 + dependencies: + '@csstools/css-parser-algorithms': 2.3.0_gdfqdfecdiaxr4x3xd7wxrvuhq + '@csstools/css-tokenizer': 2.1.1 + dev: true + /@csstools/postcss-color-function/1.1.1_postcss@8.4.12: resolution: {integrity: sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==} engines: {node: ^12 || ^14 || >=16} @@ -3839,15 +3864,13 @@ packages: postcss-selector-parser: 6.0.11 dev: true - /@csstools/selector-specificity/2.1.1_wajs5nedgkikc5pcuwett7legi: - resolution: {integrity: sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==} + /@csstools/selector-specificity/3.0.0_c3vcbepomgmxc74cgtawpgpkyi: + resolution: {integrity: sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==} engines: {node: ^14 || ^16 || >=18} peerDependencies: - postcss: ^8.4 - postcss-selector-parser: ^6.0.10 + postcss-selector-parser: ^6.0.13 dependencies: - postcss: 8.4.21 - postcss-selector-parser: 6.0.11 + postcss-selector-parser: 6.0.13 dev: true /@ctrl/tinycolor/3.6.0: @@ -9214,6 +9237,16 @@ packages: quick-lru: 4.0.1 dev: true + /camelcase-keys/7.0.2: + resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==} + engines: {node: '>=12'} + dependencies: + camelcase: 6.3.0 + map-obj: 4.3.0 + quick-lru: 5.1.1 + type-fest: 1.4.0 + dev: true + /camelcase/3.0.0: resolution: {integrity: sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==} engines: {node: '>=0.10.0'} @@ -9861,6 +9894,16 @@ packages: path-type: 4.0.0 dev: true + /cosmiconfig/8.2.0: + resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==} + engines: {node: '>=14'} + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + dev: true + /create-react-class/15.7.0: resolution: {integrity: sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==} dependencies: @@ -10095,6 +10138,14 @@ packages: mdn-data: 2.0.14 source-map: 0.6.1 + /css-tree/2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.0.2 + dev: true + /css-what/3.4.2: resolution: {integrity: sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==} engines: {node: '>= 6'} @@ -10384,6 +10435,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /decamelize/5.0.1: + resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==} + engines: {node: '>=10'} + dev: true + /decimal.js/10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} dev: true @@ -11641,7 +11697,7 @@ packages: eslint-utils: 3.0.0_eslint@8.35.0 natural-compare: 1.4.0 nth-check: 2.1.1 - postcss-selector-parser: 6.0.11 + postcss-selector-parser: 6.0.13 semver: 7.4.0 vue-eslint-parser: 8.3.0_eslint@8.35.0 transitivePeerDependencies: @@ -11983,6 +12039,16 @@ packages: merge2: 1.4.1 micromatch: 4.0.5 + /fast-glob/3.3.0: + resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + /fast-json-stable-stringify/2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -12588,7 +12654,7 @@ packages: '@types/glob': 7.2.0 array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.2.12 + fast-glob: 3.3.0 glob: 7.2.3 ignore: 5.2.4 merge2: 1.4.1 @@ -12601,7 +12667,7 @@ packages: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.2.12 + fast-glob: 3.3.0 ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 @@ -12911,6 +12977,11 @@ packages: resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==} engines: {node: '>=8'} + /html-tags/3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + dev: true + /html-void-elements/1.0.5: resolution: {integrity: sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==} @@ -13226,6 +13297,11 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + /indent-string/5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + dev: true + /infima/0.2.0-alpha.42: resolution: {integrity: sha512-ift8OXNbQQwtbIt6z16KnSWP7uJ/SysSMFI4F87MNRTicypfl4Pv3E2OGVv6N3nSZFJvA8imYulCBS64iyHYww==} engines: {node: '>=12'} @@ -14909,8 +14985,8 @@ packages: resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} engines: {node: '>= 8'} - /known-css-properties/0.26.0: - resolution: {integrity: sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==} + /known-css-properties/0.27.0: + resolution: {integrity: sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==} dev: true /language-subtag-registry/0.3.22: @@ -15335,6 +15411,10 @@ packages: /mdn-data/2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + /mdn-data/2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + dev: true + /mdn-data/2.0.4: resolution: {integrity: sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==} dev: false @@ -15352,6 +15432,24 @@ packages: dependencies: fs-monkey: 1.0.3 + /meow/10.1.5: + resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + '@types/minimist': 1.2.2 + camelcase-keys: 7.0.2 + decamelize: 5.0.1 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 8.0.0 + redent: 4.0.0 + trim-newlines: 4.1.1 + type-fest: 1.4.0 + yargs-parser: 20.2.9 + dev: true + /meow/6.1.1: resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} engines: {node: '>=8'} @@ -15386,24 +15484,6 @@ packages: yargs-parser: 20.2.9 dev: true - /meow/9.0.0: - resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} - engines: {node: '>=10'} - dependencies: - '@types/minimist': 1.2.2 - camelcase-keys: 6.2.2 - decamelize: 1.2.0 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 3.0.3 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.18.1 - yargs-parser: 20.2.9 - dev: true - /merge-descriptors/1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} @@ -15635,6 +15715,12 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + /nanoid/3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + /natural-compare-lite/1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} dev: true @@ -17328,13 +17414,13 @@ packages: resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} dev: true - /postcss-safe-parser/6.0.0_postcss@8.4.21: + /postcss-safe-parser/6.0.0_postcss@8.4.25: resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.3.3 dependencies: - postcss: 8.4.21 + postcss: 8.4.25 dev: true /postcss-scss/4.0.6_postcss@8.4.21: @@ -17362,6 +17448,14 @@ packages: cssesc: 3.0.0 util-deprecate: 1.0.2 + /postcss-selector-parser/6.0.13: + resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + /postcss-sort-media-queries/4.3.0_postcss@8.4.21: resolution: {integrity: sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg==} engines: {node: '>=10.0.0'} @@ -17446,6 +17540,15 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss/8.4.25: + resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + /preferred-pm/3.0.3: resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==} engines: {node: '>=10'} @@ -19030,6 +19133,15 @@ packages: type-fest: 0.8.1 dev: true + /read-pkg-up/8.0.0: + resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==} + engines: {node: '>=12'} + dependencies: + find-up: 5.0.0 + read-pkg: 6.0.0 + type-fest: 1.4.0 + dev: true + /read-pkg/5.2.0: resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} engines: {node: '>=8'} @@ -19040,6 +19152,16 @@ packages: type-fest: 0.6.0 dev: true + /read-pkg/6.0.0: + resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==} + engines: {node: '>=12'} + dependencies: + '@types/normalize-package-data': 2.4.1 + normalize-package-data: 3.0.3 + parse-json: 5.2.0 + type-fest: 1.4.0 + dev: true + /read-yaml-file/1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -19098,6 +19220,14 @@ packages: strip-indent: 3.0.0 dev: true + /redent/4.0.0: + resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==} + engines: {node: '>=12'} + dependencies: + indent-string: 5.0.0 + strip-indent: 4.0.0 + dev: true + /redux-thunk/2.4.2_redux@4.2.1: resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==} peerDependencies: @@ -19886,6 +20016,11 @@ packages: /signal-exit/3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + /signal-exit/4.0.2: + resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==} + engines: {node: '>=14'} + dev: true + /sirv/1.0.19: resolution: {integrity: sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==} engines: {node: '>= 10'} @@ -20327,6 +20462,13 @@ packages: min-indent: 1.0.1 dev: true + /strip-indent/4.0.0: + resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} + engines: {node: '>=12'} + dependencies: + min-indent: 1.0.1 + dev: true + /strip-json-comments/2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -20386,7 +20528,7 @@ packages: postcss: 8.4.21 postcss-selector-parser: 6.0.11 - /stylelint-scss/4.4.0_stylelint@14.16.1: + /stylelint-scss/4.4.0_stylelint@15.10.1: resolution: {integrity: sha512-Qy66a+/30aylFhPmUArHhVsHOun1qrO93LGT15uzLuLjWS7hKDfpFm34mYo1ndR4MCo8W4bEZM1+AlJRJORaaw==} peerDependencies: stylelint: ^14.5.1 || ^15.0.0 @@ -20394,54 +20536,56 @@ packages: lodash: 4.17.21 postcss-media-query-parser: 0.2.3 postcss-resolve-nested-selector: 0.1.1 - postcss-selector-parser: 6.0.11 + postcss-selector-parser: 6.0.13 postcss-value-parser: 4.2.0 - stylelint: 14.16.1 + stylelint: 15.10.1 dev: true - /stylelint/14.16.1: - resolution: {integrity: sha512-ErlzR/T3hhbV+a925/gbfc3f3Fep9/bnspMiJPorfGEmcBbXdS+oo6LrVtoUZ/w9fqD6o6k7PtUlCOsCRdjX/A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + /stylelint/15.10.1: + resolution: {integrity: sha512-CYkzYrCFfA/gnOR+u9kJ1PpzwG10WLVnoxHDuBA/JiwGqdM9+yx9+ou6SE/y9YHtfv1mcLo06fdadHTOx4gBZQ==} + engines: {node: ^14.13.1 || >=16.0.0} hasBin: true dependencies: - '@csstools/selector-specificity': 2.1.1_wajs5nedgkikc5pcuwett7legi + '@csstools/css-parser-algorithms': 2.3.0_gdfqdfecdiaxr4x3xd7wxrvuhq + '@csstools/css-tokenizer': 2.1.1 + '@csstools/media-query-list-parser': 2.1.2_jbsnjf4bbpbvuoxaajyf7saxw4 + '@csstools/selector-specificity': 3.0.0_c3vcbepomgmxc74cgtawpgpkyi balanced-match: 2.0.0 colord: 2.9.3 - cosmiconfig: 7.1.0 + cosmiconfig: 8.2.0 css-functions-list: 3.1.0 + css-tree: 2.3.1 debug: 4.3.4 - fast-glob: 3.2.12 + fast-glob: 3.3.0 fastest-levenshtein: 1.0.16 file-entry-cache: 6.0.1 global-modules: 2.0.0 globby: 11.1.0 globjoin: 0.1.4 - html-tags: 3.2.0 + html-tags: 3.3.1 ignore: 5.2.4 import-lazy: 4.0.0 imurmurhash: 0.1.4 is-plain-object: 5.0.0 - known-css-properties: 0.26.0 + known-css-properties: 0.27.0 mathml-tag-names: 2.1.3 - meow: 9.0.0 + meow: 10.1.5 micromatch: 4.0.5 normalize-path: 3.0.0 picocolors: 1.0.0 - postcss: 8.4.21 - postcss-media-query-parser: 0.2.3 + postcss: 8.4.25 postcss-resolve-nested-selector: 0.1.1 - postcss-safe-parser: 6.0.0_postcss@8.4.21 - postcss-selector-parser: 6.0.11 + postcss-safe-parser: 6.0.0_postcss@8.4.25 + postcss-selector-parser: 6.0.13 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 style-search: 0.1.0 - supports-hyperlinks: 2.3.0 + supports-hyperlinks: 3.0.0 svg-tags: 1.0.0 table: 6.8.1 - v8-compile-cache: 2.3.0 - write-file-atomic: 4.0.2 + write-file-atomic: 5.0.1 transitivePeerDependencies: - supports-color dev: true @@ -20490,6 +20634,14 @@ packages: supports-color: 7.2.0 dev: true + /supports-hyperlinks/3.0.0: + resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} + engines: {node: '>=14.18'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + /supports-preserve-symlinks-flag/1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -20924,6 +21076,11 @@ packages: engines: {node: '>=8'} dev: true + /trim-newlines/4.1.1: + resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==} + engines: {node: '>=12'} + dev: true + /trim-trailing-lines/1.1.4: resolution: {integrity: sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==} @@ -21138,6 +21295,11 @@ packages: engines: {node: '>=8'} dev: true + /type-fest/1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: true + /type-fest/2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} @@ -21548,10 +21710,6 @@ packages: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true - /v8-compile-cache/2.3.0: - resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} - dev: true - /v8-to-istanbul/9.1.0: resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} engines: {node: '>=10.12.0'} @@ -21618,7 +21776,7 @@ packages: optional: true dependencies: esbuild: 0.14.54 - postcss: 8.4.21 + postcss: 8.4.25 resolve: 1.22.1 rollup: 2.77.3 optionalDependencies: @@ -21652,7 +21810,7 @@ packages: dependencies: '@types/node': 17.0.45 esbuild: 0.15.18 - postcss: 8.4.21 + postcss: 8.4.25 resolve: 1.22.1 rollup: 2.79.1 optionalDependencies: @@ -22463,6 +22621,14 @@ packages: signal-exit: 3.0.7 dev: true + /write-file-atomic/5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.0.2 + dev: true + /ws/7.5.9: resolution: {integrity: sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==} engines: {node: '>=8.3.0'} From 92ec144fd0c69ddea5140ec4f0b54952125fec86 Mon Sep 17 00:00:00 2001 From: ClarkXia <xiawenwu41@gmail.com> Date: Wed, 19 Jul 2023 17:14:49 +0800 Subject: [PATCH 09/11] fix: do not compile runtime library of tslib (#6377) * fix: do not compile runtime library of tslib * chore: changelog --- .changeset/tricky-panthers-applaud.md | 5 +++++ packages/webpack-config/src/compileExcludes.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/tricky-panthers-applaud.md diff --git a/.changeset/tricky-panthers-applaud.md b/.changeset/tricky-panthers-applaud.md new file mode 100644 index 0000000000..51eaae83d3 --- /dev/null +++ b/.changeset/tricky-panthers-applaud.md @@ -0,0 +1,5 @@ +--- +'@ice/webpack-config': patch +--- + +fix: do not compile runtime library of tslib diff --git a/packages/webpack-config/src/compileExcludes.ts b/packages/webpack-config/src/compileExcludes.ts index f770b8a085..37aff4d0da 100644 --- a/packages/webpack-config/src/compileExcludes.ts +++ b/packages/webpack-config/src/compileExcludes.ts @@ -1,6 +1,6 @@ const SKIP_COMPILE = [ // polyfill and helpers - 'core-js', 'core-js-pure', '@swc/helpers', '@babel/runtime', + 'core-js', 'core-js-pure', '@swc/helpers', '@babel/runtime', 'tslib', // Deprecate version of @babel/runtime. 'babel-runtime', // built-in runtime From b58d38a17826fe9b278be663cf891d4dab194768 Mon Sep 17 00:00:00 2001 From: Linbudu <48507806+linbudu599@users.noreply.github.com> Date: Wed, 19 Jul 2023 19:36:59 +0800 Subject: [PATCH 10/11] chore: inlineStyle filter support (#6397) --- .changeset/sharp-frogs-live.md | 5 +++++ packages/plugin-rax-compat/src/index.ts | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 .changeset/sharp-frogs-live.md diff --git a/.changeset/sharp-frogs-live.md b/.changeset/sharp-frogs-live.md new file mode 100644 index 0000000000..34c58bfd4f --- /dev/null +++ b/.changeset/sharp-frogs-live.md @@ -0,0 +1,5 @@ +--- +'@ice/plugin-rax-compat': patch +--- + +inlineStyle filter support diff --git a/packages/plugin-rax-compat/src/index.ts b/packages/plugin-rax-compat/src/index.ts index 283cb84c99..be2efcd77b 100644 --- a/packages/plugin-rax-compat/src/index.ts +++ b/packages/plugin-rax-compat/src/index.ts @@ -60,7 +60,23 @@ const ruleSetStylesheetForLess = { let warnOnce = false; export interface CompatRaxOptions { + /** + * Enable inline style transform. + * + * @default false + * + * @example + * ```js + * inlineStyle: true; + * inlineStyle: (id) => id.includes('feeds_module'); + * ``` + */ inlineStyle?: boolean | ((id: string) => boolean); + /** + * Enable css module transform. + * + * @default true + */ cssModule?: boolean; } From 9878e74079f29403f880a1d84ed07857af5da4c9 Mon Sep 17 00:00:00 2001 From: ClarkXia <xiawenwu41@gmail.com> Date: Thu, 20 Jul 2023 11:52:07 +0800 Subject: [PATCH 11/11] chore: update versions (#6387) --- .changeset/dry-rockets-exist.md | 5 ----- .changeset/flat-spies-attack.md | 5 ----- .changeset/funny-dolphins-hope.md | 5 ----- .changeset/rotten-hats-mate.md | 6 ------ .changeset/sharp-frogs-live.md | 5 ----- .changeset/tidy-tomatoes-tie.md | 6 ------ .changeset/tough-lobsters-attend.md | 5 ----- .changeset/tricky-panthers-applaud.md | 5 ----- packages/cache-canvas/CHANGELOG.md | 7 +++++++ packages/cache-canvas/package.json | 2 +- packages/ice/CHANGELOG.md | 13 +++++++++++++ packages/ice/package.json | 6 +++--- packages/plugin-cavans/CHANGELOG.md | 11 +++++++++++ packages/plugin-cavans/package.json | 6 +++--- packages/plugin-i18n/package.json | 4 ++-- packages/plugin-pha/CHANGELOG.md | 6 ++++++ packages/plugin-pha/package.json | 4 ++-- packages/plugin-rax-compat/CHANGELOG.md | 6 ++++++ packages/plugin-rax-compat/package.json | 4 ++-- packages/runtime/CHANGELOG.md | 6 ++++++ packages/runtime/package.json | 2 +- packages/webpack-config/CHANGELOG.md | 7 +++++++ packages/webpack-config/package.json | 2 +- pnpm-lock.yaml | 22 +++++++++++++--------- 24 files changed, 84 insertions(+), 66 deletions(-) delete mode 100644 .changeset/dry-rockets-exist.md delete mode 100644 .changeset/flat-spies-attack.md delete mode 100644 .changeset/funny-dolphins-hope.md delete mode 100644 .changeset/rotten-hats-mate.md delete mode 100644 .changeset/sharp-frogs-live.md delete mode 100644 .changeset/tidy-tomatoes-tie.md delete mode 100644 .changeset/tough-lobsters-attend.md delete mode 100644 .changeset/tricky-panthers-applaud.md create mode 100644 packages/cache-canvas/CHANGELOG.md create mode 100644 packages/plugin-cavans/CHANGELOG.md diff --git a/.changeset/dry-rockets-exist.md b/.changeset/dry-rockets-exist.md deleted file mode 100644 index 845b7d1d95..0000000000 --- a/.changeset/dry-rockets-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@ice/cache-canvas': patch ---- - -feat: support cache of 2d cavans diff --git a/.changeset/flat-spies-attack.md b/.changeset/flat-spies-attack.md deleted file mode 100644 index c21cbb1252..0000000000 --- a/.changeset/flat-spies-attack.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@ice/app': patch ---- - -fix: always external dependencies when get config diff --git a/.changeset/funny-dolphins-hope.md b/.changeset/funny-dolphins-hope.md deleted file mode 100644 index 36ac4e8c6c..0000000000 --- a/.changeset/funny-dolphins-hope.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@ice/plugin-pha': patch ---- - -fix: format of dataLoaderConfig loader changed. diff --git a/.changeset/rotten-hats-mate.md b/.changeset/rotten-hats-mate.md deleted file mode 100644 index 3762f5aff0..0000000000 --- a/.changeset/rotten-hats-mate.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@ice/webpack-config': patch -'@ice/app': patch ---- - -feat: support code splitting strategy of page-vendors diff --git a/.changeset/sharp-frogs-live.md b/.changeset/sharp-frogs-live.md deleted file mode 100644 index 34c58bfd4f..0000000000 --- a/.changeset/sharp-frogs-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@ice/plugin-rax-compat': patch ---- - -inlineStyle filter support diff --git a/.changeset/tidy-tomatoes-tie.md b/.changeset/tidy-tomatoes-tie.md deleted file mode 100644 index b1c5cdf69c..0000000000 --- a/.changeset/tidy-tomatoes-tie.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@ice/runtime': patch -'@ice/app': patch ---- - -feat: support remove router even if route count is greater than 1 diff --git a/.changeset/tough-lobsters-attend.md b/.changeset/tough-lobsters-attend.md deleted file mode 100644 index 48da8c3e7d..0000000000 --- a/.changeset/tough-lobsters-attend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@ice/plugin-canvas': patch ---- - -feat: support cache of 2d cavans diff --git a/.changeset/tricky-panthers-applaud.md b/.changeset/tricky-panthers-applaud.md deleted file mode 100644 index 51eaae83d3..0000000000 --- a/.changeset/tricky-panthers-applaud.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@ice/webpack-config': patch ---- - -fix: do not compile runtime library of tslib diff --git a/packages/cache-canvas/CHANGELOG.md b/packages/cache-canvas/CHANGELOG.md new file mode 100644 index 0000000000..788d6cb938 --- /dev/null +++ b/packages/cache-canvas/CHANGELOG.md @@ -0,0 +1,7 @@ +# @ice/cache-canvas + +## 0.0.9 + +### Patch Changes + +- 018238f9: feat: support cache of 2d cavans diff --git a/packages/cache-canvas/package.json b/packages/cache-canvas/package.json index 6626fdd12a..197098970d 100644 --- a/packages/cache-canvas/package.json +++ b/packages/cache-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@ice/cache-canvas", - "version": "0.0.8", + "version": "0.0.9", "description": "", "main": "./esm/index.js", "types": "./esm/index.d.ts", diff --git a/packages/ice/CHANGELOG.md b/packages/ice/CHANGELOG.md index 6f2af64c73..2e2f72d0a2 100644 --- a/packages/ice/CHANGELOG.md +++ b/packages/ice/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 3.2.8 + +### Patch Changes + +- 27a72536: fix: always external dependencies when get config +- cf8a78e3: feat: support code splitting strategy of page-vendors +- b691b9e9: feat: support remove router even if route count is greater than 1 +- Updated dependencies [cf8a78e3] +- Updated dependencies [b691b9e9] +- Updated dependencies [92ec144f] + - @ice/webpack-config@1.0.19 + - @ice/runtime@1.2.6 + ## 3.2.7 ### Patch Changes diff --git a/packages/ice/package.json b/packages/ice/package.json index ae81f4e2ca..6687bee225 100644 --- a/packages/ice/package.json +++ b/packages/ice/package.json @@ -1,6 +1,6 @@ { "name": "@ice/app", - "version": "3.2.7", + "version": "3.2.8", "description": "provide scripts and configuration used by web framework ice", "type": "module", "main": "./esm/index.js", @@ -38,8 +38,8 @@ "dependencies": { "@ice/bundles": "0.1.12", "@ice/route-manifest": "1.2.0", - "@ice/runtime": "^1.2.5", - "@ice/webpack-config": "1.0.18", + "@ice/runtime": "^1.2.6", + "@ice/webpack-config": "1.0.19", "@swc/helpers": "0.5.1", "@types/express": "^4.17.14", "address": "^1.1.2", diff --git a/packages/plugin-cavans/CHANGELOG.md b/packages/plugin-cavans/CHANGELOG.md new file mode 100644 index 0000000000..41f98901b1 --- /dev/null +++ b/packages/plugin-cavans/CHANGELOG.md @@ -0,0 +1,11 @@ +# @ice/plugin-canvas + +## 0.0.3 + +### Patch Changes + +- 018238f9: feat: support cache of 2d cavans +- Updated dependencies [018238f9] +- Updated dependencies [b691b9e9] + - @ice/cache-canvas@0.0.9 + - @ice/runtime@1.2.6 diff --git a/packages/plugin-cavans/package.json b/packages/plugin-cavans/package.json index 6593e4d4cb..2c1e795760 100644 --- a/packages/plugin-cavans/package.json +++ b/packages/plugin-cavans/package.json @@ -1,6 +1,6 @@ { "name": "@ice/plugin-canvas", - "version": "0.0.2", + "version": "0.0.3", "description": "Provide canvas render support for ice.js", "license": "MIT", "type": "module", @@ -29,10 +29,10 @@ ], "dependencies": { "@ice/cache-canvas": "workspace:*", - "@ice/runtime": "^1.2.4" + "@ice/runtime": "^1.2.6" }, "devDependencies": { - "@ice/app": "^3.2.1", + "@ice/app": "^3.2.8", "webpack": "^5.86.0" }, "repository": { diff --git a/packages/plugin-i18n/package.json b/packages/plugin-i18n/package.json index 749f1bd995..6b97581aae 100644 --- a/packages/plugin-i18n/package.json +++ b/packages/plugin-i18n/package.json @@ -55,8 +55,8 @@ "webpack-dev-server": "^4.13.2" }, "peerDependencies": { - "@ice/app": "^3.2.7", - "@ice/runtime": "^1.2.5" + "@ice/app": "^3.2.8", + "@ice/runtime": "^1.2.6" }, "publishConfig": { "access": "public" diff --git a/packages/plugin-pha/CHANGELOG.md b/packages/plugin-pha/CHANGELOG.md index 9c7dd320be..f387803b16 100644 --- a/packages/plugin-pha/CHANGELOG.md +++ b/packages/plugin-pha/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 3.0.2 + +### Patch Changes + +- 39c92e5b: fix: format of dataLoaderConfig loader changed. + ## 3.0.1 ### Patch Changes diff --git a/packages/plugin-pha/package.json b/packages/plugin-pha/package.json index df0544eff4..45290e8ff0 100644 --- a/packages/plugin-pha/package.json +++ b/packages/plugin-pha/package.json @@ -1,6 +1,6 @@ { "name": "@ice/plugin-pha", - "version": "3.0.1", + "version": "3.0.2", "description": "ice.js plugin for PHA.", "license": "MIT", "type": "module", @@ -25,7 +25,7 @@ "htmlparser2": "^8.0.1" }, "devDependencies": { - "@ice/app": "^3.2.7", + "@ice/app": "^3.2.8", "build-scripts": "^2.1.1-0", "esbuild": "^0.17.16", "webpack": "^5.86.0", diff --git a/packages/plugin-rax-compat/CHANGELOG.md b/packages/plugin-rax-compat/CHANGELOG.md index 8e0bcba7cf..10e923321d 100644 --- a/packages/plugin-rax-compat/CHANGELOG.md +++ b/packages/plugin-rax-compat/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.2.4 + +### Patch Changes + +- b58d38a1: inlineStyle filter support + ## 0.2.3 ### Patch Changes diff --git a/packages/plugin-rax-compat/package.json b/packages/plugin-rax-compat/package.json index ccd0a1411f..432250912a 100644 --- a/packages/plugin-rax-compat/package.json +++ b/packages/plugin-rax-compat/package.json @@ -1,6 +1,6 @@ { "name": "@ice/plugin-rax-compat", - "version": "0.2.3", + "version": "0.2.4", "description": "Provide rax compat support for ice.js", "license": "MIT", "type": "module", @@ -30,7 +30,7 @@ "stylesheet-loader": "^0.9.1" }, "devDependencies": { - "@ice/app": "^3.2.7", + "@ice/app": "^3.2.8", "@types/lodash-es": "^4.17.7", "webpack": "^5.86.0" }, diff --git a/packages/runtime/CHANGELOG.md b/packages/runtime/CHANGELOG.md index 117c3d7585..fea54747e3 100644 --- a/packages/runtime/CHANGELOG.md +++ b/packages/runtime/CHANGELOG.md @@ -1,5 +1,11 @@ # @ice/runtime +## 1.2.6 + +### Patch Changes + +- b691b9e9: feat: support remove router even if route count is greater than 1 + ## 1.2.5 ### Patch Changes diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 7f76a8e512..badd36be71 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -1,6 +1,6 @@ { "name": "@ice/runtime", - "version": "1.2.5", + "version": "1.2.6", "description": "Runtime module for ice.js", "type": "module", "types": "./esm/index.d.ts", diff --git a/packages/webpack-config/CHANGELOG.md b/packages/webpack-config/CHANGELOG.md index 6357f5f7ed..b5dde78b74 100644 --- a/packages/webpack-config/CHANGELOG.md +++ b/packages/webpack-config/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 1.0.19 + +### Patch Changes + +- cf8a78e3: feat: support code splitting strategy of page-vendors +- 92ec144f: fix: do not compile runtime library of tslib + ## 1.0.18 ### Patch Changes diff --git a/packages/webpack-config/package.json b/packages/webpack-config/package.json index da577d6eda..f999ffe345 100644 --- a/packages/webpack-config/package.json +++ b/packages/webpack-config/package.json @@ -1,6 +1,6 @@ { "name": "@ice/webpack-config", - "version": "1.0.18", + "version": "1.0.19", "repository": "alibaba/ice", "bugs": "https://github.com/alibaba/ice/issues", "homepage": "https://v3.ice.work", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0dd088e17c..ac54a3407c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1091,8 +1091,8 @@ importers: specifiers: '@ice/bundles': 0.1.12 '@ice/route-manifest': 1.2.0 - '@ice/runtime': ^1.2.5 - '@ice/webpack-config': 1.0.18 + '@ice/runtime': ^1.2.6 + '@ice/webpack-config': 1.0.19 '@swc/helpers': 0.5.1 '@types/babel__generator': ^7.6.4 '@types/babel__traverse': ^7.17.1 @@ -1274,9 +1274,9 @@ importers: packages/plugin-cavans: specifiers: - '@ice/app': ^3.2.1 + '@ice/app': ^3.2.8 '@ice/cache-canvas': workspace:* - '@ice/runtime': ^1.2.4 + '@ice/runtime': ^1.2.6 webpack: ^5.86.0 dependencies: '@ice/cache-canvas': link:../cache-canvas @@ -1421,7 +1421,7 @@ importers: packages/plugin-pha: specifiers: - '@ice/app': ^3.2.7 + '@ice/app': ^3.2.8 '@remix-run/router': ^1.6.1 build-scripts: ^2.1.1-0 chalk: ^4.0.0 @@ -1450,7 +1450,7 @@ importers: specifiers: '@babel/core': ^7.0.0 '@babel/plugin-proposal-export-default-from': ^7.18.9 - '@ice/app': ^3.2.7 + '@ice/app': ^3.2.8 '@ice/bundles': ^0.1.10 '@types/lodash-es': ^4.17.7 babel-plugin-transform-jsx-stylesheet: 1.0.6 @@ -9750,8 +9750,8 @@ packages: engines: {node: '>=10'} hasBin: true dependencies: - is-text-path: 1.0.1 JSONStream: 1.3.5 + is-text-path: 1.0.1 lodash: 4.17.21 meow: 8.1.2 split2: 3.2.2 @@ -18827,6 +18827,12 @@ packages: /react-dev-utils/12.0.1_y75l3d5in5mgvug53qfq62ncxu: resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} engines: {node: '>=14'} + peerDependencies: + typescript: '>=2.7' + webpack: '>=4' + peerDependenciesMeta: + typescript: + optional: true dependencies: '@babel/code-frame': 7.18.6 address: 1.2.2 @@ -18857,9 +18863,7 @@ packages: transitivePeerDependencies: - eslint - supports-color - - typescript - vue-template-compiler - - webpack /react-dom/17.0.2_react@17.0.2: resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==}