반응: Webpack 5 Module Federation을 사용하는 Micro Frontend

5946 단어

In progress !!!!!!!!



프로젝트 초기화




mkdir /opt/mfe
cd /opt/mfe

# create dashboard app
npx create-react-app dashboard-app --template typescript
# create profile app
npx create-react-app profile-app --template typescript
# create host app
npx create-react-app container --template typescript


종속성 설치



무이 추가




npm install @mui/material @emotion/react @emotion/styled
npm install @fontsource/roboto
npm install @mui/icons-material


MFE 부서 추가




npm i webpack webpack-cli webpack-dev-server \
      html-webpack-plugin 

npm i @babel/core @babel/preset-env @babel/preset-react \ 
  babel/preset-typescript @babel/plugin-transform-runtime \  
  babel-loader css-loader postcss postcss-loader style-loader


구성


  • index.tsxbootstrap.tsx로 교체:
  • 파일 생성./src/index.ts:

  • import { createBrowserHistory, Update } from 'history';
    
    import('./bootstrap').then(({ mount }) => {
      const localRoot = document.getElementById('dashboardApp-local');
      const browserHistory = createBrowserHistory();
    
      mount({
        mountPoint: localRoot!,
        historyStrategy: browserHistory,
      });
    });
    
    


    파일 추가.babelrc:

    vi .babelrc
    ----
    {
      "presets": [
        "@babel/preset-typescript",
        "@babel/preset-react",
        "@babel/preset-env"
      ],
      "plugins": [["@babel/transform-runtime"]]
    }
    


    파일 추가webpack.config.js:

    vi webpack.config.js
    ----
    const HtmlWebPackPlugin = require('html-webpack-plugin');
    const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
    
    const deps = require('./package.json').dependencies;
    module.exports = {
      output: {
        publicPath: 'http://localhost:8081/',
      },
    
      resolve: {
        extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
      },
    
      devServer: {
        port: 8081,
        historyApiFallback: true,
        headers: {
          'Access-Control-Allow-Origin': '*',
        },
      },
    
      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 ModuleFederationPlugin({
          name: 'dashboard-app',
          filename: 'remoteEntry.js',
          remotes: {},
          exposes: {
            './DashboardAppIndex': './src/bootstrap',
          },
          shared: {
            ...deps,
            react: {
              singleton: true,
              requiredVersion: deps.react,
            },
            'react-dom': {
              singleton: true,
              requiredVersion: deps['react-dom'],
            },
          },
        }),
        new HtmlWebPackPlugin({
          template: './src/index.html',
        }),
      ],
    };
    
    


  • 실행 스크립트 교체:

  • "scripts": {
        "build": "webpack --mode production",
        "build:dev": "webpack --mode development",
        "build:start": "cd dist && PORT=8082 npx serve",
        "start": "webpack serve --open --mode development",
        "start:live": "webpack serve --open --mode development --live-reload --hot"
      },
    


  • 컨테이너용 Webpack 구성:

  • const HtmlWebPackPlugin = require('html-webpack-plugin');
    const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
    
    const deps = require('./package.json').dependencies;
    module.exports = {
      output: {
        publicPath: 'http://localhost:8080/',
      },
    
      resolve: {
        extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
      },
    
      devServer: {
        port: 8080,
        historyApiFallback: true,
        headers: {
          'Access-Control-Allow-Origin': '*',
        },
      },
    
      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 ModuleFederationPlugin({
          name: 'container',
          filename: 'remoteEntry.js',
          remotes: {
            dashboardApp: 'dashboardApp@http://localhost:8081/remoteEntry.js',
            profileApp: 'profileApp@http://localhost:8082/remoteEntry.js',
          },
          exposes: {},
          shared: {
            ...deps,
            react: {
              singleton: true,
              requiredVersion: deps.react,
            },
            'react-dom': {
              singleton: true,
              requiredVersion: deps['react-dom'],
            },
          },
        }),
        new HtmlWebPackPlugin({
          template: './src/index.html',
        }),
      ],
    };
    
    

    좋은 웹페이지 즐겨찾기