From 896cd4888f3eb987a21055d7fdab44a327b32104 Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Tue, 19 Jul 2022 11:34:26 +0100 Subject: [PATCH] Switched to dynamically loaded external react-mobiledoc-editor package no issue - dropped the bundled `react-mobiledoc-editor` package - updated `` component to pull in editor components dynamically - added a resource function to dynamically import the external module - added `Container` and `Editor` components that read from the resource function and wrap components of the same name from the external module - added `` around the `Container` and `Editor` components so that React will show a loading state whilst the external components are still being fetched - added `` so we can show an error state if loading fails --- .../app/components/react-mobiledoc-editor.js | 89 +++++++++++++++++-- ghost/admin/ember-cli-build.js | 3 + ghost/admin/package.json | 1 - ghost/admin/vendor/shims/prop-types.js | 12 +++ ghost/admin/yarn.lock | 9 +- 5 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 ghost/admin/vendor/shims/prop-types.js diff --git a/ghost/admin/app/components/react-mobiledoc-editor.js b/ghost/admin/app/components/react-mobiledoc-editor.js index 5e8a797294..0fbadfdf2c 100644 --- a/ghost/admin/app/components/react-mobiledoc-editor.js +++ b/ghost/admin/app/components/react-mobiledoc-editor.js @@ -1,12 +1,85 @@ -import React from 'react'; -import {Container, Editor} from 'react-mobiledoc-editor'; +import React, {Suspense} from 'react'; + +class ErrorHandler extends React.Component { + state = { + hasError: false + }; + + static getDerivedStateFromError() { + return {hasError: true}; + } -export default class ReactMobiledocEditor extends React.Component { render() { - return ( - - ); + if (this.state.hasError) { + return ( +

Loading has failed. Try refreshing the browser!

+ ); + } + + return this.props.children; } } + +const fetchMobiledocEditor = function () { + let status = 'pending'; + let response; + + const fetchPackage = async () => { + if (window.ReactMobiledocEditor) { + return window.ReactMobiledocEditor; + } + + await import('https://unpkg.com/kevinansfield-react-mobiledoc-editor@~0.13.2/dist/main.js'); + return window.ReactMobiledocEditor; + }; + + const suspender = fetchPackage().then( + (res) => { + status = 'success'; + response = res; + }, + (err) => { + status = 'error'; + response = err; + } + ); + + const read = () => { + switch (status) { + case 'pending': + throw suspender; + case 'error': + throw response; + default: + return response; + } + }; + + return {read}; +}; + +const editorResource = fetchMobiledocEditor(); + +const Container = (props) => { + const MobiledocEditor = editorResource.read(); + return ; +}; + +const Editor = (props) => { + const MobiledocEditor = editorResource.read(); + return ; +}; + +export default function ReactMobiledocEditorComponent(props) { + return ( + + Loading editor...

}> + + + +
+
+ ); +} diff --git a/ghost/admin/ember-cli-build.js b/ghost/admin/ember-cli-build.js index 44870f1d36..a8e2dedf98 100644 --- a/ghost/admin/ember-cli-build.js +++ b/ghost/admin/ember-cli-build.js @@ -278,6 +278,9 @@ module.exports = function (defaults) { // support `import React from 'react'` app.import('vendor/shims/react.js'); app.import('vendor/shims/react-dom.js'); + // required dependency for dynamically fetched react-mobiledoc-editor + app.import('node_modules/prop-types/prop-types.min.js'); + app.import('vendor/shims/prop-types.js'); return app.toTree(); }; diff --git a/ghost/admin/package.json b/ghost/admin/package.json index 857e616dd8..1fc23ae60c 100644 --- a/ghost/admin/package.json +++ b/ghost/admin/package.json @@ -150,7 +150,6 @@ "pretender": "3.4.7", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-mobiledoc-editor": "^0.13.1", "reframe.js": "3.0.3", "simplemde": "https://github.com/kevinansfield/simplemde-markdown-editor.git#ghost", "testem": "3.7.0", diff --git a/ghost/admin/vendor/shims/prop-types.js b/ghost/admin/vendor/shims/prop-types.js new file mode 100644 index 0000000000..da42bcd18e --- /dev/null +++ b/ghost/admin/vendor/shims/prop-types.js @@ -0,0 +1,12 @@ +(function() { + function vendorModule() { + 'use strict'; + + return { + 'default': self['prop-types'], + __esModule: true, + }; + } + + define('prop-types', [], vendorModule); +})(); diff --git a/ghost/admin/yarn.lock b/ghost/admin/yarn.lock index 761bcfada2..60a6f64747 100644 --- a/ghost/admin/yarn.lock +++ b/ghost/admin/yarn.lock @@ -13469,7 +13469,7 @@ promise.hash.helper@^1.0.7: resolved "https://registry.yarnpkg.com/promise.hash.helper/-/promise.hash.helper-1.0.8.tgz#8c5fa0570f6f96821f52364fd72292b2c5a114f7" integrity sha512-KYcnXctWUWyVD3W3Ye0ZDuA1N8Szrh85cVCxpG6xYrOk/0CttRtYCmU30nWsUch0NuExQQ63QXvzRE6FLimZmg== -prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -13666,13 +13666,6 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-mobiledoc-editor@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/react-mobiledoc-editor/-/react-mobiledoc-editor-0.13.1.tgz#cc5f06b835efd6ba7b0e9e7b82ddcbd7b02aad9b" - integrity sha512-3H2tiTiykBjV7SmVkb+1slAtAJJygG7JD+NRNV/9wUHEDRdoOlcxCRd8BpXoFoJOrxIpaKCaQ7gWFHPWcIpldg== - dependencies: - prop-types "^15.7.2" - react@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"