簡體   English   中英

通過腳本標簽加載 webpack 包用於微前端方法

[英]Loading webpack bundle via script tag for microfrontend approach

我正在關注幾篇關於如何使用 React 實現簡單微前端方法的文章( 此處此處,請參閱問題底部的示例存儲庫)。

當兩個應用程序(根應用程序和子應用程序)在各自的開發服務器中運行時,它可以完美運行。 但是,當我將構建工件部署到真正的 Web 服務器時,它不起作用。 這是根應用程序中的重要代碼:

function MicroFrontend({name, host, history}) {

    useEffect(() => {
        const scriptId = `micro-frontend-script-${name}`;

        const renderMicroFrontend = () => {
            window["render" + name](name + "-container", history);
        };

        if (document.getElementById(scriptId)) {
            renderMicroFrontend();
            return;
        }

        fetch(`${host}/asset-manifest.json`)
            .then((res) => res.json())
            .then((manifest) => {
                const script = document.createElement("script");
                script.id = scriptId;
                script.crossOrigin = "";
                script.src = `${host}${manifest.files["main.js"]}`;
                script.onload = () => {
                    renderMicroFrontend();
                };
                document.head.appendChild(script);
            });

        return () => {
            window[`unmount${name}`] && window[`unmount${name}`](`${name}-container`);
        };
    });

    return <main id={`${name}-container`}/>;
}

MicroFrontend.defaultProps = {
    document,
    window,
};

當我點擊為微應用加載 main.js 的按鈕時,它工作正常,直到它調用上面的renderMicroFrontend 然后我在瀏覽器中收到此錯誤: Uncaught TypeError: window[("render" + t)] is not a function

這是因為它找不到加載應該在window上的微前端的函數。 當我在開發服務器中運行這兩個應用程序時,我在window上具有正確的功能並且可以正常工作。 當我對部署到真實服務器的兩個應用程序執行相同的步驟時(在運行npm run build ),而不是在我的window上使用renderMicroApp函數,我有一個名為webpackJsonpmicro-app的不同變量。

我發現這是由於 webpack 文檔中的 output.library 選項(和/或相關選項)造成的:

output.jsonp 函數。 string = 'webpackJsonp' 僅在 target 設置為 'web' 時使用,它使用 JSONP 加載按需塊。 如果使用 output.library 選項,庫名稱會自動與 output.jsonpFunction 的值連接。

我基本上希望加載和評估包/腳本,以便renderMicroApp函數在窗口上可用,但是我不知道我需要哪些 webpack 設置才能使其工作,因為有很多不同的選項排列。

作為參考,我在微應用程序中使用了以下配置覆蓋(在react-app-rewired之上):

module.exports = {
  webpack: (config, env) => {
    config.optimization.runtimeChunk = false;
    config.optimization.splitChunks = {
      cacheGroups: {
        default: false,
      },
    };

    config.output.filename = "static/js/[name].js";

    config.plugins[5].options.filename = "static/css/[name].css";
    config.plugins[5].options.moduleFilename = () => "static/css/main.css";
    return config;
  },
};

在我的 index.tsx(在微型應用程序中)中,我將函數暴露在窗口上:

window.renderMicroApp = (containerId, history) => {
  ReactDOM.render(<AppRoot />, document.getElementById(containerId));
  serviceWorker.unregister();
};

一些示例回購:

您可以嘗試使用terser-webpack-plugin

const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  webpack: (config, env) => {
    config.optimization.minimize = true;
    config.optimization.minimizer = [new TerserPlugin({
      terserOptions: { keep_fnames: true }
    })];

    config.optimization.runtimeChunk = false;
    config.optimization.splitChunks = {
      cacheGroups: {
        default: false,
      },
    };

    config.output.filename = "static/js/[name].js";

    config.plugins[5].options.filename = "static/css/[name].css";
    config.plugins[5].options.moduleFilename = () => "static/css/main.css";
    return config;
  }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM