0

我们正在将我的项目迁移到模块联合。在这个过程中,容器项目必须不断地以地图为基础呈现。其他微项目应通过容器项目中的按钮打开。

我无法克服远程项目在容器中破坏地图的问题。

容器 webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const deps = require("./package.json").dependencies;
const JsonMinimizerPlugin = require("json-minimizer-webpack-plugin");
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const outputDir = path.join(__dirname, '/dist');

module.exports = {
    entry: './src/index.jsx',
    cache: false,

    mode: 'development',
    devtool: 'inline-source-map',

    optimization: {
        minimize: true,
        minimizer: [
            // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
            // `...`
            new JsonMinimizerPlugin(),
        ],},
    output: {
        publicPath: "http://localhost:3002/",
        path: path.resolve(__dirname, "dist"),
        filename: 'bundle.js'
    },
    devServer: {
        port: 3002,
    },
    resolve: {
        extensions: [".js", ".jsx"]
    },
    module: {
        unknownContextCritical: false,
        unknownContextRegExp: /^.\/.*$/,
        noParse: [/jszip.js$/],
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                },
            },
            {
                test: /\.css$/,
                use: [
                    {loader: "style-loader"},
                    {loader: "css-loader"}
                ]
            },
            {
                test: /\.svg$/,
                use: [{loader: "file-loader"}, {loader: "svg-url-loader?noquotes"}]
            },
            {
                test: /(\.jpg|\.png|\.gif|\.woff2|\.woff|\.ttf|\.eot|\.glsl)$/,
                use: {loader: "file-loader"},
            },
            {
                test: /\.m?js/,
                type: "javascript/auto",
                resolve: {
                    fullySpecified: false,
                },
            },
            { test: /\.txt$/, use: {loader:  'raw-loader'} },
            {
                test: /\.json$/i,
                loader: 'json-loader'
            },
            {
                test: /\.html$/,
                loader: "html-loader",
            },
        ]
    },
    plugins: [
        new CopyWebpackPlugin({
            patterns: [
                {
                    context: 'node_modules/kasif-js/',
                    from: '**/*',
                    globOptions: {
                        dot: false
                    },
                    to: path.resolve(outputDir, 'libs/kasif-js')
                },
                {
                    from: 'index.html',
                    to: outputDir,
                    noErrorOnMissing: true
                },

                {
                    context: 'src/icons',
                    from: '**/*',
                    globOptions: {
                        dot: false
                    },
                    to: path.resolve(outputDir, 'icons'),
                    noErrorOnMissing: true
                },
                {
                    context: 'src/styles',
                    from: '**/*',
                    globOptions: {
                        dot: false
                    },
                    to: path.resolve(outputDir, 'styles'),
                    noErrorOnMissing: true
                },
            ]
        }),
        new ModuleFederationPlugin({
            name: 'map',
            filename: 'remoteEntry.js',
            exposes: {
                './MapIndex': './src/index.jsx',
                './Basemap': './src/map/BaseMap.jsx',
            },
            remotes: {
                analysis: 'analysis@http://localhost:3000/remoteEntry.js',
            },
            shared: {
                ...deps,
                react: {
                    singleton: true,
                    requiredVersion: deps.react,
                },
                "react-dom": {
                    singleton: true,
                    requiredVersion: deps["react-dom"],
                },
            },
        }),
    ],
}

容器索引.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>Map</title>
<body>
<div id="versionInfo"></div>
<div id="dev-map"></div>
<div id="dev-analysis"></div>

<script>
    window.mapAsLibrary = true;
</script>
<script defer src="libs/kasif-js/app/app.js"></script>
<script defer src="./bundle.js"></script>
</body>
</html>

远程项目 webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const deps = require("./package.json").dependencies;
const JsonMinimizerPlugin = require("json-minimizer-webpack-plugin");
const path = require('path');

module.exports = {
    entry: "./src/index",
    cache: false,

    mode: "development",
    devtool: "source-map",

    optimization: {
        minimize: true,
        minimizer: [
            // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
            // `...`
            new JsonMinimizerPlugin(),
        ],},
    output: {
        publicPath: "http://localhost:3000/",
        path: path.resolve(__dirname, 'dist'),
        filename: 'index.js',
    },

    devServer: {
        port: 3000,
    },

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

    module: {
        unknownContextCritical: false,
        unknownContextRegExp: /^.\/.*$/,
        noParse: [/jszip.js$/],
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                },
            },
            {
                test: /\.css$/,
                use: [
                    {loader: "style-loader"},
                    {loader: "css-loader"}
                ]
            },
            {
                test: /\.svg$/,
                use: [{loader: "file-loader"}, {loader: "svg-url-loader?noquotes"}]
            },
            {
                test: /(\.jpg|\.png|\.gif|\.woff2|\.woff|\.ttf|\.eot|\.glsl)$/,
                use: {loader: "file-loader"},
            },
            {
                test: /\.m?js/,
                type: "javascript/auto",
                resolve: {
                    fullySpecified: false,
                },
            },
            { test: /\.txt$/, use: {loader:  'raw-loader'} },
            {
                test: /\.json$/i,
                loader: 'json-loader'
            },
        ],
    },
    plugins: [
        new ModuleFederationPlugin({
            name: 'analysis',
            filename: 'remoteEntry.js',
            exposes: {
                './AnalysisIndex': './src/index.jsx',
            },
            shared: {
                ...deps,
                react: {
                    singleton: true,
                    requiredVersion: deps.react,
                },
                "react-dom": {
                    singleton: true,
                    requiredVersion: deps["react-dom"],
                },
            },
        }),
        new HtmlWebpackPlugin({template: './public/index.html',}),

    ],

};

远程 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title></title>
<body>
<div id="dev-analysis"></div>
</body>
</html>

反应用法:

   const AnalysisComponent = React.lazy(
        () => import('analysis/AnalysisIndex')
    );
    
    ....
    render() {
     return (
                <div>
                    <Suspense fallback={null}>
                    <BaseMap/>
                    <AnalysisComponent />
                    </Suspense>
                </div>
            );
    }
4

0 回答 0