How to use common dependencies between multiple modules in React micro frontend - reactjs

Hey I am using react microfrontend in my react project with webpack module federation.
After changing folder structure as per microfrontend structure facing some difficulties to handle common dependencies of modules.
Getting Following Error:
ERROR in resolving fallback for shared module react
Module not found: Error: Can't resolve 'react' in '/Users/admin/Desktop/guru/project/microfrontend/modules/metronic/layout/components/subheader/components'
ERROR in resolving fallback for shared module react
Module not found: Error: Can't resolve 'react-router-dom' in '/Users/admin/Desktop/guru/project/microfrontend/modules/metronic/layout/components/subheader/components'
Here I am sharing my code structure
webpack
package.json
folder structure
Webpack:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
require('dotenv').config({ path: '../.env' });
module.exports = {
// the output bundle won't be optimized for production but suitable for development
mode: 'development',
// the app entry point is /src/index.js
entry: path.resolve(__dirname, 'src', 'index.js'),
output: {
// the output of the webpack build will be in /dist directory
path: path.resolve(__dirname, 'dist'),
// the filename of the JS bundle will be bundle.js
filename: 'bundle.js',
publicPath: '/'
},
devServer: {
historyApiFallback: true,
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
module: {
rules: [
{
// for any file with a suffix of js or jsx
test: /\.jsx?$/,
// ignore transpiling JavaScript from node_modules as it should be that state
exclude: /node_modules/,
// use the babel-loader for transpiling JavaScript to a suitable format
loader: 'babel-loader',
options: {
// attach the presets to the loader (most projects use .babelrc file instead)
presets: ["#babel/preset-env", "#babel/preset-react"]
}
},
{
// test: /\.s[ac]ss$/i,
test: /\.(sa|sc|c)ss$/,
use: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
{
test: /\.(woff(2)?|ttf|eot|svg|png)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
]
}
]
},
// add a custom index.html as the template
plugins: [
new ModuleFederationPlugin({
name: "app_container",
remotes: {
banners: "banners#http://localhost:3002/remoteEntry.js",
newDashboard: "newDashboard#http://localhost:3008/remoteEntry.js",
baggageService: "baggageService#http://localhost:3016/remoteEntry.js",
},
// shared: [ "react", "react-dom"]
shared: {
"react-router-dom": { singleton: true, eager: true, requiredVersion: "^5.1.2" },
"#manaflair/redux-batch":{ singleton: true, eager: true, requiredVersion: "1.0.0" },
"#reduxjs/toolkit":{ singleton: true, eager: true, requiredVersion: "1.3.6" },
"react-redux":{ singleton: true, eager: true, requiredVersion: "7.1.3" },
"redux":{ singleton: true, eager: true, requiredVersion: "4.0.5" },
"redux-logger":{ singleton: true, eager: true, requiredVersion: "^3.0.6" },
"redux-persist":{ singleton: true, eager: true, requiredVersion: "6.0.0" },
"redux-saga":{ singleton: true, eager: true, requiredVersion: "1.1.3" },
"react": { singleton: true, eager: true, requiredVersion: "^17.0.2" },
"#fortawesome/fontawesome-free": { singleton: true, eager: true, requiredVersion: "5.13.0" },
"react-dom": { singleton: true, eager: true, requiredVersion: "^17.0.2" },
"lodash": { singleton: true, eager: true, requiredVersion: "4.17.21" },
"lodash.debounce": { singleton: true, eager: true, requiredVersion: "^4.0.8" },
}
}),
new HtmlWebpackPlugin({
template: "./public/index.html"
}),
new webpack.DefinePlugin({
"process.env": JSON.stringify(process.env)
})
]
};
In our project have common utils and components that is being used in different micro frontend modules
how to handle that dependencies.
package.json:
{
"name": "microfrontend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --open",
"build": "webpack --config webpack.prod.config.js --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"#amcharts/amcharts3-react": "^3.0.0",
"#babel/core": "^7.17.5",
"#babel/preset-env": "^7.16.11",
"#babel/preset-react": "^7.16.7",
"#date-io/date-fns": "^1.3.11",
"#formatjs/intl-pluralrules": "1.3.5",
"#fortawesome/fontawesome-free": "^5.13.0",
"#manaflair/redux-batch": "1.0.0",
"#material-ui/core": "^4.10.2",
"#material-ui/icons": "4.9.1",
"#material-ui/pickers": "^3.3.10",
"#material-ui/styles": "4.9.14",
"#reduxjs/toolkit": "1.3.6",
"#tanem/svg-injector": "8.0.50",
"#wojtekmaj/react-daterange-picker": "^3.3.0",
"apexcharts": "3.24.0",
"axios": "0.21.2",
"axios-mock-adapter": "1.18.1",
"babel-loader": "^8.2.3",
"bootstrap": "4.5.0",
"bootstrap-daterangepicker": "^3.1.0",
"clipboard-copy": "3.1.0",
"clsx": "1.1.0",
"cp-cli": "2.0.0",
"css-mediaquery": "0.1.2",
"date-fns": "2.8.1",
"downshift": "3.4.2",
"fg-loadcss": "2.1.0",
"file-loader": "^6.2.0",
"formik": "2.1.4",
"highcharts": "^9.0.0",
"highcharts-react-official": "^3.0.0",
"html-react-parser": "^0.13.0",
"html-webpack-plugin": "^5.5.0",
"html2canvas": "^1.3.2",
"http-service": "file:../modules/http-service",
"i": "^0.3.7",
"json2mq": "0.2.0",
"jss-rtl": "^0.3.0",
"lodash": "4.17.21",
"lodash.debounce": "^4.0.8",
"material-picker-4.0": "npm:#material-ui/pickers#^4.0.0-alpha.12",
"material-ui-popup-state": "1.4.1",
"metronic": "file:../modules/metronic",
"npm": "^6.14.6",
"object-path": "0.11.8",
"perfect-scrollbar": "1.5.0",
"prop-types": "15.7.2",
"quill-emoji": "^0.1.7",
"react-beautiful-dnd": "^13.1.0",
"react-bootstrap": "1.0.1",
"react-bootstrap-daterangepicker": "^7.0.0",
"react-bootstrap-table-next": "4.0.2",
"react-bootstrap-table2-paginator": "2.1.2",
"react-copy-to-clipboard": "^5.0.2",
"react-data-table-component": "^6.9.3",
"react-datepicker": "2.16.0",
"react-draggable": "4.4.2",
"react-highcharts": "^16.1.0",
"react-hooks-helper": "^1.6.0",
"react-html-parser": "^2.0.2",
"react-image-crop": "^8.6.12",
"react-inlinesvg": "1.2.0",
"react-intl": "3.6.2",
"react-is": "16.13.1",
"react-pdf": "^5.7.0",
"react-perfect-scrollbar": "1.5.8",
"react-portal": "4.2.0",
"react-qr-reader": "^2.2.1",
"react-quill": "^1.3.5",
"react-redux": "7.1.3",
"react-router-dom": "5.1.2",
"react-router-last-location": "^2.0.1",
"react-rte": "^0.16.1",
"react-scripts": "3.2.0",
"react-select": "3.1.0",
"react-star-ratings": "^2.3.0",
"react-swipeable-views": "0.13.9",
"react-syntax-highlighter": "12.2.1",
"react-table-hoc-fixed-columns": "^2.3.4",
"react-toastify": "^6.0.6",
"react-window": "1.8.5",
"reactstrap": "^8.5.1",
"redux": "4.0.5",
"redux-logger": "^3.0.6",
"redux-persist": "6.0.0",
"redux-saga": "1.1.3",
"sass": "^1.49.9",
"sass-loader": "^12.6.0",
"socicon": "3.0.5",
"styled-components": "^5.1.1",
"sweetalert2": "^10.12.6",
"sweetalert2-react-content": "^3.2.2",
"common-gui-components": "file:../modules/common-gui-components",
"common-store": "file:../modules/common-store",
"common-utils": "file:../modules/common-utils",
"uuid": "^8.3.2",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4",
"yup": "0.29.0"
}
}
My folder structure:

