React, Webpack and Babel for Internet Explorer 9 - reactjs

Trying to support IE 9 for React. Upgraded to use babel 6.3.26 and babel-preset-es2015 and babel-preset-react for Webpack. However, when the file is loaded in IE 9, a syntax error occurs.
webpack.config.js
/* eslint-env node */
var path = require('path');
var packageJson = require('./package.json');
var _ = require('lodash');
var webpack = require('webpack');
var context = process.env.NODE_ENV || 'development';
var configFunctions = {
development: getDevConfig,
production: getProdConfig,
test: getTestConfig
};
var config = configFunctions[context]();
console.log('Building version %s in %s mode', packageJson.version, context);
module.exports = config;
function getLoaders() {
if (context.indexOf('test') === -1) {
return [
{
test: /\.js?$/,
exclude: /(test|node_modules|bower_components)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015'],
plugins: ['transform-runtime']
}
}
]
} else {
return [
{
test: /\.js?$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015'],
plugins: ['transform-runtime']
}
}
]
}
}
function getBaseConfig() {
return {
context: __dirname + "/src",
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
stats: {
colors: true,
reasons: true
},
resolve: {
extensions: ['', '.js', '.jsx']
},
module: {
loaders: _.union(
getLoaders(),
[
{
test: /\.scss$/,
loader: 'style!css!sass'
},
{
test: /\.eot$|\.svg$|\.woff$|\.ttf$/,
loader: 'url-loader?limit=30000&name=fonts/[name]-[hash:6].[ext]'
},
{
test: /\.(png|.jpe?g|gif)$/,
loader: 'url-loader?limit=5000&name=img/[name]-[hash:6].[ext]'
},
{
test: /\.mp4$/,
loader: 'url-loader?limit=5000&name=videos/[name]-[hash:6].[ext]'
}
]
)
}
};
}
function getDevConfig() {
return _.merge({}, getBaseConfig(), {
devtool: 'cheap-module-eval-source-map',
entry: [
'babel-polyfill',
'webpack-hot-middleware/client',
'./App'
],
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
eslint: {
emitError: false,
failOnError: false,
failOnWarning: false,
quiet: true
}
});
}
function getProdConfig() {
return _.merge({}, getBaseConfig(), {
devtool: 'source-map',
entry: [
'babel-polyfill',
'./App'
],
plugins: [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
minimize: true,
compress: {
warnings: false
}
})
],
eslint: {
emitError: true,
failOnError: true
}
})
}
function getTestConfig() {
return _.merge({}, getBaseConfig(), {})
}
Checking bundle.js for the offending lines reveals the usage of const which is not ES5. Am I missing something here? Do I need to transpile ES6 code into ES5 for production usage?

IE9 is not compatible with ES6, so, yes, you must transform your ES6 code to ES5. I believe the problem is you aren't telling babel to use the react and es2015 presets. I'm sure you installed them on your machine, but the babel loader only does what you tell it.
Inside your getLoaders() function, add the presets to your babel loader configuration query:
query: {
plugins: ['transform-runtime'],
presets: ['react', 'es2015']
}
Hopefully, that works for you.
babel/babel-loader reference

I am using create-react-app (v16.4.2). I tried using the followings to get the default hello world working in IE9:
1:
import 'core-js/es6/map';
import 'core-js/es6/set';
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
2:
import "babel-polyfill";
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
But neither of them worked for me. I ended up adding the following line into my index.html file in the public folder and it fixed my issue:
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
More information is available at:https://polyfill.io/v2/docs/

Related

React froala Super expression must either be null or a function not undefined

I am trying to use froala editor in my react code and It is working perfectly in my local. But in production it is crashing. It is just a blank page. When I opened console there is a error message Super expression must either be null or a function not undefined. If I remove froala editor then it is working fine.
import React from 'react';
import 'froala-editor/css/froala_style.min.css';
import 'froala-editor/css/froala_editor.pkgd.min.css';
import FroalaEditorComponent from 'react-froala-wysiwyg';
const Editor = (props) => {
return <FroalaEditorComponent {...props} />;
};
export default Editor;
and this is my webpack config
const webpack = require('webpack');
const path = require('path');
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
mode: 'production',
entry: {
main: ['./client/app/main'],
},
externals: {
react: 'React',
'react-dom': 'ReactDOM'
},
output: {
path: path.resolve(__dirname, './client/dist'),
filename: '[name].app.bundle.js',
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.html$/,
loader: 'file-loader?name=[name].[ext]',
},
{
test: /\.js?$/,
exclude: /node_modules[\/\\](?!(swiper|dom7|#jimp\/core|d3-array|d3-scale|file-type|react-wordcloud|striptags)[\/\\])/,
loader: 'babel-loader',
options: {
cacheDirectory: true,
babelrc: false,
presets: ['#babel/preset-env', '#babel/react'],
plugins: [
['#babel/plugin-proposal-decorators', { 'legacy': true }],
'#babel/plugin-proposal-optional-chaining',
'#babel/plugin-proposal-class-properties',
]
},
},
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
],
},
resolve: {
modules: [path.resolve(__dirname, './client/app'), 'node_modules'],
extensions: ['.jsx', '.js', '.json'],
// These extensions are tried when resolving a file
enforceExtension: false,
// If false it will also try to use no extension from above
moduleExtensions: ['-loader'],
// These extensions are tried when resolving a module
enforceModuleExtension: false,
},
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new CompressionPlugin({
test: /\.js?$/,
deleteOriginalAssets: true,
})
],
node: {
fs: 'empty'
}
};
Any help would be really thankfull

