thawkin3 / single-spa-demo-root-config

13 stars 10 forks source link

Uncaught Error: application '@thawkin3/single-spa-demo-nav' died in status LOADING_SOURCE_CODE: Unable to resolve bare specifier 'react' from http://localhost:9001/thawkin3-single-spa-demo-nav.js (SystemJS Error#8 #4

Open wriver1 opened 3 years ago

wriver1 commented 3 years ago

Hello Tyler, I'm following your tutorial in https://www.freecodecamp.org/news/developing-and-deploying-micro-frontends-with-single-spa/, but, I created the four apps (container app, nav, page 1 and page 2), I registered them as you show in your guide. When I go to try the microfrontends opening this URL http://localhost:9000 in the browser, it catches this error:

app-errors.js:11 Uncaught Error: application '@thawkin3/single-spa-demo-nav' died in status LOADING_SOURCE_CODE: Unable to resolve bare specifier 'react' from http://localhost:9001/thawkin3-single-spa-demo-nav.js (SystemJS Error#8 https://git.io/JvFET#8)
    at throwUnresolved (system.js:698)
    at SystemJS.systemJSPrototype.resolve (system.js:694)
    at system.js:337
    at Array.map (<anonymous>)
    at system.js:335

This is my index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Root Config</title>
  <!--
    Remove this if you only support browsers that support async/await.
    This is needed by babel to share largeish helper code for compiling async/await in older
    browsers. More information at https://github.com/single-spa/create-single-spa/issues/112
  -->
  <script src="https://cdn.jsdelivr.net/npm/regenerator-runtime@0.13.7/runtime.min.js"></script>
  <!--
    This CSP allows any SSL-enabled host and for arbitrary eval(), but you should limit these directives further to increase your app's security.
    Learn more about CSP policies at https://content-security-policy.com/#directive
  -->
  <meta http-equiv="Content-Security-Policy" content="default-src 'self' https: localhost:*; script-src 'unsafe-inline' 'unsafe-eval' https: localhost:*; connect-src https: localhost:* ws://localhost:*; style-src 'unsafe-inline' https:; object-src 'none';">
  <meta name="importmap-type" content="systemjs-importmap" />
  <!-- If you wish to turn off import-map-overrides for specific environments (prod), uncomment the line below -->
  <!-- More info at https://github.com/joeldenning/import-map-overrides/blob/master/docs/configuration.md#domain-list -->
  <!-- <meta name="import-map-overrides-domains" content="denylist:prod.example.com" /> -->

  <!-- Shared dependencies go into this import map. Your shared dependencies must be of one of the following formats:

    1. System.register (preferred when possible) - https://github.com/systemjs/systemjs/blob/master/docs/system-register.md
    2. UMD - https://github.com/umdjs/umd
    3. Global variable

    More information about shared dependencies can be found at https://single-spa.js.org/docs/recommended-setup#sharing-with-import-maps.
  -->
  <script type="systemjs-importmap">
    {
      "imports": {
        "single-spa": "https://cdn.jsdelivr.net/npm/single-spa@5.9.0/lib/system/single-spa.min.js"
      }
    }
  </script>
  <link rel="preload" href="https://cdn.jsdelivr.net/npm/single-spa@5.9.0/lib/system/single-spa.min.js" as="script">

  <!-- Add your organization's prod import map URL to this script's src  -->
  <!-- <script type="systemjs-importmap" src="/importmap.json"></script> -->

  <% if (isLocal) { %>
  <script type="systemjs-importmap">
    {
      "imports": {
        "@thawkin3/root-config": "http://localhost:9000/thawkin3-root-config.js",
        "@thawkin3/single-spa-demo-nav": "http://localhost:9001/thawkin3-single-spa-demo-nav.js",
        "@thawkin3/single-spa-demo-page-1": "http://localhost:9002/thawkin3-single-spa-demo-page-1.js",
        "@thawkin3/single-spa-demo-page-2": "http://localhost:9003/thawkin3-single-spa-demo-page-2.js"

      }
    }
  </script>
  <% } %>

  <!--
    If you need to support Angular applications, uncomment the script tag below to ensure only one instance of ZoneJS is loaded
    Learn more about why at https://single-spa.js.org/docs/ecosystem-angular/#zonejs
  -->
  <!-- <script src="https://cdn.jsdelivr.net/npm/zone.js@0.11.3/dist/zone.min.js"></script> -->

  <script src="https://cdn.jsdelivr.net/npm/import-map-overrides@2.2.0/dist/import-map-overrides.js"></script>
  <% if (isLocal) { %>
  <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/system.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/extras/amd.js"></script>
  <% } else { %>
  <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/system.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/extras/amd.min.js"></script>
  <% } %>