Related

Webpack not resolving dependencies during yarn build (Module not found: Error: Can't resolve in 'x')

I'm stuck with webpack error during the Yarn build of my commons components library.
The returned error from all .ts/.tsx files are the same, like this:
ERROR in ../../node_modules/react-select-async-paginate/es/index.js 7:0-54
Module not found: Error: Can't resolve './useAsyncPaginate' in '...\monorepo-swa-cli\node_modules\react-select-async-paginate\es'
# ./src/components/SelectAsync/SelectAsync.tsx 50:0-60 259:46-59
# ./src/components/SelectAsync/index.ts 1:0-55 1:0-55
# ./src/components/index.ts 29:0-30 29:0-30
# ./src/index.ts 1:0-29 1:0-2
Here is a complete build log.
Important: This error only occurs on files that reference an external dependency, such as moment, select-async, etc.
Here are my files:
.babelrc:
{
"presets": ["#babel/preset-env", "#babel/preset-react"]
}
webpack.config.js:
const path = require('path')
module.exports = {
entry: "./src/index.ts",
target: "node",
mode: "production",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index.js",
libraryTarget: "umd",
library: "ui-lib"
},
module: {
rules: [
{
test: /\.css/,
use: ["style-loader", "css-loader"]
},
{
test: /\.tsx?$/,
use: ["babel-loader", "ts-loader"],
exclude: /node_modules/,
}
]
},
resolve: {
importsFields: ['browser', 'module', 'main'],
modules: [path.resolve(__dirname, 'src'), '../../node_modules'],
extensions: [".tsx", ".ts"]
},
resolveLoader: {
modules: ['node_modules'],
extensions: ['.ts', '.tsx'],
mainFields: ['loader', 'main'],
},
externals: {
react: "react"
}
}
package.json:
{
"name": "cli-components",
"version": "1.0.91",
"description": "Custom React component library",
"scripts": {
"build": "webpack"
},
"dependencies": {
"react-colorful": "^5.5.1",
"rxjs": "^7.5.4",
"uuid": "^8.3.2",
"moment": "^2.29.3"
},
"devDependencies": {
"#headlessui/react": "^1.5.0",
"#types/react": "^17.0.43",
"#types/react-dom": "^17.0.11",
"autoprefixer": "^10.4.2",
"moment": "^2.29.3",
"postcss": "^8.4.8",
"react": "^17.0.2",
"react-currency-input": "^1.3.6",
"react-datepicker": "^4.7.0",
"react-dom": "^17.0.2",
"react-input-mask": "^2.0.4",
"react-quill": "^1.3.5",
"react-select": "^5.2.2",
"react-select-async-paginate": "^0.6.1",
"tailwindcss": "^3.0.23",
"tslib": "^2.3.1",
"typescript": "^4.5.4",
"#babel/core": "^7.18.0",
"#babel/preset-env": "^7.18.0",
"#babel/preset-react": "^7.12.10",
"#babel/preset-typescript": "^7.17.12",
"#types/webpack": "^5.28.0",
"babel-loader": "^8.2.3",
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2",
"ts-loader": "^9.3.0"
},
"peerDependencies": {
"moment": "^2.29.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-quill": "^1.3.5"
},
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"files": [
"dist"
],
"types": "dist/index.d.ts",
"repository": {
//...
}
}
Additional information:
Node version: 16.15.0
Yarn version: 1.22.18
OS: Windows 10 (64 btis)
Monorepo: yes.
Thankful for your attention.