toastr not showing when imported in a jsx file

I have a react app that uses webpack to bundle JS and CSS into 1 file and output it into a destination folder. I've recently added toastr to 1 of my jsx file:
import toastr from "toastr";
import "toastr/build/toastr.min.css"
Running the app and viewing the source, i've verified in the browser (viewing the source files) that toastr.min.js is included in the JS bundle and toastr.min.css is included in the CSS bundle. However, the toastr notification doesn't show. There is no error and a scrollbar appears in the right-side for a few seconds so I suspected the toastr code is working, just that the CSS is not properly styling for some reason.
I removed this line:
import "toastr/build/toastr.min.css"
and then directly added this to html
<link rel="stylesheet" type="text/css" href="~/css/toastr.min.css" />
and now it works. But I want to make it work where toastr.min.css is included in the bundle. Is there anything I'm missing?
webpack config
const path = require("path");
const webpack = require("webpack");
const miniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
home: "./Scripts/Components/Home/main.js",
login: "./Scripts/Components/Login/main.js",
vendor: [
"jquery",
"react",
"react-dom",
"react-router-dom",
"react-css-modules",
]
},
mode: "development",
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: "all",
name: "vendor",
test: "vendor",
enforce: true
}
}
}
},
output: {
publicPath: "/js/",
path: path.join(__dirname, "/wwwroot/js/"),
filename: "[name].bundle.js"
},
devtool: "source-map",
plugins: [
new miniCssExtractPlugin({
filename: "../css/[name].css"
}),
],
module: {
rules: [{
test: /\.jsx$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["env", "react"]
}
}
}, {
test: /\.css$/,
use: [{
loader: miniCssExtractPlugin.loader,
}, {
loader: "css-loader",
query: {
modules: true,
localIdentName: "[name]__[local]___[hash:base64:5]"
}
}]
}]
}
};

Can not export webpack.config when modules:false

Inside my index.js I am using webpack-dev-middleware/webpack-hot-middleware where I require my webpack.config and use it for compiler.
index.js
const webpack = require('webpack')
const webpackConfig = require('../../webpack.config.js')
const compiler = webpack(webpackConfig)
const webpackDevMiddleware = require('webpack-dev-middleware')
app.use(webpackDevMiddleware(compiler, {
publicPath: webpackConfig.output.publicPath,
hot: true,
noInfo: true,
stats: {
colors: true
}
}))
app.use(require('webpack-hot-middleware')(compiler))
I try to export my webpack.config using Common.js by require and module.exports but I get error
TypeError: Cannot assign to read only property 'exports' of object '#<Object>'
webpack.config
'use strict'
const path = require('path')
const webpack = require('webpack')
const publicPath = path.resolve(__dirname, './src/client')
const buildPath = path.resolve(__dirname, './src')
process.noDeprecation = true
module.exports = {
devtool: 'source-maps',
performance: {
hints: false
},
context: publicPath,
entry: {
bundle: [
'react-hot-loader/patch',
'webpack-hot-middleware/client?reload=false&noInfo=true',
'script-loader!jquery/dist/jquery.min.js',
'script-loader!tether/dist/js/tether.min.js',
'script-loader!bootstrap/dist/js/bootstrap.min.js',
'./app.js'
]
},
output: {
path: path.join(buildPath, 'dist'),
filename: '[name].js',
publicPath: '/'
},
resolve: {
extensions: ['.js', '.jsx'],
alias: {
CountdownForm: path.resolve(__dirname, 'src/client/scenes/countdown/components/CountdownForm.jsx'),
Countdown: path.resolve(__dirname, 'src/client/scenes/countdown/index.jsx'),
..
}
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules|dist|build/,
loader: 'babel-loader',
options: {
plugins: [
[
'babel-plugin-react-css-modules',
{
context: publicPath,
filetypes: {
'.scss': 'postcss-scss'
}
}
]
]
}
},
{
test: /\.local\.(css|scss)$/,
use: [
'style-loader',
'css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
'postcss-loader',
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: path.resolve(__dirname, './src/client/styles/global/sass-resources.scss')
}
}
]
},
{
test: /^((?!\.local).)+\.(css|scss)$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery'
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('development')
}
})
]
}
If I use ES6 (I am using babel and this usually works) using import statements at the top instead of require and export default instead of module.exports I get this error
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration misses the property 'entry'.
All of this is because of modules:false inside my .babelrc If I remove that Common.js way works, but I need this. How can I export webpack.config to compiler using modules:false
{
"presets": [
"react",
["es2015", { "modules": false }],
"stage-0"
],
"plugins": [
"react-hot-loader/babel",
"transform-runtime"
]
}
transform-runtime adds import and that results in mixing import with your module.exports.
Simple fix would be to replace module.exports with es6 export
module.exports = { ...webpackconfig }
becomes
export default { ...webpackconfig }
and update your index.js to use default export
const webpackConfig = require('../../webpack.config.js').default
You can find more information about this on these issues
https://github.com/webpack/webpack/issues/4039
https://github.com/webpack/webpack/issues/3917