</head>
<body>
  <main></main>
  <script>
    System.import('@thawkin3/root-config');
  </script>
  <import-map-overrides-full show-when-local-storage="devtools" dev-libs></import-map-overrides-full>
</body>
</html>

thawkin3-root-config.js

import { registerApplication, start } from "single-spa";
import * as isActive from "./activity-functions";

registerApplication(
  "@thawkin3/single-spa-demo-nav",
  () => System.import("@thawkin3/single-spa-demo-nav"),
  isActive.nav
);

registerApplication(
  "@thawkin3/single-spa-demo-page-1",
  () => System.import("@thawkin3/single-spa-demo-page-1"),
  isActive.page1
);

registerApplication(
  "@thawkin3/single-spa-demo-page-2",
  () => System.import("@thawkin3/single-spa-demo-page-2"),
  isActive.page2
);

start();

The package.json file of the container app is:

{
  "name": "@thawkin3/single-spa-demo-nav",
  "scripts": {
    "start": "webpack serve",
    "start:standalone": "webpack serve --env standalone",
    "build": "webpack --mode=production",
    "analyze": "webpack --mode=production --env analyze",
    "lint": "eslint src --ext js,ts,tsx",
    "format": "prettier --write \"./**\"",
    "test": "cross-env BABEL_ENV=test jest",
    "watch-tests": "cross-env BABEL_ENV=test jest --watch",
    "coverage": "cross-env BABEL_ENV=test jest --coverage"
  },
  "husky": {
    "hooks": {
      "pre-commit": "pretty-quick --staged && concurrently yarn:test yarn:lint"
    }
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/plugin-transform-runtime": "^7.12.1",
    "@babel/preset-env": "^7.12.7",
    "@babel/preset-react": "^7.12.7",
    "@babel/runtime": "^7.12.5",
    "@testing-library/jest-dom": "^5.11.6",
    "@testing-library/react": "^11.2.2",
    "@types/systemjs": "^6.1.0",
    "babel-eslint": "^11.0.0-beta.2",
    "babel-jest": "^26.6.3",
    "concurrently": "^5.3.0",
    "cross-env": "^7.0.3",
    "eslint": "^7.15.0",
    "eslint-config-prettier": "^7.0.0",
    "eslint-plugin-prettier": "^3.2.0",
    "husky": "^4.3.5",
    "identity-obj-proxy": "^3.0.0",
    "jest": "^26.6.3",
    "jest-cli": "^26.6.3",
    "prettier": "^2.2.1",
    "pretty-quick": "^3.1.0",
    "single-spa-react": "^4.0.0",
    "webpack": "^5.8.0",
    "webpack-cli": "^4.2.0",
    "webpack-config-single-spa-react": "^2.0.0",
    "webpack-dev-server": "^4.0.0-beta.0",
    "webpack-merge": "^5.4.0",
    "@babel/preset-typescript": "^7.12.7",
    "typescript": "^4.1.2",
    "webpack-config-single-spa-ts": "^2.0.0",
    "ts-config-single-spa": "^2.0.0",
    "eslint-config-ts-react-important-stuff": "^3.0.0",
    "webpack-config-single-spa-react-ts": "^2.0.0"
  },
  "dependencies": {
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "@types/jest": "^26.0.16",
    "@types/systemjs": "^6.1.0",
    "@types/webpack-env": "^1.16.0",
    "@types/react": "^16.9.32",
    "@types/react-dom": "^16.9.6"
  }
}

finally, activity-function.js

export function prefix(location, ...prefixes) {
    return prefixes.some(
        prefix => location.href.indexOf(`${location.origin}/${prefix}`) !== -1
    );
}

export function nav() {
    // The nav is always active
    return true;
}

export function page1(location) {
    return prefix(location, 'page1');
}

export function page2(location) {
    return prefix(location, 'page2');
}
ChirayyuS commented 2 years ago

@wriver1 were you able to find the solution?

thawkin3 commented 2 years ago

I've only looked into this for a couple minutes, but here are some suggestions:

  1. You're using single-spa-react v4.x, but in my package.json file you can see that I'm using v2.x. If you're just trying to follow my tutorial, I'd recommend using the exact versions that I used. Otherwise, if you want to try with the latest version of the package, I'd recommend looking at the breaking changes in v3 and v4, and that should tell you how to fix your issue so that your code is compatible with the newer version.
  2. Related, the error message is telling you that it can't find react. That probably means you need to include a React bundle in your import map. Perhaps this is one of the breaking changes in single-spa-react v3 or v4.