Returning 404 not found for the micro frontend dependencies from the host application

I am trying to implement a POC on micro frontends using module federation as an integration tool. I am able to run micro frontend separately(running on port 4001) but when I tried to run a host application(running on port 4000) that has microfrontend integrated into it, It was throwing errors saying that it couldn't able to found MF's dependencies i.e react-redux and redux toolkit as shown in the below image.
Host application doesn't have react-redux and redux toolkit as dependencies and I am not sure why it is trying to get dependencies from port 4000 instead of 4001. Can I know how to resolve this issue?
Host -webpack.config
const config: Configuration = {
mode: 'development',
output: {
publicPath: '/'
},
module: {
rules: [
{
test: /\.(ts|js)x?$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'#babel/preset-env',
'#babel/preset-react',
'#babel/preset-typescript'
]
}
}
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
plugins: [
new ModuleFederationPlugin({
name: 'container',
remotes: {
mf1: 'mf1#http://localhost:4001/remoteEntry.js'
},
shared: [deps]
}),
new HtmlWebpackPlugin({
template: 'public/index.html'
}),
new HotModuleReplacementPlugin(),
new ForkTsCheckerWebpackPlugin({
async: false
}),
new ESLintPlugin({
extensions: ['js', 'jsx', 'ts', 'tsx']
})
],
devtool: 'inline-source-map',
devServer: {
static: path.join(__dirname, 'build'),
historyApiFallback: true,
port: 4000,
open: true
}
};
export default config;
MF- webpack.config.js
const config: Configuration = {
mode: 'development',
output: {
publicPath: '/'
},
entry: './src/index',
module: {
rules: [
{
test: /\.(ts|js)x?$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'#babel/preset-env',
'#babel/preset-react',
'#babel/preset-typescript'
]
}
}
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
plugins: [
new ModuleFederationPlugin({
name: 'mf1',
filename: 'remoteEntry.js',
library: {type: 'var', name: 'mf1'},
exposes: {
'./Mf1App': './src/bootstrap'
},
shared: [deps]
}),
new HtmlWebpackPlugin({
template: 'public/index.html'
}),
new HotModuleReplacementPlugin(),
new ForkTsCheckerWebpackPlugin({
async: false
}),
new ESLintPlugin({
extensions: ['js', 'jsx', 'ts', 'tsx']
})
],
devtool: 'inline-source-map',
devServer: {
static: path.join(__dirname, 'build'),
historyApiFallback: true,
port: 4001,
open: true
}
};
export default config;
Host-package.json
{
"name": "container",
"version": "1.0.0",
"description": "",
"main": "index.ts",
"scripts": {
"start": "webpack serve --config config/webpack.dev.config.ts",
"build": "webpack --config config/webpack.prod.config.ts",
"lint": "eslint \"*/**/*.{js,ts,tsx}\"",
"lint:fix": "eslint \"*/**/*.{js,ts,tsx}\" --fix"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.15.8",
"#babel/plugin-transform-runtime": "^7.15.8",
"#babel/preset-env": "^7.15.8",
"#babel/preset-react": "^7.14.5",
"#babel/preset-typescript": "^7.15.0",
"#babel/runtime": "^7.15.4",
"#types/node": "^16.10.9",
"#types/react": "^17.0.29",
"#types/react-dom": "^17.0.9",
"#types/webpack": "^5.28.0",
"#types/webpack-dev-server": "^4.3.1",
"#typescript-eslint/eslint-plugin": "^5.0.0",
"#typescript-eslint/parser": "^5.0.0",
"babel-loader": "^8.2.2",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-react-hooks": "^4.2.0",
"fork-ts-checker-webpack-plugin": "^6.3.4",
"html-webpack-plugin": "^5.3.2",
"prettier": "^2.4.1",
"ts-node": "^10.3.0",
"tsconfig-paths-webpack-plugin": "^3.5.1",
"webpack": "^5.58.2",
"webpack-cli": "^4.9.0",
"webpack-dev-server": "^4.3.1",
"#types/fork-ts-checker-webpack-plugin": "^0.4.5",
"clean-webpack-plugin": "^3.0.0",
"typescript": "^4.4.4",
"eslint-webpack-plugin": "^2.4.1"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
MF1-package.json
{
"name": "microfrontend1",
"version": "1.0.0",
"description": "",
"main": "index.ts",
"scripts": {
"start": "webpack serve --config config/webpack.dev.config.ts",
"build": "webpack --config config/webpack.prod.config.ts",
"lint": "eslint \"*/**/*.{js,ts,tsx}\"",
"lint:fix": "eslint \"*/**/*.{js,ts,tsx}\" --fix"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.15.8",
"#babel/plugin-transform-runtime": "^7.15.8",
"#babel/preset-env": "^7.15.8",
"#babel/preset-react": "^7.14.5",
"#babel/preset-typescript": "^7.15.0",
"#babel/runtime": "^7.15.4",
"#types/node": "^16.10.9",
"#types/react": "^17.0.29",
"#types/react-dom": "^17.0.9",
"#types/webpack": "^5.28.0",
"#types/react-redux": "^7.1.19",
"#types/webpack-dev-server": "^4.3.1",
"#typescript-eslint/eslint-plugin": "^5.0.0",
"#typescript-eslint/parser": "^5.0.0",
"babel-loader": "^8.2.2",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-react-hooks": "^4.2.0",
"fork-ts-checker-webpack-plugin": "^6.3.4",
"html-webpack-plugin": "^5.3.2",
"prettier": "^2.4.1",
"ts-node": "^10.3.0",
"tsconfig-paths-webpack-plugin": "^3.5.1",
"webpack": "^5.58.2",
"webpack-cli": "^4.9.0",
"webpack-dev-server": "^4.3.1",
"#types/fork-ts-checker-webpack-plugin": "^0.4.5",
"clean-webpack-plugin": "^3.0.0",
"typescript": "^4.4.4",
"eslint-webpack-plugin": "^2.4.1"
},
"dependencies": {
"#reduxjs/toolkit": "^1.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.5"
}
}
In MF webpack.config.js update the output object as below:
`output: {
publicPath: 'http://localhost:4001/'
}`
Let me know if it helped.

Webpack css-loader does not resolve aliases

Currently doing maintenance for a project that was running React v15. Upgraded Webpack 3 > 4, Babel 6 > 7, css-loader 0.28.x > 3.0.0, etc.
Initially, updated React and used all the react-codemod + jscodeshift to transform the js files. While the version at that stage was not stable, it loaded and showed the proper styles etc.
What I find odd, is that after updating file-loader, css-loader, babel, and related packages, I kept getting Module not found: Error: Can't resolve, as following:
ERROR in ./app/sharedComponents/TitleGeneric/style.css (./node_modules/css-loader/dist/cjs.js??ref--6-1!./app/sharedComponents/TitleGeneric/style.css)
Module not found: Error: Can't resolve './sharedStyles/typography.css' in '/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric'
resolve './sharedStyles/typography.css' in '/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric'
using description file: /Users/userX/www/my-project-ui/package.json (relative path: ./app/sharedComponents/TitleGeneric)
Field 'browser' doesn't contain a valid alias configuration
using description file: /Users/userX/www/my-project-ui/package.json (relative path: ./app/sharedComponents/TitleGeneric/sharedStyles/typography.css)
no extension
Field 'browser' doesn't contain a valid alias configuration
/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css doesn't exist
.wasm
Field 'browser' doesn't contain a valid alias configuration
/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css.wasm doesn't exist
.mjs
Field 'browser' doesn't contain a valid alias configuration
/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css.mjs doesn't exist
.js
Field 'browser' doesn't contain a valid alias configuration
/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css.js doesn't exist
.json
Field 'browser' doesn't contain a valid alias configuration
/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css.json doesn't exist
as directory
/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css doesn't exist
[/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css]
[/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css.wasm]
[/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css.mjs]
[/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css.js]
[/Users/userX/www/my-project-ui/app/sharedComponents/TitleGeneric/sharedStyles/typography.css.json]
# ./app/sharedComponents/TitleGeneric/style.css (./node_modules/css-loader/dist/cjs.js??ref--6-1!./app/sharedComponents/TitleGeneric/style.css) 5:10-107 12:44-141
# ./app/sharedComponents/TitleGeneric/style.css
# ./app/sharedComponents/TitleGeneric/TitleGeneric.js
# ./app/pages/Knowledge/Bricks/Bricks.js
# ./app/pages/Knowledge/Bricks/BricksContainer.js
# ./app/loaders/pages.js
# ./app/router/routes.js
# ./app/index.js
# multi core-js/stable ./app
Before posting I've done a lot of testing, trying and seeing, modified a lot of code and could not figure out the issue; I've also done quite a lot of research online. Finally checked if there are any posts about this in StackOverflow, which I believe there is not at the moment.
Here's the package.json file:
{
"name": "Foobar",
"version": "1.0.0",
"main": "index.js",
"scripts": {
...
},
"repository": {
"type": "git",
"url": ""
},
"keywords": [],
"license": "ISC",
"engines": {
"node": ">=8.12.0"
},
"nyc": {
"include": [
"app/**/*.js"
],
"require": [
"#babel/register"
],
"all": "true",
"cache": "true",
"reporter": [
"text",
"html"
],
"sourceMap": "false",
"instrument": "false"
},
"dependencies": {
"#babel/core": "^7.5.0",
"#babel/plugin-proposal-class-properties": "^7.5.0",
"#babel/preset-env": "^7.5.3",
"#babel/preset-react": "^7.0.0",
"#babel/register": "^7.4.4",
"#moola/moola-component-library": "^0.3.9",
"#moola/moola-nuka-carousel": "^2.0.4-2",
"axios": "^0.15.3",
"babel-eslint": "^10.0.2",
"babel-loader": "^8.0.6",
"babel-plugin-lodash": "^3.3.4",
"bootstrap": "^3.3.7",
"highcharts": "^4.2.6",
"highcharts-more": "^0.1.2",
"intl": "^1.2.5",
"js-cookie": "^2.1.3",
"jwt-decode": "^2.1.0",
"mime-types": "^2.1.12",
"npm": "^5.8.0",
"numeral": "^1.5.3",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-addons-create-fragment": "^15.6.0",
"react-bootstrap": "^0.30.8",
"react-dom": "^16.8.6",
"react-highcharts": "^16.0.2",
"react-highstock": "^1.0.2",
"react-intl": "^2.4.0",
"react-intl-redux": "^2.1.1",
"react-markdown-renderer": "^1.4.0",
"react-modal": "3.8.2",
"react-paginate": "^5.2.2",
"react-redux": "^5.1.1",
"react-router-redux": "^4.0.7",
"react-transition-group": "^2.1.0",
"redux": "^4.0.1",
"redux-debounced": "^0.5.0",
"redux-form": "^7.4.2",
"redux-segment": "^1.6.1",
"redux-thunk": "^2.1.0"
},
"devDependencies": {
"#babel/plugin-proposal-export-default-from": "^7.5.2",
"acorn": "^6.2.0",
"add-asset-html-webpack-plugin": "^3.1.3",
"autoprefixer": "^9.6.1",
"babel-plugin-module-resolver": "^3.2.0",
"chai": "^3.5.0",
"chalk": "^1.1.3",
"core-js": "^3.1.4",
"create-react-class": "^15.6.3",
"css-loader": "^3.0.0",
"cyclist": "^1.0.1",
"enzyme": "^2.9.1",
"es6-promise": "^4.1.0",
"eslint": "^6.0.1",
"eslint-config-standard": "^13.0.0-1 ",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-node": "^9.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-react": "^7.14.2",
"eslint-plugin-standard": "^4.0.0",
"express": "^4.16.4",
"extract-loader": "^3.1.0",
"file-loader": "^4.0.0",
"git-revision-webpack-plugin": "^2.4.0",
"html-webpack-plugin": "^3.2.0",
"html2plaintext": "^2.0.1",
"husky": "^0.11.9",
"jsdom": "^9.4.1",
"json-server": "^0.14.0",
"jspolyfill-array.prototype.find": "^0.1.3",
"jspolyfill-array.prototype.findIndex": "^0.1.0",
"leasot": "^4.7.1",
"lodash-webpack-plugin": "^0.11.5",
"mini-css-extract-plugin": "^0.7.0",
"mocha": "^2.5.3",
"mocha-jenkins-reporter": "^0.2.3",
"mock-css-modules": "^1.0.0",
"moment": "^2.22.2",
"postcss-loader": "^3.0.0",
"postcss-modules-values": "^1.3.0",
"randexp": "^0.5.3",
"react-test-renderer": "^16.8.6",
"sinon": "^1.17.4",
"string-replace-webpack-plugin": "^0.1.3",
"style-loader": "^0.23.1",
"url-loader": "^2.0.1",
"webpack": "^4.35.3",
"webpack-bundle-analyzer": "^1.4.1",
"webpack-cli": "^3.3.5",
"webpack-dev-middleware": "^2.0.6",
"webpack-dev-server": "^2.9.1",
"webpack-hot-middleware": "^2.22.1",
"webpack-merge": "^4.1.0",
"webpack-s3-plugin": "0.9.0"
},
"optionalDependencies": {
"fsevents": "*"
}
}
The webpack base configuration file:
const webpack = require('webpack')
const path = require('path')
const chalk = require('chalk')
const loaderRules = require('./loaders')
const setup = require('./setup')
const PATHS = setup.PATHS
const VALUES = setup.VALUES
const HtmlWebpackPlugin = require('html-webpack-plugin')
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')
const IgnorePlugin = require('webpack/lib/IgnorePlugin')
const LodashReplacePlugin = require('lodash-webpack-plugin')
const isDev = process.env.npm_lifecycle_event !== 'vendor:production'
// Base configuration
const { analyticsKey, applicationPath, htmlLinkPath } = VALUES
let vendorManifest
try {
vendorManifest = require(path.join(PATHS.build, 'vendor.json'))
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND') {
throw e
}
/* eslint-disable no-console */
console.log(chalk.red('*** Moo.la script error ***'))
console.log(chalk.red('Vendor bundle/manifest not found.\nPlease run ') +
chalk.white('`npm run vendor`') +
chalk.red(' first to generate it, then try again.'))
/* eslint-enable no-console */
process.exit(1)
}
let plugins = [
new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: vendorManifest,
}),
new HtmlWebpackPlugin({
analyticsKey,
template: path.join(PATHS.app, 'shell', 'index.html'),
filename: 'index.html',
inject: 'body',
applicationPath,
htmlLinkPath,
}),
new AddAssetHtmlPlugin({
filepath: path.join(PATHS.build, 'vendor.dll.js'),
includeSourcemap: false,
}),
new IgnorePlugin(/^\.\/locale$/, /moment$/),
new LodashReplacePlugin(),
new webpack.DefinePlugin({
CDN_URL: JSON.stringify(VALUES.baseCdnUrl),
}),
]
const baseConfig = {
entry: {
index: ['core-js/stable', PATHS.app],
},
plugins,
resolve: {
modules: [
PATHS.app,
'node_modules',
],
alias: {
videos: path.resolve(__dirname, '../app/videos/'),
sharedStyles: path.resolve(__dirname, '../app/sharedStyles/'),
images: path.resolve(__dirname, '../app/images/'),
animated: path.resolve(__dirname, '../app/animated/'),
}
},
module: {
rules: loaderRules,
},
optimization: {
namedModules: true,
splitChunks: {
chunks: "all"
},
runtimeChunk: true,
concatenateModules: true,
},
output: {
path: PATHS.build,
filename: '[name]_bundle.js',
chunkFilename: '[name]_chunk.js',
},
}
module.exports = baseConfig
I've also tried to add a plugin to resolve from Babel, but without much luck:
{
"presets": [
["#babel/preset-env", {
"targets": {
"ie": 11
},
"modules": false
}],
"#babel/preset-react",
],
"plugins": [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-export-default-from",
["module-resolver", {
"root": ["./app"],
"alias": {
"videos": "./app/videos/",
"sharedStyles": "./app/sharedStyles/",
"images": "./app/images/",
"animated": "./app/animated/"
}
}]
]
}
The application is launched by node server.js where server.js looks like (simplified):
const port = 8080
const path = require('path')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const webpackConfigLocal = require('../webpack/config.local')
...
app.use(bodyParser.json())
router.use(webpackDevMiddleware(compiler, {
publicPath: '/',
logLevel: 'debug',
stats: {
colors: true,
hash: false,
version: true,
timings: false,
assets: false,
chunks: false,
modules: false,
reasons: false,
children: false,
source: false,
errors: true,
errorDetails: true,
warnings: true,
publicPath: false,
},
}))
router.use(webpackHotMiddleware(compiler))
...
app.listen(port, () => console.log(`Development server listening on port ${port}`))
I'm running out of ideas and might have to revert Webpack, Babel and all related plugins and packages back to the previous version instead.
I wonder if there is someone out there who might spot what's wrong or provide any hints or ideas on how to fix this!
Thank you!
I got back to this issue and noticed that at some point past 0.28.x css-loader requires the prefix ~ for aliases.
Find "To import styles from a node_modules path (include resolve.modules) and for alias, prefix it with a ~" in https://github.com/webpack-contrib/css-loader

