decaporg / decap-cms

A Git-based CMS for Static Site Generators
https://decapcms.org
MIT License
17.9k stars 3.04k forks source link

When using netlify-cms as npm module peer requirements are included #1715

Closed richtera closed 4 years ago

richtera commented 6 years ago

Describe the bug

When trying to use the custom mounting of the netlify-cms with the most recent code. There is a problem the way require is handled. The netlify-cms.js and cms.js compiles include all peer dependencies rather than declaring them as peer and requiring them.

When using something like this to mount the cms:

/** @format */

import React from "react";
import _ from "lodash";
import { identity } from "../apollo/initApollo";

import { questionStyles } from "../../components/Question";
import { appStyles } from "../../pages/_app";
import MetadataControl from "../../components/MetadataControl";
import ActivityPreview from "../../components/ActivityPreview";
import PagePreview from "../../components/PagePreview";
import registerIdControl from "../../components/IdControl";

if (process.browser) {
  window.CMS_MANUAL_INIT = true;
  window.netlifyIdentity = identity;
}

function resolveScopedStyles(scope) {
  return {
    className: scope.props.className,
    styles: scope.props.children
  };
}

const styles = resolveScopedStyles(
  <React.Fragment>
    <style jsx global>
      {`
        /* This is used for previewing content in the cms not sure why nc- got lost */
        .nc-widgetPreview p {
          margin: 1em 0px !important;
        }

        /* Hack to display Coursebuilder */
        h1.nc-collectionPage-sidebarHeading:after {
          content: "Coursebuilder";
          font-size: 23px;
        }
        h1.nc-collectionPage-sidebarHeading {
          font-size: 0;
        }
      `}
    </style>
    {questionStyles()}
    {appStyles()}
  </React.Fragment>
);

let MarkdownPreview = null;
let CMS = null;
export class CMSContainer extends React.Component {
  componentWillMount() {
    if (process.browser) {
      const { init, default: CMSImport } = require("netlify-cms/dist/netlify-cms.js");

      CMS = CMSImport;

      const backend = JSON.parse(process.env.CMS_BACKEND);
      init({
        config: {
          display_url: window.location.href.replace(
            /(^https?:\/\/[^\/]*)(\/.*)?$/,
            (all, url) => url
          ),
          backend
        }
      });
      _.forEach(styles.styles, style => {
        const styles = style.props.css;
        CMS.registerPreviewStyle(styles, { raw: true });
      });
      CMS.registerPreviewStyle(
        "//fonts.googleapis.com/icon?family=Material+Icons"
      );
      CMS.registerPreviewTemplate("activity", ActivityPreview);
      CMS.registerPreviewTemplate("page", PagePreview);
      CMS.registerPreviewTemplate("article", PagePreview);
      CMS.registerWidget("metadata", MetadataControl);
      registerIdControl(CMS);
    }
  }

  render() {
    return (
      <React.Fragment>
        <div id="nc-root" key="cms" />
        {styles.styles}
      </React.Fragment>
    );
  }
}

export default CMSContainer;

it causes multiple versions of the peer dependencies to be loaded (for example "react".) This causes various problems inside of the cms and outside of the cms in the mounting application.

To Reproduce

Use the above kind of view within a react application to boot up the CMS.

Expected behavior This should work normally.

Screenshots Errors like:

Failed to load entries: Invariant Violation: Minified React error #254; visit https://reactjs.org/docs/error-decoder.html?invariant=254&args[]=question_0_0 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.

Applicable Versions:

CMS configuration I can provide in private.

Additional context It seems that the dist/netlify-cms.js is built with a CDN deploy in mind rather than for use as a normal npm module. I am thinking the default package.json main modules should not include peer dependencies but the dist/.js should. I am trying to make a PR.

erquhart commented 5 years ago

As mentioned in #1718, the CMS will always includes it's own peer dependencies - there's no reason that I'm aware of to avoid this. What we do need is for the core to load a set of dependencies that can then be shared by all extensions. Rather than satisfying this by introducing a new package, netlify-cms-core should be outputting multiple builds, along with a global object of dependencies for consumers that use a script tag.

lukeburns commented 5 years ago

The CMS preview seems to break for react components that rely on reactDOM.findDOMNode (e.g. reactstrap components that use react-transition-group), which I suspect is due to the presence of multiple versions of React: https://github.com/Pomax/react-onclickoutside/issues/231#issuecomment-333174275.

erquhart commented 5 years ago

The preview pane code runs in an iframe, so shouldn't be an issue there.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

erquhart commented 4 years ago

netlify-cms-app can be used for applications that want to provide their own copy of React.