Angular Module Federation -- Shared module is not available for eager consumption - javascript

Getting this issue when trying to run tests on my Angular microfrontend to use inside Module Federation. Angular 12, Webpack 5.
Uncaught Error: Shared module is not available for eager consumption: 5487
How to configure eager consumption for these modules?

In most cases, solve this issue by setting eager: true on your shared common Angular modules:
shared: share({
"#angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto', eager: true },
"#angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto', eager: true },
"#angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto', eager: true },
"#angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto', eager: true },

Create a separate webpack.conf for testing
You can set all shared modules to eager: true in your primary webpack.config.js, but that would force you to use a larger bundle size, one of the things Module Federation aims to avoid.
A better option could be to set up a separate webpack.test.config.js, which will just be used for running tests, and in that file set your modules to eager: true:
webpack.test.config.js
shared: share({
"#angular/core": {
eager: true,
singleton: true,
strictVersion: true,
requiredVersion: 'auto'
},
"#angular/common": {
eager: true,
singleton: true,
strictVersion: true,
requiredVersion: 'auto'
},
"#angular/common/http": {
eager: true,
singleton: true,
strictVersion: true,
requiredVersion: 'auto'
}
})

Related

Module Federation Material shared dependency issue (Nextjs as host, React as Remote)

App Structure
I'm using Next JS in Host app and React JS in remote app. Both apps are using below library as dependency
Note
I'm using ModuleFederationPlugin for both app and not using Next Js Specific module federation plugin
Remote app deps
"#mui/icons-material": "^5.11.0",
"#mui/material": "^5.11.4",
"#mui/styles": "^5.11.2",
"#emotion/react": "^11.10.5",
"#emotion/styled": "^11.10.5",
Host app deps
"#emotion/react": "^11.10.4",
"#emotion/styled": "^11.10.4",
"#mui/icons-material": "^5.10.9",
"#mui/lab": "^5.0.0-alpha.103",
"#mui/material": "^5.10.9",
"#mui/styles": "^5.10.9",
Problem Statement
I'm having a problem when trying to share material related module in Host app. When running host app, it shown below error.
I don't want to add eager: true in material related dependencies since its ended up creating large initial chunk which I don't want. Also removing material related dependencies from Host app seems not a good idea because then multiple instance warning is showing.
The remote app is also configured as shown here
Please share some thought on how to share these deps in an optimised way.
Error Screenshot
Host app shared config (Next JS App)
const dotenvFile = `.env.${process.env.DOTENV_RUNTIME || 'local'}`
require('dotenv').config({ path: dotenvFile })
const deps = require('../../package.json').dependencies
module.exports = {
distDir: '../../dist/client',
async rewrites() {
/*
This rewrites method is needed to persist route state while using MFE.
Keep adding base route here when onboarding new MFE App
*/
return [ ]
},
webpack: (config, { webpack, isServer }) => {
const { ModuleFederationPlugin } = webpack.container
if (!isServer) {
config.plugins.push(
new webpack.IgnorePlugin({
resourceRegExp: /urlencoded-body-parser/,
}),
new ModuleFederationPlugin({
name: 'Host ui',
remotes: {},
shared: {
react: {
eager: true,
singleton: true,
requiredVersion: deps.react,
},
'react-dom': {
eager: true,
singleton: true,
requiredVersion: deps['react-dom'],
},
'#mui/materia': {
requiredVersion: deps['#mui/materia'],
singleton: true,
},
'#mui/icons-material': {
requiredVersion: deps['#mui/icons-material'],
singleton: true,
},
'#mui/styles': {
requiredVersion: deps['#mui/styles'],
singleton: true,
},
'#emotion/react': {
requiredVersion: deps['#emotion/react'],
singleton: true,
},
},
}),
)
}
return config
},
}
Remote app shared config (React JS App)
shared: {
react: {
requiredVersion: deps.react,
singleton: true,
},
'react-dom': {
requiredVersion: deps['react-dom'],
singleton: true,
},
'react-router': {
requiredVersion: deps['react-router'],
singleton: true,
},
'react-router-dom': {
requiredVersion: deps['react-router-dom'],
singleton: true,
},
'#mui/materia': {
requiredVersion: deps['#mui/materia'],
singleton: true,
},
'#mui/icons-material': {
requiredVersion: deps['#mui/icons-material'],
singleton: true,
},
'#mui/styles': {
requiredVersion: deps['#mui/styles'],
singleton: true,
},
'#emotion/react': {
requiredVersion: deps['#emotion/react'],
singleton: true,
},
},
Github Issue link - https://github.com/module-federation/module-federation-examples/issues/2740
I have tried adding eager:true in Host app but its making initial chunk 5 MB which is not expected. My expectation is my configuration works without adding eager key in any app.

All styled components return any (#types/styled-components)

I'm having a weird issue when using styled-components along with VSCode. Below is basically what I get for any components coming from styled-components, they all return any.
I got it working before, but can't tell when and I can't see what's wrong in the setup to return any for all the components. I tried to move back to tslint config, removing/commenting out all rules inside the eslintrc files, but couldn't make it work either.
Supprisingly enough, I tried the starter kit I'm using for my project and the types there are working with the original setup.
I tried to use the same version of styled-components packages, but still couldn't make it work. Any help, or direction to look at this issue would be very welcomed!
.eslintrc.js
module.exports = {
env: {
browser: true,
es6: true,
},
extends: [
'plugin:#typescript-eslint/recommended',
'plugin:#typescript-eslint/recommended-requiring-type-checking',
'plugin:react/recommended',
'prettier/#typescript-eslint',
],
parser: '#typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
sourceType: 'module',
ecmaFeatures: { jsx: true },
},
plugins: ['#typescript-eslint', 'react', 'react-native'],
rules: {
camelcase: 'off',
'react/display-name': 'off',
'react/prop-types': 'off',
'#typescript-eslint/ban-ts-ignore': 'off',
'#typescript-eslint/camelcase': 'off',
'#typescript-eslint/explicit-function-return-type': 'off',
'#typescript-eslint/interface-name-prefix': 'off',
'#typescript-eslint/no-explicit-any': 'off',
'#typescript-eslint/no-use-before-define': 'off',
'#typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'#typescript-eslint/no-non-null-assertion': 'off',
'#typescript-eslint/unbound-method': 'off',
'#typescript-eslint/no-unsafe-assignment': 'off',
'#typescript-eslint/no-unsafe-call': 'off',
'#typescript-eslint/no-unsafe-member-access': 'off',
'#typescript-eslint/no-unsafe-return': 'off',
'#typescript-eslint/no-misused-promises': [
'error',
{
checksVoidReturn: false,
},
],
'#typescript-eslint/explicit-module-boundary-types': ['error', { allowArgumentsExplicitlyTypedAsAny: true }],
},
settings: {
react: {
pragma: 'React',
version: 'detect',
},
},
ignorePatterns: ['node_modules/**/*', 'docs/**/*', 'examples/**/*', 'lib/**/*'],
};
tsconfig.json
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"baseUrl": "./src",
"experimentalDecorators": true,
"inlineSources": true,
"jsx": "react",
"lib": ["es2017", "dom"],
"module": "commonjs",
"moduleResolution": "node",
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"plugins": [
{
"name": "typescript-styled-plugin",
"lint": {
"validProperties": [
"shadow-color",
"shadow-opacity",
"shadow-offset",
"shadow-radius",
"padding-horizontal",
"padding-vertical",
"margin-vertical",
"margin-horizontal",
"tint-color",
"aspect-ratio",
"elevation"
]
}
}
],
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"sourceRoot": "./src",
"strict": true,
"strictPropertyInitialization": false,
"suppressImplicitAnyIndexErrors": true,
"target": "es2015"
},
"include": [".eslintrc.js", "src/**/*.ts", "src/**/*.tsx"]
}
"lint": "yarn format && yarn eslint && yarn stylelint",
"eslint": "tsc -p . --noEmit --skipLibCheck; eslint --fix 'src/**/*.{ts,tsx}'",
...
"#typescript-eslint/eslint-plugin": "3.8.0",
"#typescript-eslint/parser": "3.8.0",
"eslint": "7.6.0",
"eslint-config-prettier": "6.11.0",
"eslint-plugin-react": "7.20.5",
"eslint-plugin-react-native": "3.8.1",
styled.d.ts
import 'styled-components';
declare module 'styled-components' {
// tslint:disable-next-line
export interface DefaultTheme {
darkMode: boolean;
background: string;
lightBackground: string;
grayBackground: string;
darkBackground: string;
heading: string;
subheading: string;
copy: string;
stroke: string;
underlay: string;
map: string;
}
}
This is how I solved it -
after navigating to the types file of styled-components inside the project I saw this error: node_modules/hoist-non-react-statics/index"' has no exported member 'NonReactStatics'. ts
It turned out that I had packages using an older version of hoist-non-react-static, and it was overriding the types being used by styled-components.
upgrading those packages (in my case it was react-redux) solved the problem.
Types got quietly moved to #types/styled-components-react-native. Still good to update your other dependencies, of course :)
Reference: https://github.com/styled-components/styled-components/issues/2099