How to make ASP.NET Core 2 work with Webpack 4 and hot reloading

I'm trying to use ASP.NET Core 2 with Webpack 4 and React and I would love hot reloading. Problem is; when I try to make a change to one of the files it comes back with this error in Chrome:
:8100/dist/__webpack_hmr Failed to load resource: net::ERR_INCOMPLETE_CHUNKED_ENCODING.
My package.json:
{
"name": "ui",
"private": true,
"version": "0.1.0",
"license": "UNLICENSED",
"description": "Application",
"devDependencies": {
"#types/history": "4.6.0",
"#types/jquery": "3.3.1",
"#types/jsonwebtoken": "^7.2.6",
"#types/lodash": "4.14.105",
"#types/moment": "2.13.0",
"#types/query-string": "^5.1.0",
"#types/react": "^16.0.40",
"#types/react-dates": "16.0.5",
"#types/react-dom": "^15.5.1",
"#types/react-redux": "^4.4.45",
"#types/react-router": "4.0.12",
"#types/react-router-dom": "4.0.5",
"#types/react-router-redux": "5.0.3",
"#types/webpack": "2.2.15",
"#types/webpack-env": "1.13.0",
"airbnb-prop-types": "2.8.1",
"aspnet-prerendering": "3.0.1",
"aspnet-webpack": "2.0.1",
"aspnet-webpack-react": "3.0.0",
"awesome-typescript-loader": "3.2.1",
"bootstrap": "4.0.0",
"css-loader": "^0.28.11",
"domain-task": "3.0.3",
"event-source-polyfill": "0.0.9",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "1.1.11",
"glob": "^7.1.2",
"history": "4.6.3",
"install": "0.10.4",
"jquery": "3.2.1",
"jquery-mask-plugin": "1.14.15",
"jsonwebtoken": "^8.2.0",
"lodash": "4.17.5",
"moment": "2.21.0",
"muicss": "0.9.38",
"myriad-font": "0.0.2",
"node-noop": "1.0.0",
"node-sass": "^4.7.2",
"numbro": "2.0.5",
"path": "0.12.7",
"popper.js": "1.14.1",
"postcss-cssnext": "^3.1.0",
"postcss-loader": "2.1.1",
"prop-types": "15.6.1",
"query-string": "^6.0.0",
"react": "^16.2.0",
"react-addons-css-transition-group": "15.6.2",
"react-cookie": "^2.1.4",
"react-dom": "^16.2.0",
"react-moment": "0.7.0",
"react-moment-proptypes": "1.5.0",
"react-redux": "^5.0.7",
"react-router-dom": "4.1.1",
"react-router-redux": "^5.0.0-alpha.9",
"redux": "3.7.1",
"redux-thunk": "2.2.0",
"rxjs": "5.5.7",
"sass-loader": "^6.0.7",
"sfcookies": "^1.0.2",
"source-map-loader": "0.2.3",
"style-loader": "^0.18.2",
"tslint": "^5.9.1",
"tslint-react": "^3.5.1",
"typescript": "^2.7.2",
"url-loader": "1.0.1",
"webpack": "^4.2.0",
"webpack-cli": "^2.0.13",
"webpack-hot-middleware": "^2.21.2",
"webpack-merge": "4.1.2"
},
"scripts": {
"compile-vendor": "webpack --config webpack.config.vendor.js",
"compile-client": "webpack --config webpack.config.js"
},
"dependencies": {
"#types/react-hot-loader": "^3.0.6",
"react-hot-loader": "^3.1.1"
}
}
And my webpack.config.js:
"use strict";
const path = require('path');
const webpack = require('webpack');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const merge = require('webpack-merge');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const glob = require('glob');
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
// Configuration in common to both client-side and server-side bundles
const sharedConfig = () => ({
mode: !(env && env.prod) ? 'development' : 'production',
stats: { modules: false },
resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
output: {
filename: '[name].js',
publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
{
test: /\.tsx?$/,
include: /ClientApp/,
use: 'awesome-typescript-loader?silent=false'
},
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
loader: "file-loader",
options: {
limit: 50000,
name: "./img/[name].[ext]"
}
},
{
// Match woff2 in addition to patterns like .woff?v=1.1.1.
test: /\.(woff|woff2|ttf)(\?v=\d+\.\d+\.\d+)?$/,
loader: "file-loader",
options: {
limit: 50000,
name: "./fonts/[name].[ext]"
}
}
]
},
performance: {
hints: false
},
devtool: 'cheap-module-source-map',
plugins: [new CheckerPlugin()]
});
// Configuration for client-side bundle suitable for running in browsers
const clientBundleOutputDir = './wwwroot/dist';
const clientBundleConfig = merge(sharedConfig(), {
entry: {
"main-client": ['./ClientApp/boot-client.tsx'].concat(glob.sync('./ClientApp/img/**/*.svg'))
},
module: {
rules: [
{
test: /\.(scss|css)$/,
loader: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
{
loader: "css-loader",
options: {
importLoaders: 1
}
},
"postcss-loader"
]
}),
exclude: /node_modules/
}
]
},
output: { path: path.join(__dirname, clientBundleOutputDir) },
plugins: [
new ExtractTextPlugin("site.css"),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./wwwroot/dist/vendor-manifest.json')
}),
new webpack.NamedModulesPlugin()
]
});
return [clientBundleConfig];
};

