How to get promises to work in IE10 with react - reactjs

I am trying to fetch data using promise in my react application. I installed and implemented this polyfill es6-promise but works for IE11 on window 8 but IE10 window 7 is says 'promise are undefined'. I assumed the polyfill is meant to cover all IE9+, but it is just not working for me. Has anyone come across this problem? Am I missing something in the implementation of the es6-promise polyfill with webpack??
// calling it my jsx file
import React, { PropTypes } from 'react';
import es6promise from 'es6-promise'; // not sure if I need this in the jsx file also??
promise.polyfill();
import 'isomorphic-fetch';
class App extends React.Component {
...
}
App.propTypes = propTypes;
export default App;
webpack.config.js
var promise = require('es6-promise').polyfill();
switch (TARGET) {
case 'build':
module.exports = mergeConfig({
plugins: [
// Reference: http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
// Minify all javascript. Loaders are switched into minimizing mode
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.DefinePlugin({
'process.env': {
// This has effect on the react lib size
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.ProvidePlugin({
PROMISE: promise
})
]
});
break;

You can try babel-polyfill.
After install it as dependency.
Import it in your app.js
import 'babel-polyfill';

I have an another interesting solution (it works for me in that case). I didn't want to import a polyfill into every file so I provided via WebpackProvidePlugin.
new webpack.ProvidePlugin({
"Promise": "babel-polyfill",
'fetch': 'imports-loader?this=>global!exports-loader?
global.fetch!whatwg-fetch'
})
So now I can use these stuff without importing into every file. And a very important note. Some resources are suggesting to use es6-promise instead babel-polyfill, I tried to use it but it doesn't work for me. Looks like es6-promise-polyfill didn't work in case of using webpack + babel. So I switched to the babel-polyfill. Tested in the IE11 and all is fine.
Hope it helps.
Best Regard. Velidan.

I recommend using the native-promise-polyfill npm module, especially if you don't need the other features babel-polyfill includes:
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

Related

babel: polyfill Array.from for IE11 support

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';

Disable/Hide "Download the React DevTools..."

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.

How to import from different bundle created with webpack

I have two project using webpack. Now I want to bring one project as module of other project. I can get the two bundle created but don't know how to import from the other bundle.
Elaborating a bit:-
Lets say the other file from which i want to import looks like as follows:-
index2.js (Bundled as bundleTwo)
import SomeCompoent from "./components/SomeCompoent/SomeCompoent";
module.exports = {SomeCompoent}
and in the file (is in another bundle - bundleOne) below I want to import the component (somecomponent):-
index1.js (in bundleOne)
import {SomeCompoent} from "bundleTwo";
but here bundleTwo is undefiend
Any help is highly appreciated
One way that I have figured out myself, is that using alias this can be achieved.
To make this line import {SomeCompoent} from "bundleTwo"; work, bundleTwo can be defined in alias :-
config:{
resolve: {
alias: {
"bundleTwo": path.join(__dirname, "<path_to_the_bundleTwo>")
}
....
If you want to use webpack only,then just set the libraryTarget to 'umd' in bundletwo webpack configuration.
In order to be able to import this module, you need to export your bundle.
output: {
libraryTarget: 'umd',// make the bundle export
filename: "index.js",
path: path.resolve(__dirname, "dist"),
}
However, this can also be achieved by just using Babel to transpile your ES6 code to ES5 code.
babel index2.js --out-file dist/index2.js
Now set the main in package.json to "dist/index2.js"
Now you can use it like
import {SomeCompoent} from "bundleTwo";
You can also create a gulp script for that
gulp.task('js', function () {
return gulp.src(['packages/**/*.js', "!**/*.test.js"])
.pipe(babel({
plugins: ['transform-runtime']
}))
.pipe(gulp.dest('dist'));
});

referencing an amd module(arcgis) in webpack app

I'm building a react app with webpack and i need to incorporate arcgis maps into a react component. I have know idea how to bring this into my project. I've tried creating an arcgis directory with an index.js of the built javascript and trying to reference that:
import {Map} from 'arcgis/index'
That doesn't work. I then just tried to include the css/js script tags directly into my index.html but when I try to require them, like in the example, webpack obviously can't find them. Is there some way to tell webpack to ignore require calls in my src file so it gets handled by the browser? I'm trying and failing at doing the following:
import React from 'react'
export default class EsriMap extends React.Component {
componentDidMount() {
const _this = this
require(["esri/map", "dojo/domReady!"], function(Map) {
var map = new Map(_this.refs.map, {
center: [-118, 34.5],
zoom: 8,
basemap: "topo"
});
});
}
render() {
return (
<div ref="map"></div>
)
}
}
You may want to try this https://github.com/tomwayson/esri-webpack-babel .
This method is nice because it doesn't bog down the build. You pull in the ESRI Api from the CDN, and tell webpack that it's an external.
//Add this...
externals: [
// Excludes any esri or dojo modules from the bundle.
// These are included in the ArcGIS API for JavaScript,
// and its Dojo loader will pull them from its own build output
function (context, request, callback) {
if (/^dojo/.test(request) ||
/^dojox/.test(request) ||
/^dijit/.test(request) ||
/^esri/.test(request)
) {
return callback(null, "amd " + request);
}
callback();
}
],
//And this to you output config
output: {
libraryTarget: "amd"
},
When your app loads you bootstrap you webpack modules using Dojo in a script tag.
<!-- 1. Configure and load ESRI libraries -->
<script>
window.dojoConfig = {
async: true
};
</script>
<script src="https://js.arcgis.com/4.1/"></script>
<!-- Load webpack bundles-->
<script>
require(["Angular/dist/polyfills.bundle.js", "Angular/dist/vendor.bundle.js", "Angular/dist/app.bundle.js"], function (polyfills, vendor, main) { });
</script>
I've got it working with an Angular 2 App I'm working on. The only downside is I haven't yet got the unit tests to run right using Karma. I've only been working on that a few hours now.. Hope to have a solution to the testing issue soon.
#getfuzzy's answer will work well as long as you don't need to lazy load the ArcGIS API (say for example only on a /map route).
For that you will want to take the approach I describe in this answer
This blog post explains why you need to use one of these two approaches and explains how they work as well as the pros/cons of each.
I think you can try using bower version of esrijsapi. Doc link

Gulp and Browserify turn my React Redux into a huge file even though I removed the React dependencies

TL;DR: I'm getting build files that are way too big. I want them to be small and use the React source files from a CDN.
My Gulp file contains this:
gulp.task('build', () => {
browserify({
entries: dirs.src + '/index.jsx',
extensions: ['.jsx'],
debug: false
})
.transform(babelify.configure({
presets: ["es2015", "react"]
}))
.bundle()
.pipe(source('index.js'))
.pipe(gulp.dest(dirs.dest));
});
And said index.jsx file contains:
import { Provider } from 'react-redux';
import slides from './stores/slides';
const store = slides();
ReactDOM.render(
<Provider store={store}>
<h1>Test</h1>
</Provider>,
document.getElementById('target')
);
React Redux is pretty small. And if I remove that part from the latter file the result is a mere 1 KB in size. Otherwise it'll turn into 700Kb+.
I already removed these two lines from that file:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
Because I wanted to load React and ReactDOM from a CDN. Why are my files still this incredibly large?
You're currently using the development version of React. You have to build your own production version, for that the process.env.NODE_ENV flag has to be set to production.
If you're using browserify, you need envify: https://github.com/hughsk/envify
npm install envify --save-dev
Your Gulpfile.js
var envify = require('envify/custom');
//...
.transform(babelify.configure({
presets: ["es2015", "react"]
}))
.transform(envify({
NODE_ENV: 'production'
}))
//...
More resources: http://dev.topheman.com/make-your-react-production-minified-version-with-webpack/
I'm loading Ready through script tags from a CDN. I don't want to have the entire React codebase in my own local project files.
In this case, your production Webpack config should specify React in externals config option:
{
// ...
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
// ...
}
Otherwise Webpack will bundle it.
Also verify that you don’t have a devtool option in the production config. It can bloat the code immensely if you use 'eval' or even inline sourcemaps.
I know uglify, but I don't want my code uglified
You should be using uglify for your code in production. This is the only way to have small builds.

Resources