I have a react app that I need to run inside a NextJS host app and run on it's own.
In the NextJS example at https://github.com/module-federation/module-federation-examples/tree/master/nextjs-react there are notes that:
NOTE: If version: '0' is omitted, you'll encounter an issue where a copy of react will be downloaded from the remoteEntry.
NOTE: Another issue you may run into is an invalid hook call if you are federating a component that uses react hooks. This is directly related to multiple copies of react running at the same time. The above resolves this.
I have set up a remote app with ModuleFederationPlugin:
shared: {
react: {
singleton: true,
requiredVersion: false,
version: "0"
},
"react-dom": {
singleton: true,
requiredVersion: false,
version: "0"
}
}
This works when running inside a NextJS host. But when I run my federated app on its own, I get TypeError: n.n(...)(...).createContext is not a function. If I remove version: "0" then I get invalid hook call when run inside the NextJS host.
Is it possible to handle both cases, or have a fallback in case there is no react version present in shared scope?
I found that I had to add:
resolve: {
alias: {
react: path.resolve("./node_modules/react")
}
}
Related
I have working reactjs app with redux and react router.
I want to switch to preact.
When I updated webpack config to alias react and react dom.
Component started mounting infinitely. It mount then unmount .. goes on doing so.
Webpack config.
alias: {
"react": path.resolve(__dirname, 'react.js'),
"react-dom": path.resolve(__dirname, 'react.js')
},
react.js
var preact = require('preact-compat');
var react = {};
Object.keys(preact).forEach(function(key) {
react[key] = preact[key];
});
module.exports = react;
This file is because I am using react hot loader.
React app is working fine .. but adding preact has bug. pls guide me.
From my experience, preact-compat and React Hot Loader (RHL) don't work together very well (it's still on the TODO list of the developer of preact-compact, see this comment).
I work around these issues myself by not combining the two, i.e. use the "real" React and ReactDOM when I want to use RHL, or use preact-compat when I don't need RHL.
I'm currently having trouble getting my React application working in IE11. The problem seems to be that some of the newer ES6 stuff isn't available in IE11. So my goal is to polyfill the missing functionality. I'm using nwb [1] which is a zero-configuration setup for React applications. However, I'm unsure how to configure Babel (or Webpack ?) to polyfill certain methods like Array.from. It looks like fetch, Promise, and Object.assign are all polyfill-ed but not Array.from for example. Any help would be greatly appreciated.
Here is my nwb.config file:
module.exports = {
type: 'react-app',
webpack: {
define: {
VERSION: JSON.stringify(require('./package.json').version),
HOSTNAME: JSON.stringify(process.env.NODE_ENV === 'production' ?
'https://xyz.azurewebsites.net' :
'http://localhost:8080')
},
rules: {
babel: {
test: /\.jsx?/
}
},
extra: {
resolve: {
extensions: ['.jsx']
},
devtool: '#inline-source-map'
},
html: {
favicon: 'src/img/favicon.ico'
}
}
};
Thanks,
[1] A toolkit for React app. https://github.com/insin/nwb
Sounds like you need to add babel-polyfill to your project.
This will emulate a full ES2015+ environment and is intended to be
used in an application rather than a library/tool. This polyfill is
automatically loaded when using babel-node.
This means you can use new built-ins like Promise or WeakMap, static
methods like Array.from or Object.assign, instance methods like
Array.prototype.includes, and generator functions (provided you use
the regenerator plugin). The polyfill adds to the global scope as well
as native prototypes like String in order to do this.
The easiest way for you would probably be to import it at the top of your main js file:
import 'babel-polyfill';
How do you completely disable or hide the "persistent" console message: Download the React DevTools for a better development experience while in development?
As of React 16.2.0, you can add a line like this to your webpack configuration:
new webpack.DefinePlugin({
'__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })'
}),
If not using webpack you can put, somewhere in a module imported before react:
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = { isDisabled: true };
This disables all logs about React DevTools.
Put this line somewhere in the global scope (it won't work if you put it inside a bundled module):
__REACT_DEVTOOLS_GLOBAL_HOOK__ = true;
Here's a related gist from Ryan Florence that's the basis for the above hack:
if (
process.env.NODE_ENV === 'production' &&
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ &&
Object.keys(window.__REACT_DEVTOOLS_GLOBAL_HOOK__._renderers).length
) {
window.__REACT_DEVTOOLS_GLOBAL_HOOK__._renderers = {}
}
Update: React 16 has a new console warning that reads Warning: The installed version of React DevTools is too old and will not work with the current version of React. Please update React DevTools. To disable it, put this code in the global scope:
__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
supportsFiber: true,
inject: function() {},
onCommitFiberRoot: function() {},
onCommitFiberUnmount: function() {},
};
Put something like that in your html
<script>{`
(function() {
var info = console.info
console.info = function (message) {
if (!/Download the React DevTools/.test(message)) info.apply(console, arguments)
}
})()
`}</script>
If you use Storybook with Angular or Vue, or any other framework - the message "Download the React DevTools for a better development experience:" in the devtools does't make any sense. And even for folks who use React - it may be annoying.
I tried all answers in this thread, however, they don't really work anymore. Even the accepted answer is no valid anymore. So, this is what works right now for Storybook 6+ and Webpack 4/5:
The message comes from the Storybook Manager (which is created with React I guess). Create file manager.js in your .storybook dir. It should be a sibling of your other storybook config files, e.g. main.js, privew.js, etc..
Add the following code to disable a range of React messages:
// .storybook/manager.js
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
_renderers: {},
supportsFiber: true,
inject: () => ({}),
onCommitFiberRoot: () => ({}),
onCommitFiberUnmount: () => ({}),
};
Re-run your build and the message should disappear. This will also remove another warning from React: The installed version of React DevTools is too old and will not work with the current version of React
Here's a solution for Next.JS (works with 12.1.6 at time of writing):
In your project root, add the following lines to next.config.js:
module.exports = {
// add your other next config settings here
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, nextRuntime, webpack }
) => {
config.plugins = [...config.plugins,
new webpack.DefinePlugin({
'__REACT_DEVTOOLS_GLOBAL_HOOK__': '({ isDisabled: true })'
})
]
// Important: return the modified config
return config
},
}
This solution combines Dan Abramov's answer with the Next.js documentation description of modifying webpack config.
Also, locally you could just comment that part of code.
Search all file in "node_modules" for "React DevTools", you will get 2 results, react-dom.js and ReactDOM.js:
react-dom.js, navigate to line 5430, make line 5430 - 5437 to a comment, save.
ReactDOM.js, navigate to line 68, make line 68 - 75 to a comment, save.
Restart your app server.
I hope this method is not against the React License.
I am writing a npm package that depend on :
"peerDependencies": {
"react": "15.4.1",
},
"dependencies": {
"classnames": "2.2.5",
"react-onclickoutside": "5.8.3",
"styled-components": "1.1.2"
}
I have added them as peer dependencies.
I have created a webpack build, and I've generated a 'umd' module that I want to import in my application.
The probleme is that a component from the module that depend on react-onclickoutside, complain about the presence of 2 React.
This is the code that can be toggled and generate this error :
DropDown = onClickOutside(DropDown, {
handleClickOutside(instance) {
return instance.closeMenu;
},
});
This give me this error :
Error: Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's `render` method, or you have multiple copies of React loaded (details: ....).(…)
If I look at my UMD module, I can see that my peer dependencies is bundled, this is probably why there is now two React in my application.
I would like to know how I can prevent webpack from bundling React react in my module
You can make use of the externals feature in webpack. Basically it will create the UMD module without bundling React, and assuming that it will be provided elsewhere
How can I test React-Bootstrap components with node.js outside the browser? I am using Webpack. Since I'm running headless, I specify the null-loader for styles in my webpack config:
{test: /(\.css|\.less)$/, loader: 'null-loader'}
Nevertheless, I get an error when I run mocha that shows that the style-loader is being used:
webpack:///./~/style-loader/addStyles.js?:14
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
^
ReferenceError: window is not defined
at eval (webpack:///./~/style-loader/addStyles.js?:14:30)
at eval (webpack:///./~/style-loader/addStyles.js?:9:47)
at module.exports (webpack:///./~/style-loader/addStyles.js?:31:68)
at eval (webpack:///./~/bootstrap-webpack/bootstrap.config.js?./~/style-loader!./~/css-loader!./~/less-loader!./~/bootstrap-webpack/bootstrap-styles.loader.js:7:38)
[...]
It looks like this is because bootstrap-webpack is using the style loader even though my code isn't.
I've uploaded a full but minimal project to GitHub so you can take a look.
bootstrap-webpack allows you to override its config. Just create file bootstrap.config.js and specify it in the import:
bootstrap.config.js
module.exports = {
styleLoader: 'null-loader',
scripts: {
// add every bootstrap script you need
'transition': false
},
styles: {
// add every bootstrap style you need
"mixins": true,
"normalize": true,
"print": true,
"scaffolding": true,
"type": true,
}
};
App.jsx
import 'bootstrap-webpack!../../bootstrap.config.js';