From c78c297f7760c71af6d4cab21ed20e5cffbcb5dd Mon Sep 17 00:00:00 2001 From: Graham Mendick Date: Sat, 11 Jan 2025 12:13:16 +0000 Subject: [PATCH] Stopped bundling navigation react Can't bundle navigation react and support 'use client'. Bundling puts all components into a single file but 'use client' needs to be applied at the file level. So switched the package task of navigation react to transpile using typescript instead of bundle using rollup. Kept rollup for all other libraries and tasks. Without bundling typescript puts some helper stuff at the top of each file - it used appear just once when it was one big file. To keep this to a minimum removed 'import * as React from 'react';' - this isn't needed anymore because react/typescript adds 'react/jsx-runtime'. Removing this removes the importStar typescript helper stuff. Don't want to 'importHelpers' because then dependent on tslib and don't want any 3rd party dependencies. This stopped the build task from working because it didn't recognise 'react/jsx-runtime'. So added it as an external but there is no umd build for it so the index.html sample won't work anymore. But noticed that [react doesn't support umd builds anymore](https://github.com/facebook/react/pull/28735#issuecomment-2036072578) anyway so will either ditch the build task and index.html sample or switch to esm?! will investigate later. Haven't tried the unbundled navigation react package but the files are generated at least --- .gitignore | 2 +- NavigationReact/src/FluentLink.tsx | 2 +- NavigationReact/src/NavigationBackLink.tsx | 4 +- NavigationReact/src/NavigationContext.ts | 4 +- NavigationReact/src/NavigationHandler.tsx | 5 +- NavigationReact/src/NavigationLink.tsx | 1 - NavigationReact/src/NavigationReact.server.ts | 10 ++ NavigationReact/src/RefreshLink.tsx | 4 +- NavigationReact/src/SceneRSCView.ts | 1 - NavigationReact/src/SceneView.server.tsx | 1 - NavigationReact/src/SceneView.ts | 2 +- NavigationReact/src/tsconfig.json | 2 +- NavigationReact/src/withStateNavigator.tsx | 4 +- build/npm/navigation-react/package.json | 14 +- gulpfile.js | 21 ++- package-lock.json | 163 ++++++++++++++++++ package.json | 1 + 17 files changed, 219 insertions(+), 22 deletions(-) create mode 100644 NavigationReact/src/NavigationReact.server.ts diff --git a/.gitignore b/.gitignore index da26f5cf13..d3dbd90161 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ build/dist -build/npm/**/navigation*.js +build/npm/**/*.js build/npm/**/android build/npm/**/ios build/npm/**/cpp diff --git a/NavigationReact/src/FluentLink.tsx b/NavigationReact/src/FluentLink.tsx index 9224cb4cac..14c7a57f93 100644 --- a/NavigationReact/src/FluentLink.tsx +++ b/NavigationReact/src/FluentLink.tsx @@ -1,7 +1,7 @@ +'use client' import LinkUtility from './LinkUtility'; import withStateNavigator from './withStateNavigator'; import { FluentLinkProps } from './Props'; -import * as React from 'react'; var FluentLink = (props: FluentLinkProps) => { var htmlProps = LinkUtility.toHtmlProps(props); diff --git a/NavigationReact/src/NavigationBackLink.tsx b/NavigationReact/src/NavigationBackLink.tsx index c02c50f361..67e2c42145 100644 --- a/NavigationReact/src/NavigationBackLink.tsx +++ b/NavigationReact/src/NavigationBackLink.tsx @@ -1,7 +1,7 @@ -import LinkUtility from './LinkUtility'; +'use client' +import LinkUtility from './LinkUtility'; import withStateNavigator from './withStateNavigator'; import { NavigationBackLinkProps } from './Props'; -import * as React from 'react'; var NavigationBackLink = (props: NavigationBackLinkProps) => { var htmlProps = LinkUtility.toHtmlProps(props); diff --git a/NavigationReact/src/NavigationContext.ts b/NavigationReact/src/NavigationContext.ts index 7f3da150cb..b2fea79008 100644 --- a/NavigationReact/src/NavigationContext.ts +++ b/NavigationReact/src/NavigationContext.ts @@ -1,4 +1,4 @@ +import { createContext } from 'react'; import { StateNavigator } from 'navigation'; -import * as React from 'react'; -export default React.createContext({ oldState: null, state: null, data: {}, stateNavigator: new StateNavigator() }); +export default createContext({ oldState: null, state: null, data: {}, stateNavigator: new StateNavigator() }); diff --git a/NavigationReact/src/NavigationHandler.tsx b/NavigationReact/src/NavigationHandler.tsx index ebe4e7b938..4638301a61 100644 --- a/NavigationReact/src/NavigationHandler.tsx +++ b/NavigationReact/src/NavigationHandler.tsx @@ -1,10 +1,11 @@ +'use client' +import { Component } from 'react'; import AsyncStateNavigator from './AsyncStateNavigator'; import NavigationContext from './NavigationContext'; import { StateNavigator, State } from 'navigation'; -import * as React from 'react'; type NavigationHandlerState = { context: { oldState: State, state: State, data: any, asyncData: any, stateNavigator: AsyncStateNavigator } }; -class NavigationHandler extends React.Component<{ stateNavigator: StateNavigator, children: any }, NavigationHandlerState> { +class NavigationHandler extends Component<{ stateNavigator: StateNavigator, children: any }, NavigationHandlerState> { constructor(props) { super(props); var { stateNavigator } = this.props; diff --git a/NavigationReact/src/NavigationLink.tsx b/NavigationReact/src/NavigationLink.tsx index 4f55d869d8..a5018a9607 100644 --- a/NavigationReact/src/NavigationLink.tsx +++ b/NavigationReact/src/NavigationLink.tsx @@ -2,7 +2,6 @@ import LinkUtility from './LinkUtility'; import withStateNavigator from './withStateNavigator'; import { NavigationLinkProps } from './Props'; -import * as React from 'react'; var NavigationLink = (props: NavigationLinkProps) => { var htmlProps = LinkUtility.toHtmlProps(props); diff --git a/NavigationReact/src/NavigationReact.server.ts b/NavigationReact/src/NavigationReact.server.ts new file mode 100644 index 0000000000..1da4597e09 --- /dev/null +++ b/NavigationReact/src/NavigationReact.server.ts @@ -0,0 +1,10 @@ +import AsyncStateNavigator from './AsyncStateNavigator'; +import NavigationContext from './NavigationContext.server'; +import NavigationHandler from './NavigationHandler'; +import NavigationBackLink from './NavigationBackLink'; +import NavigationLink from './NavigationLink'; +import RefreshLink from './RefreshLink'; +import FluentLink from './FluentLink'; +import SceneView from './SceneView.server'; + +export { AsyncStateNavigator, NavigationContext, NavigationHandler, NavigationBackLink, NavigationLink, RefreshLink, FluentLink, SceneView }; diff --git a/NavigationReact/src/RefreshLink.tsx b/NavigationReact/src/RefreshLink.tsx index 3f1987def6..f37dc34d8f 100644 --- a/NavigationReact/src/RefreshLink.tsx +++ b/NavigationReact/src/RefreshLink.tsx @@ -1,7 +1,7 @@ -import LinkUtility from './LinkUtility'; +'use client' +import LinkUtility from './LinkUtility'; import withStateNavigator from './withStateNavigator'; import { RefreshLinkProps } from './Props'; -import * as React from 'react'; var RefreshLink = (props: RefreshLinkProps) => { var htmlProps = LinkUtility.toHtmlProps(props); diff --git a/NavigationReact/src/SceneRSCView.ts b/NavigationReact/src/SceneRSCView.ts index 05c369602b..c841da23f3 100644 --- a/NavigationReact/src/SceneRSCView.ts +++ b/NavigationReact/src/SceneRSCView.ts @@ -1,4 +1,3 @@ - const SceneRSCView = ({children}) => children; export default SceneRSCView; diff --git a/NavigationReact/src/SceneView.server.tsx b/NavigationReact/src/SceneView.server.tsx index 904032ce71..42094881ba 100644 --- a/NavigationReact/src/SceneView.server.tsx +++ b/NavigationReact/src/SceneView.server.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { SceneViewProps } from './Props'; import useNavigationEvent from './useNavigationEvent'; import SceneRSCView from './SceneRSCView'; diff --git a/NavigationReact/src/SceneView.ts b/NavigationReact/src/SceneView.ts index 8284160478..52f4aea557 100644 --- a/NavigationReact/src/SceneView.ts +++ b/NavigationReact/src/SceneView.ts @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import { useContext } from 'react'; import NavigationContext from './NavigationContext'; import { SceneViewProps } from './Props'; diff --git a/NavigationReact/src/tsconfig.json b/NavigationReact/src/tsconfig.json index bc36ad64fc..81cdef2354 100644 --- a/NavigationReact/src/tsconfig.json +++ b/NavigationReact/src/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "es5", - "jsx": "react", + "jsx": "react-jsx", "esModuleInterop": true, "baseUrl": "../../types" } diff --git a/NavigationReact/src/withStateNavigator.tsx b/NavigationReact/src/withStateNavigator.tsx index aeef2678d5..f02bf634e8 100644 --- a/NavigationReact/src/withStateNavigator.tsx +++ b/NavigationReact/src/withStateNavigator.tsx @@ -1,8 +1,8 @@ import NavigationContext from './NavigationContext'; -import * as React from 'react'; +import { ComponentType } from 'react'; import { LinkProps } from './Props'; -export default (Link: React.ComponentType) => (props: T) => ( +export default (Link: ComponentType) => (props: T) => ( {({ stateNavigator }) => } diff --git a/build/npm/navigation-react/package.json b/build/npm/navigation-react/package.json index 901af204c0..f55cd6a9bd 100644 --- a/build/npm/navigation-react/package.json +++ b/build/npm/navigation-react/package.json @@ -2,12 +2,24 @@ "name": "navigation-react", "version": "4.5.1", "description": "React plugin for the Navigation router", - "main": "navigation.react.js", + "main": "NavigationReact.js", "types": "navigation.react.d.ts", "repository": { "type": "git", "url": "git+https://github.com/grahammendick/navigation.git" }, + "exports": { + ".": { + "react-server": { + "browser": "./NavigationReact.server.js", + "node": "./NavigationReact.server.js" + }, + "default": { + "browser": "./NavigationReact.js", + "node": "./NavigationReact.js" + } + } + }, "keywords": [ "router", "navigation", diff --git a/gulpfile.js b/gulpfile.js index b2dd0110f7..5707bc940b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,6 +9,7 @@ var rename = require('gulp-rename'); var rollup = require('rollup'); var sucrase = require('@rollup/plugin-sucrase'); var terser = require('gulp-terser'); +var ts = require('gulp-typescript'); var typescript = require('@rollup/plugin-typescript'); events.EventEmitter.defaultMaxListeners = 0; @@ -16,7 +17,7 @@ events.EventEmitter.defaultMaxListeners = 0; var items = [ require('./build/npm/navigation/package.json'), Object.assign({ globals: { navigation: 'Navigation', react: 'React', - 'react-dom': 'ReactDOM' } }, + 'react-dom': 'ReactDOM', 'react/jsx-runtime': '_jsx' } }, require('./build/npm/navigation-react/package.json')), Object.assign({ globals: { navigation: 'Navigation', 'navigation-react': 'NavigationReact', react: 'React' } }, @@ -97,9 +98,21 @@ var itemTasks = items.reduce((tasks, item) => { var { globals = {}, format = 'cjs' } = item; tasks.buildTasks.push( nameFunc(() => buildTask(name, tsFrom, jsTo, globals, item), 'build' + name)); - tasks.packageTasks.push( - nameFunc(() => rollupTask(name, tsFrom, jsPackageTo, globals, format), 'package' + name) - ); + if (!item.exports) { + tasks.packageTasks.push( + nameFunc(() => rollupTask(name, tsFrom, jsPackageTo, globals, format), 'package' + name) + ); + } else { + var include = tsFrom.replace(name + '.ts', '**/*.{ts,tsx}'); + var tsconfig = tsFrom.replace(name + '.ts', 'tsconfig.json'); + tasks.packageTasks.push( + nameFunc(() => ( + src(include) + .pipe(ts.createProject(tsconfig)()) + .pipe(dest(`./build/npm/${packageName}`)) + ), 'package' + name) + ); + } return tasks; }, { buildTasks: [], packageTasks: [] }); diff --git a/package-lock.json b/package-lock.json index 8a3933b62a..05a5b7a2ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "gulp-mocha": "^8.0.0", "gulp-rename": "^1.2.3", "gulp-terser": "^1.2.0", + "gulp-typescript": "^6.0.0-alpha.1", "jsdom": "^25.0.1", "navigation": "file:build/npm/navigation", "navigation-react": "file:build/npm/navigation-react", @@ -6421,6 +6422,104 @@ "readable-stream": "2 || 3" } }, + "node_modules/gulp-typescript": { + "version": "6.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-6.0.0-alpha.1.tgz", + "integrity": "sha512-KoT0TTfjfT7w3JItHkgFH1T/zK4oXWC+a8xxKfniRfVcA0Fa1bKrIhztYelYmb+95RB80OLMBreknYkdwzdi2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1", + "plugin-error": "^1.0.1", + "source-map": "^0.7.3", + "through2": "^3.0.1", + "vinyl": "^2.2.0", + "vinyl-fs": "^3.0.3" + }, + "engines": { + "node": ">= 8" + }, + "peerDependencies": { + "typescript": "~2.7.1 || >=2.8.0-dev || >=2.9.0-dev || ~3.0.0 || >=3.0.0-dev || >=3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev " + } + }, + "node_modules/gulp-typescript/node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/gulp-typescript/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gulp-typescript/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/gulp-typescript/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/gulp-typescript/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/gulp-typescript/node_modules/through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, "node_modules/gulplog": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", @@ -17918,6 +18017,70 @@ } } }, + "gulp-typescript": { + "version": "6.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/gulp-typescript/-/gulp-typescript-6.0.0-alpha.1.tgz", + "integrity": "sha512-KoT0TTfjfT7w3JItHkgFH1T/zK4oXWC+a8xxKfniRfVcA0Fa1bKrIhztYelYmb+95RB80OLMBreknYkdwzdi2Q==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1", + "plugin-error": "^1.0.1", + "source-map": "^0.7.3", + "through2": "^3.0.1", + "vinyl": "^2.2.0", + "vinyl-fs": "^3.0.3" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + } + } + }, "gulplog": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", diff --git a/package.json b/package.json index db8afbdd07..222947ea5b 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "gulp-mocha": "^8.0.0", "gulp-rename": "^1.2.3", "gulp-terser": "^1.2.0", + "gulp-typescript": "^6.0.0-alpha.1", "jsdom": "^25.0.1", "navigation": "file:build/npm/navigation", "navigation-react": "file:build/npm/navigation-react",