From 3ca8f6e557e8a93d9a5ab4b108e9088c47233779 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, 15 Aug 2022 16:34:32 +0800 Subject: [PATCH 01/31] Fix/forward ref input compat (#444) * fix: use forwardRef to InputCompat for pass ref * chore: modify type of ref --- packages/rax-compat/src/create-element.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/rax-compat/src/create-element.ts b/packages/rax-compat/src/create-element.ts index 43eb2d843..b77f45fd8 100644 --- a/packages/rax-compat/src/create-element.ts +++ b/packages/rax-compat/src/create-element.ts @@ -6,7 +6,7 @@ import type { RefObject, SyntheticEvent, } from 'react'; -import { createElement as _createElement, useEffect, useCallback, useRef, useState } from 'react'; +import { createElement as _createElement, useEffect, useCallback, useRef, useState, forwardRef as _forwardRef } from 'react'; import { cached, convertUnit } from 'style-unit'; import { observerElement } from './visibility'; import { isFunction, isObject, isNumber } from './type'; @@ -29,7 +29,7 @@ import { isFunction, isObject, isNumber } from './type'; const NON_DIMENSIONAL_REG = /opa|ntw|ne[ch]|ex(?:s|g|n|p|$)|^ord|zoo|grid|orp|ows|mnc|^columns$|bs|erim|onit/i; function createInputCompat(type: string) { - function InputCompat(props: any) { + function InputCompat(props: any, ref: RefObject) { const { value, onInput, ...rest } = props; const [v, setV] = useState(value); const onChange = useCallback((event: SyntheticEvent) => { @@ -43,10 +43,11 @@ function createInputCompat(type: string) { ...rest, value: v, onChange, + ref, }); } - return InputCompat; + return _forwardRef(InputCompat); } /** From 55598d04a1e5579d13bf435bdb57a9fd0539771b Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Wed, 17 Aug 2022 15:11:12 +0800 Subject: [PATCH 02/31] feat: export createStore and createModel api from ice (#445) --- examples/with-store/src/models/user.ts | 2 +- examples/with-store/src/pages/blog/models/info.ts | 2 +- examples/with-store/src/pages/blog/store.ts | 2 +- examples/with-store/src/pages/models/counter.ts | 2 +- examples/with-store/src/pages/store.ts | 2 +- examples/with-store/src/store.ts | 2 +- packages/plugin-store/src/index.ts | 9 ++++++++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/examples/with-store/src/models/user.ts b/examples/with-store/src/models/user.ts index e162baf09..041b699b2 100644 --- a/examples/with-store/src/models/user.ts +++ b/examples/with-store/src/models/user.ts @@ -1,4 +1,4 @@ -import { createModel } from '@ice/plugin-store/esm/runtime'; +import { createModel } from 'ice'; export default createModel({ state: { diff --git a/examples/with-store/src/pages/blog/models/info.ts b/examples/with-store/src/pages/blog/models/info.ts index c99ee5b20..60924a244 100644 --- a/examples/with-store/src/pages/blog/models/info.ts +++ b/examples/with-store/src/pages/blog/models/info.ts @@ -1,4 +1,4 @@ -import { createModel } from '@ice/plugin-store/esm/runtime'; +import { createModel } from 'ice'; export default createModel({ state: { diff --git a/examples/with-store/src/pages/blog/store.ts b/examples/with-store/src/pages/blog/store.ts index 4375df669..4a1f21686 100644 --- a/examples/with-store/src/pages/blog/store.ts +++ b/examples/with-store/src/pages/blog/store.ts @@ -1,4 +1,4 @@ -import { createStore } from '@ice/plugin-store/esm/runtime'; +import { createStore } from 'ice'; import info from './models/info'; export default createStore({ info }); diff --git a/examples/with-store/src/pages/models/counter.ts b/examples/with-store/src/pages/models/counter.ts index ed62a5603..d47da9565 100644 --- a/examples/with-store/src/pages/models/counter.ts +++ b/examples/with-store/src/pages/models/counter.ts @@ -1,4 +1,4 @@ -import { createModel } from '@ice/plugin-store/esm/runtime'; +import { createModel } from 'ice'; export default createModel({ state: { diff --git a/examples/with-store/src/pages/store.ts b/examples/with-store/src/pages/store.ts index 4a59915c7..fd399d4f1 100644 --- a/examples/with-store/src/pages/store.ts +++ b/examples/with-store/src/pages/store.ts @@ -1,4 +1,4 @@ -import { createStore } from '@ice/plugin-store/esm/runtime'; +import { createStore } from 'ice'; import counter from './models/counter'; const store = createStore({ counter }); diff --git a/examples/with-store/src/store.ts b/examples/with-store/src/store.ts index 5fa480991..34eafd1ac 100644 --- a/examples/with-store/src/store.ts +++ b/examples/with-store/src/store.ts @@ -1,4 +1,4 @@ -import { createStore } from '@ice/plugin-store/esm/runtime'; +import { createStore } from 'ice'; import user from './models/user'; export default createStore({ user }); diff --git a/packages/plugin-store/src/index.ts b/packages/plugin-store/src/index.ts index 0e0edf62b..373361373 100644 --- a/packages/plugin-store/src/index.ts +++ b/packages/plugin-store/src/index.ts @@ -13,7 +13,7 @@ const ignoreStoreFilePatterns = ['**/models/**', storeFilePattern]; const plugin: Plugin = (options) => ({ name: '@ice/plugin-store', - setup: ({ onGetConfig, modifyUserConfig, context: { rootDir, userConfig } }) => { + setup: ({ onGetConfig, modifyUserConfig, generator, context: { rootDir, userConfig } }) => { const { disableResetPageState = false } = options || {}; const srcDir = path.join(rootDir, 'src'); const pageDir = path.join(srcDir, 'pages'); @@ -38,6 +38,13 @@ const plugin: Plugin = (options) => ({ ]; return config; }); + + // Export store api: createStore, createModel from `.ice/index.ts`. + generator.addExport({ + specifier: ['createStore', 'createModel'], + source: '@ice/plugin-store/esm/runtime', + type: false, + }); }, runtime: path.join(path.dirname(fileURLToPath(import.meta.url)), 'runtime.js'), }); From b74ff95563c863345b7114d9322c30abf8a40817 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, 17 Aug 2022 15:13:46 +0800 Subject: [PATCH 03/31] Feat/compat maxlength (#448) * feat: compat maxlength * test: add test for maxlength * feat: move maxlength to createInputCompat --- packages/rax-compat/src/create-element.ts | 19 ++++++++++++++----- .../rax-compat/tests/createElement.test.tsx | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/packages/rax-compat/src/create-element.ts b/packages/rax-compat/src/create-element.ts index b77f45fd8..d8f0aef17 100644 --- a/packages/rax-compat/src/create-element.ts +++ b/packages/rax-compat/src/create-element.ts @@ -39,6 +39,15 @@ function createInputCompat(type: string) { onInput && onInput(event.nativeEvent); }, [onInput]); + // Compat maxlength in rax-textinput, because maxlength is invalid props in web,it will be set attributes to element + // and react will Throw a warning in DEV. + // https://github.com/raxjs/rax-components/issues/459 + // https://github.com/raxjs/rax-components/blob/master/packages/rax-textinput/src/index.tsx#L142 + if (rest.maxlength) { + rest.maxLength = rest.maxlength; + delete rest.maxlength; + } + return _createElement(type, { ...rest, value: v, @@ -82,12 +91,12 @@ export function createElement

{ const node = wrapper.queryByTestId('valueTest'); expect(node.value).toBe(str); }); + + it('input set empty string to maxlength not be 0', () => { + const str = 'hello world'; + const wrapper = render(createElement( + 'input', + { + 'data-testid': 'maxlengthTest', + value: str, + maxlength: '' + }, + )); + + const node = wrapper.queryByTestId('valueTest'); + expect(node?.getAttribute('maxlength')).toBe(null); + }); }); From 26e04850f98f392baa14515d29222ff3b8cb86cf 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, 17 Aug 2022 15:14:04 +0800 Subject: [PATCH 04/31] fix: should get eventTarget by _nativeNode (#449) --- packages/rax-compat/src/create-element.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/rax-compat/src/create-element.ts b/packages/rax-compat/src/create-element.ts index d8f0aef17..640d9747e 100644 --- a/packages/rax-compat/src/create-element.ts +++ b/packages/rax-compat/src/create-element.ts @@ -129,16 +129,19 @@ function VisibilityChange({ const listen = useCallback((eventName: string, handler: Function) => { const { current } = ref; - if (current != null) { - if (isFunction(handler)) { - observerElement(current as HTMLElement); - current.addEventListener(eventName, handler); - } + // Rax components will set custom ref by useImperativeHandle. + // So We should get eventTarget by _nativeNode. + // https://github.com/raxjs/rax-components/blob/master/packages/rax-textinput/src/index.tsx#L151 + if (current && isFunction(handler)) { + const eventTarget = current._nativeNode || current; + observerElement(eventTarget as HTMLElement); + eventTarget.addEventListener(eventName, handler); } return () => { const { current } = ref; if (current) { - current.removeEventListener(eventName, handler); + const eventTarget = current._nativeNode || current; + eventTarget.removeEventListener(eventName, handler); } }; }, [ref]); From 4d6bd3584f9b8ef46e10f0bf23b2b84f08e31022 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Thu, 18 Aug 2022 11:02:09 +0800 Subject: [PATCH 05/31] chore: remove unused constants.ts (#451) --- constants.ts | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 constants.ts diff --git a/constants.ts b/constants.ts deleted file mode 100644 index 089a034f2..000000000 --- a/constants.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const ICE_PKG_PACKAGES = [ - 'rax-compat', - 'jsx-runtime', -]; From 2fa2a482899aaa005cc2a3735efcdc71b333ce08 Mon Sep 17 00:00:00 2001 From: zkylearner <49386848+zkylearner@users.noreply.github.com> Date: Mon, 22 Aug 2022 14:30:44 +0800 Subject: [PATCH 06/31] fix: transform component name (#469) * fix: transform component name * fix: modify params name --- packages/style-import/src/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/style-import/src/index.ts b/packages/style-import/src/index.ts index ebf8e69f9..a1e2447d5 100644 --- a/packages/style-import/src/index.ts +++ b/packages/style-import/src/index.ts @@ -6,13 +6,14 @@ interface TransformOptions { libraryName: string; style: ((name: string) => string) | Boolean; sourceMap?: Boolean; + kebabCase?: Boolean; } export async function importStyle(code: string, options: TransformOptions): Promise; }> { - const { style, libraryName, sourceMap } = options; + const { style, libraryName, sourceMap, kebabCase = true } = options; if (!style) { return null; } @@ -45,7 +46,12 @@ export async function importStyle(code: string, options: TransformOptions): Prom console.log(e); return; } - exports.forEach(({ n: importName }) => { + exports.forEach(({ n }) => { + const toKebabCase = (str: string) => str.replace(/^[A-Z]/, $1 => $1.toLowerCase()).replace(/([A-Z])/g, $1 => `-${$1.toLowerCase()}`); + let importName = n; + if (kebabCase) { + importName = toKebabCase(importName); + } const stylePath = typeof style === 'function' ? style(importName) : `${libraryName}/es/${importName}/style`; if (stylePath) { styleStatements.push(`import '${stylePath}';`); From 65e4f5b302fb47604f2bb7d18d6016b9e4ce44e5 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Mon, 22 Aug 2022 15:35:45 +0800 Subject: [PATCH 07/31] fix: importStyle test case (#471) --- packages/style-import/tests/importStyle.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/style-import/tests/importStyle.test.ts b/packages/style-import/tests/importStyle.test.ts index 6ae744787..9bfdc3782 100644 --- a/packages/style-import/tests/importStyle.test.ts +++ b/packages/style-import/tests/importStyle.test.ts @@ -5,7 +5,7 @@ describe('import style', () => { it('simple import', async () => { const sourceCode = `import { Button } from 'antd';`; const result = await importStyle(sourceCode, { libraryName: 'antd', style: true }); - expect(result?.code).toBe(`${sourceCode}\nimport 'antd/es/Button/style';`); + expect(result?.code).toBe(`${sourceCode}\nimport 'antd/es/button/style';`); }); it('custom style', async () => { const sourceCode = `import { Button } from 'antd';`; @@ -20,12 +20,12 @@ describe('import style', () => { it('multiple import', async () => { const sourceCode = `import { Button, Table } from 'antd';`; const result = await importStyle(sourceCode, { libraryName: 'antd', style: true }); - expect(result?.code).toBe(`${sourceCode}\nimport 'antd/es/Button/style';\nimport 'antd/es/Table/style';`); + expect(result?.code).toBe(`${sourceCode}\nimport 'antd/es/button/style';\nimport 'antd/es/table/style';`); }); it('named import', async () => { const sourceCode = `import { Button as Btn } from 'antd';`; const result = await importStyle(sourceCode, { libraryName: 'antd', style: true }); - expect(result?.code).toBe(`${sourceCode}\nimport 'antd/es/Button/style';`); + expect(result?.code).toBe(`${sourceCode}\nimport 'antd/es/button/style';`); }); it('default import', async () => { const sourceCode = `import * as antd from 'antd';`; From f3029568d2fab0db35cdc54798ac8e9f35413648 Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Mon, 22 Aug 2022 16:15:51 +0800 Subject: [PATCH 08/31] feat: support import history from ice (#458) * feat: support import history from ice * fix: test case --- examples/basic-project/src/pages/about.tsx | 5 +++-- packages/ice/templates/core/index.ts.ejs | 1 + packages/runtime/src/history.ts | 13 +++++++++++++ packages/runtime/src/index.ts | 2 ++ packages/runtime/src/runClientApp.tsx | 3 +++ 5 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 packages/runtime/src/history.ts diff --git a/examples/basic-project/src/pages/about.tsx b/examples/basic-project/src/pages/about.tsx index 0c46fcb0f..dce5b82a5 100644 --- a/examples/basic-project/src/pages/about.tsx +++ b/examples/basic-project/src/pages/about.tsx @@ -1,4 +1,4 @@ -import { Link, useData, useConfig } from 'ice'; +import { Link, useData, useConfig, history } from 'ice'; import { isWeb } from '@uni/env'; // @ts-expect-error import url from './ice.png'; @@ -12,6 +12,7 @@ export default function About() { const config = useConfig(); console.log('render About', 'data', data, 'config', config); + console.log('history in component', history); return ( <> @@ -19,7 +20,7 @@ export default function About() { home new -

isWeb: { isWeb ? 'true' : 'false' }
+
isWeb: {isWeb ? 'true' : 'false'}
); } diff --git a/packages/ice/templates/core/index.ts.ejs b/packages/ice/templates/core/index.ts.ejs index 8dc432a46..83a75817a 100644 --- a/packages/ice/templates/core/index.ts.ejs +++ b/packages/ice/templates/core/index.ts.ejs @@ -52,6 +52,7 @@ export { Links, Scripts, Main, + history, } from '@ice/runtime'; <%- framework.imports %> diff --git a/packages/runtime/src/history.ts b/packages/runtime/src/history.ts new file mode 100644 index 000000000..b9615c745 --- /dev/null +++ b/packages/runtime/src/history.ts @@ -0,0 +1,13 @@ +import type { History } from 'history'; + +// Value of history will be modified after render Router. +let routerHistory: History | null = null; + +function setHistory(customHistory: History) { + routerHistory = customHistory; +} + +export { + routerHistory, + setHistory, +}; \ No newline at end of file diff --git a/packages/runtime/src/index.ts b/packages/runtime/src/index.ts index 5f0785ff0..728ec4ca1 100644 --- a/packages/runtime/src/index.ts +++ b/packages/runtime/src/index.ts @@ -39,6 +39,7 @@ import type { } from './types.js'; import dataLoader from './dataLoader.js'; import getAppConfig, { defineAppConfig } from './appConfig.js'; +import { routerHistory as history } from './history.js'; export { getAppConfig, @@ -68,6 +69,7 @@ export { useParamsSingle, useSearchParamsSingle, useLocationSingle, + history, }; export type { diff --git a/packages/runtime/src/runClientApp.tsx b/packages/runtime/src/runClientApp.tsx index 901753782..850e30e16 100644 --- a/packages/runtime/src/runClientApp.tsx +++ b/packages/runtime/src/runClientApp.tsx @@ -3,6 +3,7 @@ import * as ReactDOM from 'react-dom/client'; import { createHashHistory, createBrowserHistory, createMemoryHistory } from 'history'; import type { HashHistory, BrowserHistory, Action, Location, InitialEntry, MemoryHistory } from 'history'; import { createHistorySingle } from './utils/history-single.js'; +import { setHistory } from './history.js'; import Runtime from './runtime.js'; import App from './App.js'; import { AppContextProvider } from './AppContext.js'; @@ -56,6 +57,8 @@ export default async function runClientApp(options: RunClientAppOptions) { const appConfig = getAppConfig(app); const history = createHistory(appConfig, { memoryRouter, routePath }); + // Set history for import it from ice. + setHistory(history); const matches = matchRoutes( routes, From dffcace4e1ea9623f5273083f4c561670e2abee3 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Wed, 24 Aug 2022 14:47:00 +0800 Subject: [PATCH 09/31] chore: unite cache dir (#472) --- packages/ice/src/constant.ts | 2 +- packages/ice/tests/preBundleCJSDeps.test.ts | 2 +- packages/ice/tests/transformImport.test.ts | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ice/src/constant.ts b/packages/ice/src/constant.ts index bd8e59305..8feb54785 100644 --- a/packages/ice/src/constant.ts +++ b/packages/ice/src/constant.ts @@ -6,7 +6,7 @@ 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 CACHE_DIR = path.join('node_modules', RUNTIME_TMP_DIR); +export const CACHE_DIR = path.join('node_modules', '.cache'); export const BUILDIN_ESM_DEPS = [ '@ice/runtime', ]; diff --git a/packages/ice/tests/preBundleCJSDeps.test.ts b/packages/ice/tests/preBundleCJSDeps.test.ts index 611e0db37..95c4c53d3 100644 --- a/packages/ice/tests/preBundleCJSDeps.test.ts +++ b/packages/ice/tests/preBundleCJSDeps.test.ts @@ -8,7 +8,7 @@ import { scanImports } from '../src/service/analyze'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const alias = { '@': path.join(__dirname, './fixtures/scan') }; const rootDir = path.join(__dirname, './fixtures/scan'); -const cacheDir = path.join(rootDir, '.ice'); +const cacheDir = path.join(rootDir, '.cache'); it('prebundle cjs deps', async () => { const deps = await scanImports([path.join(__dirname, './fixtures/scan/app.ts')], { alias, rootDir }); diff --git a/packages/ice/tests/transformImport.test.ts b/packages/ice/tests/transformImport.test.ts index 553cfcbeb..4f5c40e2c 100644 --- a/packages/ice/tests/transformImport.test.ts +++ b/packages/ice/tests/transformImport.test.ts @@ -12,7 +12,7 @@ import { createUnplugin } from 'unplugin'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const alias = { '@': path.join(__dirname, './fixtures/scan') }; const rootDir = path.join(__dirname, './fixtures/scan'); -const cacheDir = path.join(rootDir, '.ice'); +const cacheDir = path.join(rootDir, '.cache'); const appEntry = path.join(__dirname, './fixtures/scan/app.ts'); const outdir = path.join(rootDir, 'build'); @@ -33,8 +33,8 @@ it('transform module import', async () => { ], }); const buildContent = await fse.readFile(path.join(outdir, 'app.js')); - expect(buildContent.includes(path.join(rootDir, '.ice/deps/@ice_runtime_client.js'))).toBeTruthy(); - expect(buildContent.includes(path.join(rootDir, '.ice/deps/@ice_runtime.js'))).toBeTruthy(); + expect(buildContent.includes(path.join(rootDir, '.cache/deps/@ice_runtime_client.js'))).toBeTruthy(); + expect(buildContent.includes(path.join(rootDir, '.cache/deps/@ice_runtime.js'))).toBeTruthy(); }); afterAll(async () => { From 898e94afa98f39e63578e3b8a437ee7d5ed3c7d4 Mon Sep 17 00:00:00 2001 From: luhc228 <44047106+luhc228@users.noreply.github.com> Date: Wed, 24 Aug 2022 14:56:40 +0800 Subject: [PATCH 10/31] feat: add Data component (#404) * feat: add Data component * feat: compat ssr fallback to csr * feat: support disableFallback when renderServer * chore: remove Data component --- packages/ice/templates/core/index.ts.ejs | 1 + packages/runtime/src/Document.tsx | 19 ++++++++++++++++++- packages/runtime/src/index.ts | 2 ++ packages/runtime/src/runServerApp.tsx | 7 +++++-- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/ice/templates/core/index.ts.ejs b/packages/ice/templates/core/index.ts.ejs index 83a75817a..9c9455b63 100644 --- a/packages/ice/templates/core/index.ts.ejs +++ b/packages/ice/templates/core/index.ts.ejs @@ -51,6 +51,7 @@ export { Title, Links, Scripts, + Data, Main, history, } from '@ice/runtime'; diff --git a/packages/runtime/src/Document.tsx b/packages/runtime/src/Document.tsx index 5336a20ae..65b6a5216 100644 --- a/packages/runtime/src/Document.tsx +++ b/packages/runtime/src/Document.tsx @@ -94,7 +94,10 @@ export function Scripts(props) { * disable hydration warning for CSR. * initial app data may not equal CSR result. */} -