I am trying to create an application which holds universal layout for other application (which are submodules from git). I use microfrontend technique to achieve that.
My layout works fine with everything needed and I wanted to test sharing components between apps by using webpack.
When I have created ModuleFederationPlugin objects in each webpack.config.js files, an app importing Footer doesn't see this component.
webpack.config.js (layout)
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: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",
},
},
{
test: /\.json$/,
use: {
loader: "json-loader",
},
},
{
test: /\.png$/i,
use: [
{
loader: 'file-loader',
},
],
},
{
test: /\.less$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "less-loader",
options: {
lessOptions: {
javascriptEnabled: true
}
}
}]
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-url-loader',
options: {
limit: 10000,
},
},
],
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "layout",
filename: "remoteEntry.js",
exposes: {
"./Footer": "./src/components/Footer.jsx"
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
eager: true,
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
eager: true,
},
},
}),
new HtmlWebPackPlugin({
template: "./src/index.html",
}),
],
};
webpack.config.js (web app)
const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
output: {
publicPath: "http://localhost:3000/",
},
devServer: {
port: 3000
},
resolve: {
extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
},
test: /\.svg$/,
use: ['#svgr/webpack'],
entry: './src/index.js',
module: {
rules: [{
test: /\.(png|jp(e*)g|svg|gif)$/,
use: [{
loader: 'file-loader',
options: {
name: 'images/[hash]-[name].[ext]',
},
}, ],
}, ],
},
plugins: [
new ModuleFederationPlugin({
name: "web",
remotes: {
layout: "layout#http://localhost:3002/remoteEntry.js"
},
}),
new HtmlWebPackPlugin({
template: './public/index.html'
})
],
}
App.js (web app)
...
import Footer from "layout/Footer";
class App extends React.Component {
...
render() {
return (
<>
<Footer />
</>
);
}
}
VS Code console
Failed to compile.
./src/App.js
Module not found: Can't resolve 'layout/Footer' in 'C:\Users\neraz\Desktop\projekty\layout\web\src'
Related
I've installed file-loader and url-loader, and added the below to my webpack config
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'file-loader',
options: {}
}]
},
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
},
},
below is my html
<img src="../src/assets/laughing.svg">
console error after npm run dev
Failed to load resource: the server responded with a status of 404 (Not Found)
I'm new to webpack, not sure what I'm doing wrong here....
Full config:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development',
entry: {
bundle: path.resolve(__dirname, 'src/index.js'),
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name][contenthash].js',
clean: true,
assetModuleFilename: '[name][ext]',
},
devtool: 'source-map',
devServer: {
static: {
directory: path.resolve(__dirname, 'dist'),
},
port: 3000,
open: true,
hot: true,
compress: true,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
},
},
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'file-loader',
options: {}
}]
},
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack App',
filename: 'index.html',
template: 'src/index.html',
}),
new HtmlWebpackPlugin({
title: 'Webpack App',
filename: 'about.html',
template: 'src/about.html',
}),
],
}
Any idea how to fix this?
Image works when I'm not not running npm run dev. So img src must be correct.
I think you should remove file-loader and url-loader
Here's the documentation example:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource', // EXAMPLE HERE
},
],
},
};
only use the asset/resource module
I am having an issue trying to 'run serve' with a React-App I am working on. I am getting a bunch of error messages but I think are mainly due to this one error -
#babel/polyfill is deprecated. Please, use required parts of 'core-js' and 'regenerator-runtime/runtime' separately.
This is a webpack.config.dev.js and webpack.config.js file
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: { main: './src/index.tsx' },
mode: 'development',
externals: {
react: 'React',
'react-dom': 'ReactDOM',
'react-router': 'ReactRouter',
},
target: 'web',
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
[
'#babel/preset-env',
{
useBuiltIns: 'entry',
corejs: 3,
},
],
],
},
},
{ loader: 'ts-loader' },
],
},
{
test: /\.(jsx?)$/,
use: [
{
loader: 'babel-loader',
options: {
presets: [
[
'#babel/preset-env',
{
useBuiltIns: 'entry',
corejs: 3,
},
],
],
},
},
],
},
{
test: /\.(s*)css$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: 'src/index.html',
filename: 'index.html',
chunksSortMode: 'auto',
chunks: ['main'],
}),
],
};
Any ideas? Thank you!
I'm starting to experiment with the micro frontend with webpack module federation.
This is for a very particular purpose because in our company we develop big software like dashboards in react in Role base access control, and I would like each section (or almost) to be a separate application.
So I managed to implement everything, only I noticed that the automatic reload of the app container was not done when I modify a remote app. I can understand why, but I wonder if there is a way to modify this? Knowing that I can't work only on the remote app because it uses the app container's redundancy provider...
Here my webpack config for app container :
const ReactRefreshPlugin = require("#pmmmwh/react-refresh-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack").container
.ModuleFederationPlugin;
const path = require("path");
const deps = require("./package.json").dependencies;
module.exports = {
entry: "./src/index",
target:"web",
mode: "development",
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 3001,
hot:true
},
output: {
publicPath: "auto",
},
resolve: {
extensions: [".js", ".jsx", ".json", ".ts", ".tsx"],
},
module: {
rules: [
{
test: /bootstrap\.tsx$/,
loader: "bundle-loader",
options: {
lazy: true,
},
},
{
test: /\.tsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
plugins: ['react-refresh/babel'],
presets: ["#babel/preset-react", "#babel/preset-typescript"],
},
},
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader",
},
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: true,
},
},
{
loader: 'postcss-loader',
options: {
options: {}
}
},
],
},
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
'resolve-url-loader',
'sass-loader',
],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader',
],
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "appshell",
filename: "remoteEntry.js",
remotes: {
mfsectors: "mfsectors#http://localhost:3002/remoteEntry.js",
},
exposes: {
"./routes": "./src/routes",
"./src/store/**": "./src/store"
},
shared: {
...deps,
react: {
eager: true,
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
eager: true,
singleton: true,
requiredVersion: deps["react-dom"],
},
},
}),
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
new ReactRefreshPlugin({
exclude: [/node_modules/, /bootstrap\.tsx$/],
}),
],
};
and here my webpack config for app remote :
const ReactRefreshPlugin = require("#pmmmwh/react-refresh-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack").container
.ModuleFederationPlugin;
const path = require("path");
const deps = require("./package.json").dependencies;
module.exports = {
entry: "./src/index.ts",
mode: "development",
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 3002,
hot:true
},
output: {
publicPath: "auto",
},
resolve: {
extensions: [".js", ".jsx", ".json", ".ts", ".tsx"],
},
module: {
rules: [
{
test: /bootstrap\.tsx$/,
loader: "bundle-loader",
options: {
lazy: true,
},
},
{
test: /\.tsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
plugins: ['react-refresh/babel'],
presets: ["#babel/preset-react", "#babel/preset-typescript"],
},
},
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader",
},
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
sourceMap: true,
},
},
{
loader: 'postcss-loader',
options: {
options: {}
}
},
],
},
{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
'resolve-url-loader',
'sass-loader',
],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader',
],
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "mfsectors",
filename: "remoteEntry.js",
remotes: {
appshell: "appshell#http://localhost:3001/remoteEntry.js",
},
exposes: {
"./routes": "./src/routes",
},
shared: {
...deps,
react: {
eager: true,
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
eager: true,
singleton: true,
requiredVersion: deps["react-dom"],
},
},
}),
new HtmlWebpackPlugin({
template: "./public/index.html",
}),
new ReactRefreshPlugin({
exclude: [/node_modules/, /bootstrap\.tsx$/],
}),
],
};
Thank you !
Sorry for my bad english ^^'
you could simply add this to your host's webpack.config.js:
{
...
devServer: {
...
liveReload: true,
watchFiles: [path.resolve(__dirname, '..')], // make sure that hits your host app folder
},
}
and then on your remote's webpack.config.js:
{
...
devServer: {
...
devMiddleware: {
writeToDisk: true,
},
},
}
Webpack-stream version: 5.2.1
npm version: 6.14.4
node version: v10.13.0
platform: windows10
I use gulp + webpack-stream for two modules: libraries.js and page.js
The problem relates only to the import from node_modules to page.js, the same import to libraries.js works well.
Import module as
import 'slick-carousel/slick/slick';
and even just import throws that error without call
Full code page.js
'use strict';
import '../_modules/forms/doctor-review';
import 'slick-carousel/slick/slick';
$(window).on('load', function () {
$('.js-slick').slick();
});
webpack config for libraries.js:
{
mode: λ.mode,
output: {
pathinfo: false,
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
},
},
},
],
},
optimization: {
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
vendor: {
chunks: 'all',
test: /node_modules/,
},
},
},
},
}
webpack config for page.js:
{
mode: λ.mode,
output: {
pathinfo: false,
},
plugins: [],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
},
},
},
],
},
optimization: {
namedModules: true,
namedChunks: true,
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
vendor: {
chunks: 'all',
test: /node_modules/,
},
},
},
},
}
I'm migrating a react website to webpack 4 (from 3) but have been running into some strange problems when using webpack for css.
It works fine for the css that I wrote myself, but any css from third party components in node_modules does not seem to be included at all.
Here is an example of my webpack config:
const webpack = require('webpack');
const path = require('path');
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const config = {
entry: [
'react-hot-loader/patch',
'./src/index.js'
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
exclude: [/node_modules/, /global\.css$/],
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
}
},
'postcss-loader'
]
},
{
test: /\.css$/,
include: [/node_modules/, /global\.css$/],
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 0,
modules: true,
}
}
]
},
{
test: /\.png$/,
use: [
{
loader: 'url-loader',
options: {
mimetype: 'image/png'
}
}
]
},
{
test: /\.svg$/,
use: 'file-loader'
},
{
test: /\.jpg$/,
use: [
{
loader: 'url-loader',
options: {
mimetype: 'image/jpg'
}
}
]
},
]
},
resolve: {
extensions: [
'.js',
'.jsx'
],
alias: {
'react-dom': '#hot-loader/react-dom'
},
modules: [
'node_modules',
],
},
devServer: {
contentBase: './dist'
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/),
new LodashModuleReplacementPlugin,
new HtmlWebpackPlugin({
template: require('html-webpack-template'),
inject: false,
appMountId: 'app',
})
],
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
module.exports = (env, argv) => {
if (argv.hot) {
// Cannot use 'contenthash' when hot reloading is enabled.
config.output.filename = '[name].[hash].js';
}
return config;
};
Only css from my own files are included in the generated bundle.
I'm using the latest versions:
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
Greatful for any help!
Layout of the project