Configuration.resolve has an unknown property 'fallback'. These properties are valid: - reactjs

I got this error in my react project.
Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.resolve has an unknown property 'fallback'. These properties are valid:
object { alias?, aliasFields?, cachePredicate?, cacheWithContext?, concord?, descriptionFiles?, enforceExtension?, enforceModuleExtension?, extensions?, fileSystem?, mainFields?, mainFiles?, moduleExtensions?, modules?, plugins?, resolver?, symlinks?, unsafeCache?, useSyncFileSystemCalls? }
-> Options for the resolver
I have try to build react pdf for my project. I have used craco for resolving errors caused by re
var webpack = require("webpack");
module.exports = {
webpack: {
configure: {
resolve: {
fallback: {
process: require.resolve("process/browser"),
zlib: require.resolve("browserify-zlib"),
stream: require.resolve("stream-browserify"),
util: require.resolve("util"),
buffer: require.resolve("buffer"),
asset: require.resolve("assert"),
},
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
process: "process/browser",
}),
],
},
},
};
act pdf. Here is my code.

Related

Storybook can't process TS files outside of the project

I have noticed that Storybook can't process Typescript files if they are from another project (monorepo), but it is doing okay with TS files that are within its project.
How do I configure Storybook to handle TS files outside the project?
Structure of the monorepo:
package1
.storybook
main.ts
preview.ts
component.tsx (this component imports file.ts)
component.stories.tsx
package2
file.ts <- (Storybook can't process this file: ModuleParseError: Module parse failed: Unexpected token)
Here is the main.ts config file:
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const path = require('path');
const toPath = (filePath) => path.join(process.cwd(), filePath);
module.exports = {
"stories": [
"../src/**/*.stories.#(mdx|js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/addon-interactions",
"#storybook/addon-knobs/register",
"#storybook/preset-create-react-app",
"#storybook/addon-a11y",
'storybook-addon-styled-component-theme/dist/preset',
'storybook-addon-themes',
"storybook-dark-mode",
],
"framework": "#storybook/react",
"core": {
"builder": "#storybook/builder-webpack5",
"disableTelemetry": true,
},
features: {
emotionAlias: false,
},
typescript: { reactDocgen: false },
webpackFinal: async (config, { configType }) => {
return {
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve.alias,
'#emotion/core': toPath('node_modules/#emotion/react'),
'emotion-theming': toPath('node_modules/#emotion/react'),
},
plugins: [new TsconfigPathsPlugin()]
},
}
}
}
Here is the error:
ModuleParseError: Module parse failed: Unexpected token (7:11)
File was processed with these loaders:
* ../../node_modules/#pmmmwh/react-refresh-webpack-plugin/loader/index.js
You may need an additional loader to handle the result of these loaders.
| import { Palette as palette } from '../Palette';
|
> const Paper: any = [
| {
If I import the same TS file, but manually precompiled into regular JS - Storybook works.
I have no idea what to try to solve this :(
Add this to .storybook/main.js
webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
// Storybook uses its own webpack config, so we need to merge our config with it
// See https://storybook.js.org/docs/configurations/custom-webpack-config/
// Add typescript loader to process TS-files from other packages
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: require.resolve("ts-loader"),
options: {
reportFiles: [
"../**/src/**/*.{ts,tsx}"
]
}
},
]
});
config.resolve.extensions.push(".ts", ".tsx");
return config;
}

Webpack Module Federation loads chunks from wrong URL

