이어서 할 곳

GitHub - fc-micro-frontends/career-up at step21

REACT_APP_AUTH0_DOMAIN=dev-vcrmf0xuep020tri.us.auth0.com
REACT_APP_AUTH0_CLIENT_ID=27LLb4I9cIjiiQNSjbNIX9sQM1KECUfk
REACT_APP_AUTH0_CALLBACK_URL=http://localhost:3000
REACT_APP_MICROAPP_POSTING=http://localhost:3001
REACT_APP_MICROAPP_EDU=http://localhost:3002
REACT_APP_MICROAPP_NETWORK=http://localhost:3003
REACT_APP_MICROAPP_JOB=http://localhost:3004
REACT_APP_FRAGMENT_RECOMMEND_CONNECTIONS=http://localhost:5001
REACT_APP_SERVER_URL=http://localhost:4000
➜ pnpm i

➜ pnpm build

공통 컴포넌트인 Profile 컴포넌트를 ui-kit 으로 이동

➜ pnpm --filter @career-up/ui-kit add @auth0/auth0-spa-js -D
// career-up/packages/ui-kit/src/components/Profile.module.css

.profile-top {
  display: flex;
  flex-direction: column;
  background-color: white;

  padding: 30px 12px 16px;
  border-radius: 8px 8px 0 0;
  border-bottom: 1px solid rgb(0 0 0 / 0.1);
  gap: 10px;
  justify-content: center;
  align-items: center;
}

.profile-img {
  width: 50px;
}

.profile-name {
  font-size: 16px;
  font-weight: bold;
}

.profile-email {
  color: rgb(0 0 0/0.6);
  font-size: 12px;
}

.profile-bottom {
  display: flex;
  flex-direction: column;
  padding: 16px 12px 16px;
  border-radius: 0 0 8px 8px;
  background-color: white;
  gap: 10px;
}

.profile-bottom-item {
  display: flex;
  flex-direction: row;
  justify-content: space-between;

  color: rgb(0 0 0/0.6);
  font-size: 14px;
}

.profile-bottom-item-count {
  color: #0a66c2;
  cursor: pointer;
}
// career-up/packages/ui-kit/src/components/Profile.tsx

import React from "react";
import { type User } from "@auth0/auth0-spa-js";
import styles from "./Profile.module.css";

export interface UserType extends User {
  view_count: number;
  update_count: number;
  courses: { courseId: number; done: false }[];
}

interface ProfileProps {
  user: UserType | null;
}

const Profile: React.FC<ProfileProps> = ({ user }) => {
  if (user === null) {
    return null;
  }

  const { picture, name, email, view_count, update_count } = user;

  return (
    <div>
      <div className={styles["profile-top"]}>
        <img className={styles["profile-img"]} src={picture} />
        <div className={styles["profile-name"]}>{name}</div>
        <div className={styles["profile-email"]}>{email}</div>
      </div>
      <div className={styles["profile-bottom"]}>
        <div className={styles["profile-bottom-item"]}>
          <div>프로필 조회자</div>
          <div className={styles["profile-bottom-item-count"]}>
            {view_count}
          </div>
        </div>
        <div className={styles["profile-bottom-item"]}>
          <div>업데이트 노출</div>
          <div className={styles["profile-bottom-item-count"]}>
            {update_count}
          </div>
        </div>
      </div>
    </div>
  );
};

export default Profile;
// career-up/packages/ui-kit/src/index.ts

import "./global.css";

import Icon from "./components/Icon";
import Button from "./components/Button";
**import Profile from "./components/Profile";**

export { Icon, Button, **Profile** };
➜ pnpm --filter @career-up/ui-kit build

교육에 있는 Profile 변경

// career-up/apps/edu/src/containers/profile-container.tsx

import { useAtomValue } from "jotai";
import React from "react";
import { userAtom } from "../atoms";
import { Profile } from "@career-up/ui-kit";

const ProfileContainer: React.FC = () => {
  const user = useAtomValue(userAtom);

  return <Profile user={user} />;
};

export default ProfileContainer;
➜ pnpm --filter @career-up/edu build

➜ pnpm --filter @career-up/edu build:start 
// career-up/apps/edu/webpack.config.js

const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const Dotenv = require("dotenv-webpack");

const deps = require("./package.json").dependencies;
module.exports = (_, argv) => ({
  output: {
    publicPath: "<http://localhost:3002/>",
  },

  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },

  devServer: {
    port: 3002,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /\\.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\\.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /\\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },

  plugins: [
    new Dotenv({
      path: "../../.env",
    }),
    new ModuleFederationPlugin({
      name: "edu",
      filename: "remoteEntry.js",
      remotes: {},
      exposes: {
        "./injector": "./src/injector.tsx",
      },
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          requiredVersion: deps["react-dom"],
        },
        "@career-up/shell-router": {
          singleton: true,
        },
        "@career-up/ui-kit": {
          singleton: true,
          **shareScope: "v2",**
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
  ],
});
➜ pnpm --filter @career-up/edu build

➜ pnpm --filter @career-up/edu build:start 
// career-up/apps/edu/src/injector.tsx

import { injectFactory } from "@career-up/shell-router";
import { routes } from "./routes";
**import "@career-up/ui-kit/index.css";**

const inject = injectFactory({
  routes,
});

export default inject;
➜ pnpm --filter @career-up/edu build

➜ pnpm --filter @career-up/edu build:start 

포스팅에 있는 Profile 변경

// career-up/apps/posting/src/containers/profile-container.tsx

import React, { useEffect, useState } from "react";
import { getUser } from "../apis";
import { type UserType } from "../types";
import { useAuth0Client } from "@career-up/shell-router";
import { Profile } from "@career-up/ui-kit";

const ProfileContainer = () => {
  const auth0Client = useAuth0Client();
  const [user, setUser] = useState<UserType | null>(null);

  useEffect(() => {
    (async () => {
      try {
        const token = await auth0Client.getTokenSilently();
        const user = await getUser(token);
        setUser(user);
      } catch (error) {
        alert(error);
      }
    })();
  }, [auth0Client]);

  return <Profile user={user} />;
};

export default ProfileContainer;
// career-up/apps/posting/src/types.ts

import { type User } from "@auth0/auth0-spa-js";

export interface PostType {
  id: number;
  message: string;
  createdAt: string;
  author: {
    email: string;
    name: string;
    picture: string;
  };
}

export interface UserType extends User {
  view_count: number;
  update_count: number;
  **courses: { courseId: number; done: false }[];**
}