State of the art webpack / React configuration

I'm trying to setup a webpack 2, babel, and React configuration for achieving:
Native ES6/ES7 features
Tree shaking builds
Hot reloading
I had a demo repo but it has distinct stuff mixed, like even JSHint and ESLint at the same time.
I'd like to get my setup up and running and get suggestions for best practices
So, as first option I tried to use babel-preset-env. Then after some dependencies being installed. I ran into this issue:
ERROR in ./src/main.jsx
Module build failed: SyntaxError: 'import' and 'export' may only appear at the top level (3:0)
However, the first line in my code is import 'babel-polyfill'; then just import's.
This is how my Babel config file looks like:
{
"presets": [
[
"env",
{
"modules": false,
"targets": {
"browsers": ["last 2 versions"]
}
}
],
"react"
],
"plugins": [
"babel-plugin-transform-class-properties",
"transform-react-require"
]
}
This is what my development webpack config file looks like:
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const path = require('path');
const buildPath = path.resolve(__dirname, 'build');
const nodeModulesPath = path.resolve(__dirname, 'node_modules');
const TransferWebpackPlugin = require('transfer-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const config = {
//Entry points to the project
entry: [
'babel-polyfill',
'webpack/hot/dev-server',
'webpack/hot/only-dev-server',
path.join(__dirname, '../src/main.jsx')
],
//Config options on how to interpret requires imports
resolve: {
extensions: [".js", ".jsx"]
},
//Server Configuration options
devServer:{
contentBase: 'build', //Relative directory for base of server
devtool: 'eval',
hot: true, //Live-reload
inline: true,
port: 3000, //Port Number
host: 'localhost', //Change to '0.0.0.0' for external facing server
proxy: {
'^\/api': {
target: 'http://127.0.0.1:9090'
}
},
historyApiFallback: true
},
devtool: 'eval',
output: {
path: buildPath, //Path of output file
filename: 'app.js'
},
plugins: [
new webpack.DefinePlugin({
API_BASE: '""',
PRODUCTION: false,
'process.env.NODE_ENV': '"development"'
}),
//Enables Hot Modules Replacement
new webpack.HotModuleReplacementPlugin(),
//Allows error warnings but does not stop compiling. Will remove when eslint is added
new webpack.NoEmitOnErrorsPlugin(),
//Moves files
new TransferWebpackPlugin([
{from: 'www'}
], path.resolve(__dirname, "src")),
new ExtractTextPlugin("main.css")
],
module: {
rules: [
{
//React-hot loader and
test: /\.(js|jsx)$/, //All .js and .jsx files
loaders: [ 'babel-loader', 'react-hot-loader'],
//react-hot is like browser sync and babel loads jsx and es6-7
exclude: [nodeModulesPath]
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: 'style',
use: 'css'
})
},
{
test: /\.svg$/,
loader: 'svg-sprite?' + JSON.stringify({
name: '[name]_[hash]',
prefixize: true
})
}
]
}
};
module.exports = config;
And this below is package.json
{
"name": "LumaHealth",
"version": "1.0.0",
"description": "LumaHealth",
"main": "start.js",
"scripts": {
"start": "webpack --config ./webpack/webpack.config.development.js",
"build": "webpack --config ./webpack/webpack.config.production.js",
"clean": "rm build/app.js"
},
"repository": {
"type": "git",
"url": "git#github.com:lumahealthhq/web-app.git"
},
"keywords": [],
"author": "Marcelo Oliveira",
"license": "MIT",
"devDependencies": {
"babel-cli": "^6.24.0",
"babel-core": "^6.24.0",
"babel-eslint": "^7.2.1",
"babel-plugin-react-require": "^3.0.0",
"babel-plugin-transform-class-properties": "^6.23.0",
"babel-preset-env": "^1.2.2",
"babel-preset-react": "^6.23.0",
"css-loader": "^0.26.4",
"enzyme": "^2.0.0",
"eslint": "^3.7.1",
"eslint-config-airbnb": "^14.1.0",
"eslint-loader": "^1.7.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.4.1",
"extract-text-webpack-plugin": "^2.1.0",
"html-webpack-plugin": "^2.28.0",
"nyc": "^10.1.2",
"postcss-loader": "^1.3.3",
"postcss-nested": "^1.0.0",
"react-addons-test-utils": "^15.4.1",
"sinon": "^1.17.2",
"style-loader": "^0.13.2",
"sw-precache": "^5.0.0",
"transfer-webpack-plugin": "^0.1.4",
"webpack": "^2.3.2",
"webpack-dev-server": "^2.4.2"
},
"dependencies": {
"babel-core": "^6.5.2",
"babel-eslint": "^7.0.0",
"babel-plugin-transform-react-require": "^1.0.1",
"babel-polyfill": "^6.23.0",
"co": "^4.6.0",
"express": "^4.12.3",
"file-loader": "^0.10.1",
"humps": "^2.0.0",
"isomorphic-fetch": "^2.2.1",
"local-storage": "^1.4.2",
"lodash": "^4.16.4",
"material-ui": "^0.17.0",
"moment": "^2.15.2",
"q": "^1.4.1",
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-redux": "^5.0.3",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.6",
"react-slick": "^0.14.4",
"react-tap-event-plugin": "^2.0.0",
"react-web-notification": "^0.2.3",
"redux": "^3.6.0",
"redux-form": "^6.1.1",
"redux-logger": "^2.7.0",
"redux-socket.io": "^1.3.1",
"redux-thunk": "^2.1.0",
"socket.io-client": "^1.7.2",
"url-loader": "^0.5.7",
"vanilla-masker": "^1.0.9"
}
}
I recently upgraded my boilerplate from webpack 1 to webpack 2, feel free to get any information / concept from the webpack config file there, hope it helps.
https://github.com/iroy2000/react-redux-boilerplate

Resources