I am building a project with webpack module federation with the following setup:
React host (running on localhost:3000)
Angular Remote 1 (running on localhost:4201)
Angular Remote 2 (running on localhost:4202)
The goal is to get both remotes working. If I only run one of the and remove the other it is working perfectly.
The issue I am facing is that when the remotes are loaded, __webpack_require__.p is set by one of the remotes' script and therefore the other remote's chunk is loaded from the wrong url.
Here is the error I get:
My module federation config is the following:
React host:
.
.
.
new ModuleFederationPlugin({
name: "react_host",
filename: "remoteEntry.js",
remotes: {
angular_remote_1: "angular_remote_1#http://localhost:4201/angular_remote_1.js",
angular_remote_2: "angular_remote_2#http://localhost:4202/angular_remote_2.js"
},
exposes: {},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
},
},
}),
.
.
.
Angular Remote 1
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
output: {
publicPath: "auto",
uniqueName: "angular_remote_1",
scriptType: "text/javascript"
},
optimization: {
runtimeChunk: false
},
experiments: {
outputModule: true
},
plugins: [
new ModuleFederationPlugin({
name: "angular_remote_1",
library: { type: "var", name: "angular_remote_1" },
filename: "angular_remote_1.js",
exposes: {
'./angularRemote1': './src/loadAngularRemote1.ts',
},
shared: ["#angular/core", "#angular/common", "#angular/router"]
})
],
};
Angular Remote 2
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
module.exports = {
output: {
publicPath: "auto",
uniqueName: "angular_remote_2",
scriptType: "text/javascript"
},
optimization: {
runtimeChunk: false
},
experiments: {
outputModule: true,
},
plugins: [
new ModuleFederationPlugin({
name: "angular_remote_2",
library: { type: "var", name: "angular_remote_2" },
filename: "angular_remote_2.js",
exposes: {
'./angularRemote2': './src/loadAngularRemote2.ts',
},
shared: ["#angular/core", "#angular/common", "#angular/router"]
})
],
};
Thins I have tried so far:
Playing around with public path (between auto and hardcoded)
Setting a custom chunkLoadingGlobal for both remotes (not the host)
The exact reproduction of this issue can be found here: https://github.com/BarniPro/react-host-angular-remotes-microfrontend
Any help is greatly appreciated.
The issue can be solved by setting the topLevelAwait experiment to true in the remotes's webpack.config.js:
experiments: {
topLevelAwait: true,
},
This results in the two remotes loading in sync which prevents the paths from overriding each other.
Another update I had to make was disabling the splitChunks option in the remotes' optimization settings (see SplitChunksPlugin):
optimization: {
runtimeChunk: false, // This is also needed, but was added in the original question as well
splitChunks: false,
}
The Github repo has been updated with the working solution.

Gatsby + React-pdf

I'm trying to get react-pdf to work in gatsby and something is wonky with my webpack config. Tried different ways from different posts but nothing seems to do the trick.
if I remove 'process/browser', the site builds fine but the PDF doesn't render and I get the error that process is not defined. If I leave it in, the site won't build at all.
/gatsby-node.js
const webpack = require("webpack");
exports.onCreateWebpackConfig = ({ stage, loaders, actions, plugins }) => {
if (stage === "build-html" || stage === "develop-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /react-pdf/, // check /pdfjs-dist/ too
use: loaders.null()
},
{
test: /pdfjs-dist/, // check /pdfjs-dist/ too
use: loaders.null()
}
]
}
});
}
actions.setWebpackConfig({
resolve: {
fallback: {
module: "empty",
dgram: "empty",
dns: "mock",
fs: "empty",
http2: "empty",
net: "empty",
tls: "empty",
child_process: "empty",
process: require.resolve("process/browser"),
zlib: require.resolve("browserify-zlib"),
stream: require.resolve("stream-browserify"),
util: require.resolve("util"),
buffer: require.resolve("buffer"),
asset: require.resolve("assert")
}
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ["buffer", "Buffer"],
process: "process/browser"
})
]
});
};
I've also tried moving the process/browser part into the stage check:
...
if (stage === "build-html" || stage === "develop-html") {
actions.setWebpackConfig({
plugins: [
new webpack.ProvidePlugin({
process: "process/browser"
})
]
});
}
...
but that doesn't seem to work either :/
I feel like I just need a little tweak here but for the life of me I can't figure out what. Any ideas?
Found the missing thing.. Had to add safer-buffer to the loaders:
actions.setWebpackConfig({
module: {
rules: [
{
test: /safer-buffer/,
use: loaders.null()
}
]
}
});

Storybook couldn't resolve fs

