我们正在将我的项目迁移到模块联合。在这个过程中,容器项目必须不断地以地图为基础呈现。其他微项目应通过容器项目中的按钮打开。
我无法克服远程项目在容器中破坏地图的问题。
容器 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>
);
}