Specify env option for ES7

For using ES6 in the environment, I have to specify the .eslintrc file as:
"env": {
"node": false,
"browser": true,
"amd": true,
"mocha": true,
"jasmine": false,
"es6": true
}
But what when I want to use ES7, can I just:
"env": {
"node": false,
"browser": true,
"amd": true,
"mocha": true,
"jasmine": false,
"es7": true
}
?
For information, I looked at https://eslint.org/docs/user-guide/configuring but did not get the answer.
Update
My current file eslint file looks as following:
{
"globals": {
"com": true,
"oData": false,
"sakp": false,
"fin": true,
"cloud": true,
"bsuite": false,
"cordova": false,
"ui": true,
"webide": false,
"asyncTest": false,
"i2d": true,
"gltrade": false,
"drilldown": true,
"opaTest": false,
"ux": true,
"test": false,
"$": false,
"module": false,
"ai": false,
"notEqual": false,
"notDeepEqual": false,
"throws": false,
"ssuite": false,
"deepEqual": false,
"s2p": false,
"Promise": false,
"ehs": false,
"sinon": false,
"stop": false,
"util": true,
"slo": false,
"mdm": false,
"mytravelandexpense": false,
"strictEqual": false,
"cec": false,
"cus": false,
"notStrictEqual": false,
"fscm": false,
"fm": true,
"nw": true,
"shcm": false,
"fcg": true,
"URI": false,
"fs": true,
"retail": false,
"d3": false,
"hcm": false,
"oil": true,
"assert": false,
"hpa": false,
"ok": false,
"sap": true,
"QUnit": false,
"cross": true,
"srm": false,
"equal": false,
"expect": false,
"jQuery": false,
"publicservices": true,
"uxcc": false,
"equals": false,
"tl": false,
"travel": true
},
"env": {
"node": false,
"browser": true,
"amd": true,
"mocha": true,
"jasmine": false,
"es6": true
}
}
Where to specify es7?
To control which edition of syntax is allowed, you'll want to set the ecmaVersion under parserOptions:
{
"env": {
"node": false,
"browser": true,
"amd": true,
"mocha": true,
"jasmine": false,
"es6": true
},
"parserOptions": {
"ecmaVersion": 2016
}
}
The value can either be the year or edition number of the specification (e.g. ECMAScript 2018 and the 9th edition have the same effect).

