Overview
Drupal Canvas provides several utilities, a FormattedText component, and autoconfigured @drupal-api-client/json-api-client and next-image-standalone packages for use in code components. Currently these are not really possible to be used outside of Canvas in a React codebase used with @drupal-canvas/cli to develop Canvas components.
Proposed resolution
Extract those elements to a separate package that can be used both in Canvas and outside it in a React codebase.
- Add a new package under
packages/drupal-canvawhich will be publish asdrupal-canvas. - The following elements should be moved from ui/lib/astro-hydration/src/lib to the new package and, if needed, adapted to work also outside Canvas:
@/lib/drupal-utils@/lib/FormattedText@/lib/jsonapi-utils@/lib/utils@drupal-api-client/json-api-client
The automatic configuration of the client will need to be adapted to also work outside Canvas in a React codebase. The client should know how to connect to a Drupal site so lists can be built locally. The base URL can be read from the environment variable that would be set up for the CLI tool. The tricky part is exposing the jsonapi.base_path service parameter. See how it was done in a browser context #3536124: Configure Drupal API Client automatically for code components.next-image-standalone
The image component in context outside Canvas should provide a loader that just returns the same image URL/path without any optimization. Trying to optimize example images from component.yml files might need #3559717: Image SDC does not generate srcset attribute for example images to work first, though that is for SDCs, but maybe it’s a similar challenge under the hood.
The package should provide named exports from the main file to allow for import autocompletion and provide a single package to import from (e.g.
import { Image, JsonApiClient } from 'drupal-canvas') but also still provide separate exports compatible with the current ones to allow for maintaining backward-compatible import map entries (e.g.import Image from 'next-image-standalone'orimport { JsonApiClient } from '@drupal-api-client/json-api-client';that can be mapped using the import map toimport Image from 'drupal-canvas/next-image-standalone'orimport { JsonApiClient } from 'drupal-canvas/json-api-client'). - Add the new package as a dependency of
@drupal-canvas/uiand update the import map (1, 2) to point existing entries to the new package and add a new entry for the package itself. - Update user documentation on packages, data fetching, and responsive images to include information about the new package and use it in code examples.
- Update
component-importsrule in the@drupal-canvas/eslint-configto:- allow imports from the new package,
- and to warn about existing import specifiers being deprecated in favor of the new package.
Issue fork canvas-3560419
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
wotnakComment #4
wotnakMost moved utils worked as is. The image loader already had a fallback to the original URL.
When it comes to JsonApiClient, getting autoconfiguration working outside Drupal Canvas in a local React codebase wasn't really possible without changes to specific dev env. To allow developing components using JSONAPI in a local dev env I settled on creating a Vite plugin that, based on env variables (CLI's
CANVAS_SITE_URLand additional optionalCANVAS_JSONAPI_PREFIX), injectsdrupalSettings.canvasDatavariables that JsonApiClient uses for autoconfiguration. The plugin also configures resolving of the@/components/alias based on CLI'sCANVAS_COMPONENT_DIRenv variable.@drupal-canvas/eslint-configcomponent-imports rule was updated to also, when possible, provide automatic fixes for imports of elements moved into thedrupal-canvaspackage.drupal-canvaspackage is now a dependency ofui/lib/astro-hydration, so npm workspaces configuration had to be changed.astro-hydrationwas added to the root workspace and removed from theuiworkspace.If in the future we will want to add
uito the root workspace, it will be a more complicated process. NPM cli has problems with installing dependencies of workspace packages when they are nested inside each other (likeastro-hydrationis insideui) and the UI build job in GitLab CI saves node_modules as an artifact, but the root node_modules dir with ui dependencies included is currently too big, and GitLab hits the size limit when trying to save it as a job artifact.Since
tsup(used for building other packages included in the repo) is no longer actively maintained (https://github.com/egoist/tsup#readme), I used tsdown for building the new packages.Comment #6
balintbrews