Webpack build issue with mobx and mobx-react

I have a project that uses React and Mobx with Mobx-react.
My project runs perfectly fine locally. However, when built using webpack -p, I get a blank screen with the following error in the console:
webpack:///./~/mobx-react/index.js?:3 Uncaught Error: Cannot find module "mobx"
at webpackMissingModule (webpack:///./~/mobx-react/index.js?:3)
at webpackUniversalModuleDefinition (webpack:///./~/mobx-react/index.js?:3)
at eval (webpack:///./~/mobx-react/index.js?:10)
at Object.<anonymous> (bundle.js:18)
at n (bundle.js:1)
at eval (webpack:///./src/components/Category.jsx?:35)
at Object.<anonymous> (bundle.js:27)
at n (bundle.js:1)
at eval (webpack:///./src/components/CategoryNavsDates.jsx?:15)
at Object.<anonymous> (bundle.js:14)
Here is my webpack config:
var path = require('path');
var webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer')
var CopyWebpackPlugin = require('copy-webpack-plugin');
var BUILD_DIR = path.resolve(__dirname, 'build/');
var SOURCE_DIR = path.resolve(__dirname, 'src/');
module.exports = {
devtool: 'eval',
entry: SOURCE_DIR + '/index.jsx',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
cacheDirectory: true,
plugins: ['transform-decorators-legacy'],
presets: ['es2015', 'stage-0', 'react']
}
},
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { modules: true, importLoaders: 1, localIdentName: "[name]__[local]___[hash:base64:3] "} },
{ loader: 'postcss-loader', options: {} },
]
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
plugins: [
new webpack.LoaderOptionsPlugin({
options: {
postcss: function () {
return [
require('postcss-import'),
require('postcss-cssnext'),
];
},
}
}),
new CopyWebpackPlugin([{ from: 'index.html', to: '' },])
],
devServer: {
historyApiFallback: true
},
};
There is only one file using Mobx in my entire project, and that is the file the error refers to, Category.jsx.
Category.jsx sample:
import { observer } from 'mobx-react'
import { observable } from 'mobx'
...
#observer class Category extends React.Component {
#observable showingSmallMenu = false
...
}
As I say this all works perfectly fine locally.
What could be the problem here?
Does it make a difference if you import mobx before mobx-react?
In my case, that is caused by:
alias: {
mobx: __dirname + '/node_modules/mobx/lib/mobx.es6.js'
}
Remove mobx alias, then the problem is solved

Why does Hot Module Replacement stop working on webpack dev server when I setup Babel es2015 preset?

I have a small app running through webpack dev server (on dev environment).
The hot module replacement is running well, I can see my changes on the fly while I edit my js files.
But as soon as I add the es2015 preset in babel loader config, it stops working !
webpack.config.js :
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
process.env.BABEL_ENV = 'development';
module.exports = {
entry: {
app: ['react-hot-loader/patch', path.join(__dirname, 'src')]
},
output: {
path: path.join(__dirname, 'build'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.js$/,
include: path.join(__dirname, 'src'),
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: ['react'],
},
},
}
]
},
devServer: {
historyApiFallback: true,
quiet: true,
hotOnly: true,
contentBase: './build',
host: 'my-host.local',
port: 8091,
watchOptions: {
aggregateTimeout: 300,
poll: 1000,
},
},
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack demo',
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new FriendlyErrorsWebpackPlugin(),
new webpack.WatchIgnorePlugin([
path.join(__dirname, 'node_modules')
]),
],
};
src/index.js file :
import React from 'react';
import ReactDOM from 'react-dom';
import Component from './Component';
import { AppContainer } from 'react-hot-loader';
const app = document.createElement('div');
document.body.appendChild(app);
const render = App => {
ReactDOM.render(
<AppContainer><App /></AppContainer>,
app
);
};
render(Component);
if (module.hot) {
module.hot.accept('./Component', () => render(Component));
}
Component.js
import React from 'react';
export default class Title extends React.Component {
render() {
return (
<div>Ass</div>
);
}
}
.babelrc
{
"presets": [
[
"react",
"es2015",
{
"modules": false
}
]
],
"env": {
"development": {
"plugins": [
"react-hot-loader/babel"
]
}
}
}
And soon as I replace
presets: ['react'],
by
presets: ['es2015', 'react'],
The Hot Module Replacement feature stops working.. Does anyone has a clue here ?
(also don't hesitate to point at bad practices or avoidable complications in my code)
You need the following .babelrc (I don't know why).
.babelrc
{
"presets": [
["es2015", {"modules": false}],
"stage-2",
"react"
],
}
Where stage-2 is the npm package babel-preset-stage-2.

Resources