Grunt JSHint works well only with 0.9.2

I got grunt-contrib-jshint to validate JS files. Problem arises when I change jshint version to other than 0.9.2. Configuration Gruntfile.js
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: [
'Gruntfile.js',
'<%= config.app %>/scripts/**/*.js',
'!<%= config.app %>/content_scripts/coffee/*'
]
}
and .jshintrc
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": false,
"unused": false,
"strict": false,
}
So when I update to newest version 0.11.2 JSHint works but shows No problems while on 0.9.2 shows couple of various error.
Please help.

Using underscore with jshint

I'm using the underscore library.
I get this when running jshint:
[L38:C38] W117: '_' is not defined.
var approvedAndRequstedCount = _.countBy(products, function(obj) {
Warning: Task "jshint:all" failed. Use --force to continue.
This is my config file:
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"camelcase": false,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"globals": {
"angular": false
}
}
I guess it's something with the globals option? I tried to add "_": false but no luck. Any ideas?
I had this issue as well.
I installed underscore: bower install -save underscore and it worked fine in the code. Unfortunately jshint was not finding that reference. You must tell jshint about your global variables in configuration file like .jshintrc:
{
…
"globals": {
"angular": false,
"_": false
}
}
If you continue to have this issue you need to make sure that underscore is included when jshint is executed. I would not recommend setting -W117 to true. Squelching those errors might lead to more bugs.

Categories

Resources