I am setting up a Storybook with RemixJS. I got the following error when trying to import a component
ERROR in ./node_modules/#remix-run/node/errors.js
Module not found: Error: Can't resolve 'fs' in '/Users/ht/Desktop/a/node_modules/#remix-run/node'
ERROR in ./node_modules/#remix-run/node/node_modules/source-map/lib/read-wasm.js
Module not found: Error: Can't resolve 'fs' in '/Users/ht/Desktop/a/node_modules/#remix-run/node/node_modules/source-map/lib'
ERROR in ./node_modules/#remix-run/node/sessions/fileStorage.js
Module not found: Error: Can't resolve 'fs' in '/Users/ht/Desktop/a/node_modules/#remix-run/node/sessions'
ERROR in ./node_modules/busboy/lib/main.js
Module not found: Error: Can't resolve 'fs' in '/Users/ht/Desktop/a/node_modules/busboy/lib'
ERROR in ./node_modules/#remix-run/node/errors.js
Module not found: Error: Can't resolve 'fs/promises' in '/Users/ht/Desktop/a/node_modules/#remix-run/node'
ERROR in ./node_modules/#remix-run/node/upload/fileUploadHandler.js 124:15
Module parse failed: Unexpected token (124:15)
You may need an appropriate loader to handle this file type, currently, no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| }
| class NodeOnDiskFile {
> lastModified = 0;
| webkitRelativePath = "";
|
ERROR in ./node_modules/#remix-run/node/formData.js 53:73
Module parse failed: Unexpected token (53:73)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| get(name) {
| let arr = this._fields[name];
> return (arr === null || arr === void 0 ? void 0 : arr.slice(-1)[0]) ?? null;
| }
|
I got the suggestion that I should add this to the web pack
{
resolve: {
fallback: {
fs: false
}
}
}
How could I do it with a storybook? I use storybook version 6.4.19
I added this to .storybook/main.js but without success
webpackFinal: async (config, { configType }) => {
config.node = {
...config.node,
fs: 'empty'
};
return config;
},
Thank you
Depending on the webpack version you are using to build your Storybook you need to add fs, stream and other Node core module used by Remix packages.
As a rule of thumb you can use the list from Webpack documentation on resolve.fallback here.
If you are using Stroybook with Webpack 4 the config should look like :
module.exports = {
// Storybook config
webpackFinal: async (config, { configType }) => {
config.node = {
...config.node,
fs: "empty",
assert: "empty",
buffer: "empty",
console: "empty",
constants: "empty",
crypto: "empty",
domain: "empty",
events: "empty",
http: "empty",
https: "empty",
os: "empty",
path: "empty",
punycode: "empty",
process: "empty",
querystring: "empty",
stream: "empty",
string_decoder: "empty",
sys: "empty",
timers: "empty",
tty: "empty",
url: "empty",
util: "empty",
vm: "empty",
zlib: "empty",
};
return config;
},
};
Or with Webpack 5
module.exports = {
// Storybook config
webpackFinal: async (config, { configType }) => {
config.resolve.fallback = {
fs: false,
assert: false,
buffer: false,
console: false,
constants: false,
crypto: false,
domain: false,
events: false,
http: false,
https: false,
os: false,
path: false,
punycode: false,
process: false,
querystring: false,
stream: false,
string_decoder: false,
sys: false,
timers: false,
tty: false,
url: false,
util: false,
vm: false,
zlib: false,
};
return config;
},
};
Upgrade storybook to use webpack 5
https://gist.github.com/shilman/8856ea1786dcd247139b47b270912324
Update .storybook/main.js
module.exports = {
stories: ["../.slicemachine/assets/**/*.stories.#(js|jsx|ts|tsx)"],
addons: [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/addon-interactions",
],
framework: "#storybook/react",
core: {
builder: "webpack5",
},
webpackFinal: async (config, { configType }) => {
config.resolve = {
...config.resolve,
fallback: {
...(config.resolve || {}).fallback,
fs: false,
stream: false,
os: false,
},
}
// Return the altered config
return config
},
}

Webpack Module Federation fails with Next JS when using styled-components

I'm trying to get Webpack Module Federation working with a NextJS app where the federated module is using styled-components. My configuration is working as expected if I'm only using react and react-dom but using styled-components gives me these errors:
It looks like there are several instances of 'styled-components' initialized in this application. This may cause dynamic styles to not render properly, errors during the rehydration process, a missing theme prop, and makes your application bigger without good reason.
and
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
I have tried the different approaches to resolve styled-components to a single instance by modifying the Webpack config in both the host and remote apps, but all seem to fail.
Here is my current configuration:
Federated modules repo (webpack.config.js):
const { ModuleFederationPlugin } = require("webpack").container;
const deps = require("./package.json").dependencies;
const path = require("path");
module.exports = {
mode: "development",
devServer: {
contentBase: path.join(__dirname, "dist"),
port: 3001,
},
output: {
publicPath: "auto",
},
resolve: {
extensions: [".js"],
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
options: {
plugins: [
["babel-plugin-styled-components", { pure: true, ssr: true }],
],
presets: ["#babel/preset-react"],
},
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "remoteLib",
filename: "remoteEntry.js",
exposes: {
"./Button": "./src/Button",
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
},
"styled-components": {
singleton: true,
requiredVersion: deps["styled-components"],
},
},
}),
],
};
Consuming NextJS app Webpack config (next.config.js):
webpack: (config, options) => {
const { ModuleFederationPlugin } = options.webpack.container;
config.plugins.push(
new ModuleFederationPlugin({
remotes: {
'federated-components': 'remoteLib#http://localhost:3001/remoteEntry.js'
}
})
);
return config;
}

Resources