diff --git a/.gitignore b/.gitignore index b9eb951cc9..ddbdfc283b 100644 --- a/.gitignore +++ b/.gitignore @@ -35,6 +35,7 @@ yalc.lock # IDE .idea/ +.vscode/ # TypeScript *.tsbuildinfo diff --git a/CHANGELOG.md b/CHANGELOG.md index 4737eefe5d..c38f22442c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Changes since the last non-beta release. #### Fixed - Fix obscure errors by introducing FULL_TEXT_ERRORS [PR 1695](https://github.com/shakacode/react_on_rails/pull/1695) by [Romex91](https://github.com/Romex91). +- Remove server-side-only functions from client bundles [PR 1697](https://github.com/shakacode/react_on_rails/pull/1697) by [Romex91](https://github.com/Romex91). ### [14.1.1] - 2025-01-15 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 02602be7a4..7550a5e29d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ * After updating code via Git, to prepare all examples: ```sh cd react_on_rails/ -bundle && yarn && rake examples:gen_all && rake node_package && rake +bundle && yarn && rake shakapacker_examples:gen_all && rake node_package && rake ``` See [Dev Initial Setup](#dev-initial-setup) below for, well... initial setup, diff --git a/knip.ts b/knip.ts index dc4c2efe80..5e97a8a22d 100644 --- a/knip.ts +++ b/knip.ts @@ -4,7 +4,7 @@ const config: KnipConfig = { // ! at the end means files are used in production workspaces: { '.': { - entry: ['node_package/src/ReactOnRails.ts!', 'node_package/src/ReactOnRails.node.ts!'], + entry: ['node_package/src/ReactOnRails.node.ts!'], project: ['node_package/src/**/*.[jt]s!', 'node_package/tests/**/*.[jt]s'], babel: { config: ['node_package/babel.config.js'], diff --git a/node_package/src/ReactOnRails.ts b/node_package/src/ReactOnRails.client.ts similarity index 96% rename from node_package/src/ReactOnRails.ts rename to node_package/src/ReactOnRails.client.ts index 91e5ffcac2..5e4e248c92 100644 --- a/node_package/src/ReactOnRails.ts +++ b/node_package/src/ReactOnRails.client.ts @@ -1,20 +1,16 @@ import type { ReactElement } from 'react'; import * as ClientStartup from './clientStartup'; -import handleError from './handleError'; import ComponentRegistry from './ComponentRegistry'; import StoreRegistry from './StoreRegistry'; -import serverRenderReactComponent from './serverRenderReactComponent'; import buildConsoleReplay from './buildConsoleReplay'; import createReactOutput from './createReactOutput'; import Authenticity from './Authenticity'; import context from './context'; import type { RegisteredComponent, - RenderParams, RenderResult, RenderReturnType, - ErrorOptions, ReactComponentOrRenderFunction, AuthenticityHeaders, Store, @@ -243,8 +239,8 @@ ctx.ReactOnRails = { * Used by server rendering by Rails * @param options */ - serverRenderReactComponent(options: RenderParams): null | string | Promise { - return serverRenderReactComponent(options); + serverRenderReactComponent(): null | string | Promise { + throw new Error('serverRenderReactComponent is not available in "react-on-rails.client". Import "react-on-rails" server-side.'); }, /** @@ -259,8 +255,8 @@ ctx.ReactOnRails = { * Used by Rails to catch errors in rendering * @param options */ - handleError(options: ErrorOptions): string | undefined { - return handleError(options); + handleError(): string | undefined { + throw new Error('handleError is not available in "react-on-rails.client". Import "react-on-rails" server-side.'); }, /** diff --git a/node_package/src/ReactOnRails.node.ts b/node_package/src/ReactOnRails.node.ts index fea963ca05..811b8ca9c4 100644 --- a/node_package/src/ReactOnRails.node.ts +++ b/node_package/src/ReactOnRails.node.ts @@ -1,7 +1,7 @@ -import ReactOnRails from './ReactOnRails'; +import ReactOnRails from './ReactOnRails.server'; import streamServerRenderedReactComponent from './streamServerRenderedReactComponent'; ReactOnRails.streamServerRenderedReactComponent = streamServerRenderedReactComponent; -export * from './ReactOnRails'; -export { default } from './ReactOnRails'; +export * from './ReactOnRails.server'; +export { default } from './ReactOnRails.server'; diff --git a/node_package/src/ReactOnRails.server.ts b/node_package/src/ReactOnRails.server.ts new file mode 100644 index 0000000000..bd9f45303b --- /dev/null +++ b/node_package/src/ReactOnRails.server.ts @@ -0,0 +1,14 @@ +import handleError from './handleError'; +import serverRenderReactComponent from './serverRenderReactComponent'; + +import ReactOnRails from './ReactOnRails.client'; + +if (typeof window !== 'undefined') { + console.log("This file shouldn't be loaded in the client. If your Webpack target is 'web' (default), add 'server' to 'resolve.conditionNames'."); +} + +ReactOnRails.handleError = handleError; +ReactOnRails.serverRenderReactComponent = serverRenderReactComponent; + +export * from "./types"; +export default ReactOnRails; diff --git a/node_package/src/types/index.ts b/node_package/src/types/index.ts index 597355d9dd..8d61f1eb44 100644 --- a/node_package/src/types/index.ts +++ b/node_package/src/types/index.ts @@ -47,23 +47,23 @@ type RenderFunctionResult = ReactComponent | ServerRenderResult | Promise { ... }; - * + * * // Option 2: Using renderFunction property * const anotherRenderFunction = (props) => { ... }; * anotherRenderFunction.renderFunction = true; @@ -82,7 +82,6 @@ export type { // eslint-disable-line import/prefer-default-export ReactComponent, AuthenticityHeaders, RenderFunction, - RenderFunctionResult, Store, StoreGenerator, CreateReactOutputResult, @@ -131,7 +130,7 @@ export interface ErrorOptions { serverSide: boolean; } -export type RenderingError = Pick; +type RenderingError = Pick; export interface RenderResult { html: string | null; diff --git a/node_package/tests/Authenticity.test.js b/node_package/tests/Authenticity.test.js index 551a9ecc4a..120a76249d 100644 --- a/node_package/tests/Authenticity.test.js +++ b/node_package/tests/Authenticity.test.js @@ -1,4 +1,4 @@ -import ReactOnRails from '../src/ReactOnRails'; +import ReactOnRails from '../src/ReactOnRails.client'; const testToken = 'TEST_CSRF_TOKEN'; diff --git a/node_package/tests/ReactOnRails.test.js b/node_package/tests/ReactOnRails.test.js index afa6f4c271..731cc8cb55 100644 --- a/node_package/tests/ReactOnRails.test.js +++ b/node_package/tests/ReactOnRails.test.js @@ -6,7 +6,7 @@ import { createStore } from 'redux'; import React from 'react'; import createReactClass from 'create-react-class'; -import ReactOnRails from '../src/ReactOnRails'; +import ReactOnRails from '../src/ReactOnRails.client'; describe('ReactOnRails', () => { expect.assertions(14); diff --git a/package-scripts.yml b/package-scripts.yml index 315c37a70f..e3a07ca77d 100644 --- a/package-scripts.yml +++ b/package-scripts.yml @@ -25,9 +25,9 @@ scripts: # 3. Check if the project is built now; # 4. If it failed, print an error message (still follow https://docs.npmjs.com/cli/v8/using-npm/scripts#best-practices). script: > - [ -f node_package/lib/ReactOnRails.js ] || + [ -f node_package/lib/ReactOnRails.server.js ] || (npm run build >/dev/null 2>&1 || true) && - [ -f node_package/lib/ReactOnRails.js ] || + [ -f node_package/lib/ReactOnRails.server.js ] || { echo 'Building react-on-rails seems to have failed!'; } format: diff --git a/package.json b/package.json index 1666161967..92c10a1221 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,10 @@ "exports": { ".": { "node": "./node_package/lib/ReactOnRails.node.js", - "default": "./node_package/lib/ReactOnRails.js" + "react-server": "./node_package/lib/ReactOnRails.server.js", + "server": "./node_package/lib/ReactOnRails.server.js", + "browser": "./node_package/lib/ReactOnRails.client.js", + "default": "./node_package/lib/ReactOnRails.server.js" } }, "directories": { diff --git a/spec/dummy/config/webpack/serverWebpackConfig.js b/spec/dummy/config/webpack/serverWebpackConfig.js index b64a616a60..b4e46c2f2d 100644 --- a/spec/dummy/config/webpack/serverWebpackConfig.js +++ b/spec/dummy/config/webpack/serverWebpackConfig.js @@ -109,6 +109,15 @@ const configureServer = () => { // If using the React on Rails Pro node server renderer, uncomment the next line // serverWebpackConfig.target = 'node' + // Needed to load the server version of ReactOnRails (see "exports" in /package.json). + // Implied by serverWebpackConfig.target = 'node' and can be removed you use the Node renderer. + if (serverWebpackConfig.resolve.conditionNames !== undefined) { + serverWebpackConfig.resolve.conditionNames.unshift('server'); + } else { + // '...' uses the default conditions + serverWebpackConfig.resolve.conditionNames = ['server', '...']; + } + return serverWebpackConfig; }; diff --git a/tsconfig.json b/tsconfig.json index a98ac818ff..9ace43ac95 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,13 +3,13 @@ "allowJs": true, "esModuleInterop": true, "jsx": "react-jsx", - "lib": ["dom", "es2015"], - "module": "CommonJS", + "lib": ["dom", "es2020"], + "module": "node16", "noImplicitAny": true, "outDir": "node_package/lib", "strict": true, "incremental": true, - "target": "es5" + "target": "es2020" }, "include": ["node_package/src/**/*"] }