Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: resolve vite errors due to using expressions in dynamic imports #7671

Merged
merged 6 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 0 additions & 19 deletions packages/calcite-components-react/src/auto-define.ts

This file was deleted.

40 changes: 27 additions & 13 deletions packages/calcite-components-react/support/patchSSR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,47 @@ const { resolve } = require("path");
// attempting to use browser APIs, which don't exist on the server.
const defineCustomElementImports = /import { defineCustomElement as defineCalcite.*(\r\n|\r|\n)/gm;

// The removed imports are replaced with autoDefine, which is a wrapper around defineCustomElement
// to make sure it's only called on the client.
const autoDefineImport = "import { autoDefine } from './auto-define';";
// The removed imports are replaced with utils that check the environment
// to make sure the components are only defined on the browser.
const browserCheckUtils = `
// CodeSandbox exposes 'process', which makes it look like NodeJS. The only way to determine it should be
// be treated as the browser is the non-standard value they use for 'process.platform'.
// https://nodejs.org/api/process.html#processplatform
type CodeSandboxWorkaround = NodeJS.Platform | "browser";

// Matches createReactComponent exports to add autoDefine instead of defineCustomElement.
// The regex creates capture groups for the component name and other parts of the line
// that shouldn't be replaced/removed.
const reactWrapperExports = /createReactComponent<(.*)>.*\((['|\w|-]*)(.*)(defineCalcite\w*)\)/g;
// https://github.com/flexdinesh/browser-or-node/blob/master/src/index.js
const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
const isNode =
typeof process !== "undefined" &&
process.versions != null &&
process.versions.node != null &&
(process?.platform as CodeSandboxWorkaround) !== "browser";`;

// The patched version of the createReactComponent export using the capture groups to fill in the blanks
const patchedReactWrapperExports = "createReactComponent<$1>($2$3autoDefine($2))";
// Matches createReactComponent exports to replace the defineCustomElement
// arguments with inlined, anonymous functions that dynamically import the
// components when in the browser. The regex creates capture groups for the
// component name and other arguments that shouldn't be replaced/removed.
const reactWrapperExports = /createReactComponent<(.*)>.*\('([\w|-]*)'(.*)(defineCalcite\w*)\)/g;

// The autoDefine import is placed below this line
const reactLibImport = "import { createReactComponent } from './react-component-lib';";
// The patched version of the createReactComponent export using capture groups to fill in the blanks.
const patchedReactWrapperExports =
"createReactComponent<$1>('$2'$3isBrowser && !isNode ? async () => (await import('@esri/calcite-components/dist/components/$2.js')).defineCustomElement() : undefined)";

// The isBrowser and isNode utils are placed below this line
const jsxTypeImport = "import type { JSX } from '@esri/calcite-components/dist/components';";

(async () => {
try {
const filePath = resolve(`${__dirname}/../src/components.ts`);
const contents = await readFile(filePath, { encoding: "utf8" });

if (contents.includes(autoDefineImport)) {
if (contents.includes("isBrowser")) {
console.log("SSR patch: skipping, components.ts is already patched");
return;
}

const patchedContents = contents
.replace(reactLibImport, `$&\n${autoDefineImport}`)
.replace(jsxTypeImport, `$&\n${browserCheckUtils}`)
.replace(defineCustomElementImports, "")
.replace(reactWrapperExports, patchedReactWrapperExports);

Expand Down