How to use CSS Modules with webpack in React isomorphic app? - reactjs

I am build an isomorphic app using react, react-router, express and webpack. Now I want to use css modules to import css.
I use import './index.css' in index.jsx, it works fine on client, but doesn't work on server rendering. The error is Error: Cannot find module './index.css'.
components/index.jsx
import React, {Component, PropTypes} from 'react';
import style from './index.css';
class App extends Component {
constructor(props, context) {
super(props, context);
}
render() {
return (
<div id="login">
// ...
</div>
);
}
};
export default App;
server/router/index.js
import url from 'url';
import express from 'express';
import swig from 'swig';
import React from 'react';
import {renderToString} from 'react-dom/server';
import {match, RouterContext} from 'react-router';
import routes from '../../client/routes/routes';
import DataWrapper from '../../client/container/DataWrapper';
import data from '../module/data';
const router = express.Router();
router.get('*', async(req, res) => {
match({
routes,
location: req.url
}, async(error, redirectLocation, props) => {
if (error) {
res.status(500).send(error.message);
} else if (redirectLocation) {
res.status(302).redirect(redirectLocation.pathname + redirectLocation.search);
} else if (props) {
let content = renderToString(
<DataWrapper data={data}><RouterContext {...props}/></DataWrapper>
);
let html = swig.renderFile('views/index.html', {
content,
env: process.env.NODE_ENV
});
res.status(200).send(html);
} else {
res.status(404).send('Not found');
}
});
});
export default router;
webpack.config.dev.js(for webpack-dev-server)
var webpack = require('webpack');
var config = require('./config');
module.exports = {
devtool: 'inline-source-map',
entry: [
'webpack-dev-server/client?http://localhost:' + config.webpackPort,
'webpack/hot/only-dev-server',
'./src/client/entry',
],
output: {
path: __dirname + '/public/js',
filename: 'app.js',
publicPath: 'http://localhost:' + config.webpackPort + '/public/js',
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify('development')
}
})
],
resolve: {
extensions: ['', '.js', '.jsx', '.css']
},
module: {
loaders: [{
test: /\.jsx?$/,
loader: 'react-hot',
exclude: /node_modules/
}, {
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
}, {
test: /\.css$/,
loader: 'style-loader!css-loader?modules',
exclude: /node_modules/
}, {
test: /\.(png|woff|woff2|svg|ttf|eot)$/,
loader: 'url-loader',
exclude: /node_modules/
}]
}
}

I'd recommend using webpack to compile UI code for both client and server side in that case. Just set target: "node" in webpack config to produce bundle which can executed in Node environment.

That article might help for compiling your server side code with Webpack: http://jlongster.com/Backend-Apps-with-Webpack--Part-I
Especially on how to exclude node_modules with the externals key.
A very bare config might look like:
'use strict';
const path = require('path');
const fs = require('fs');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const rootDir = path.resolve(__dirname, '..');
const distDir = path.join(rootDir, 'dist');
const srcDir = path.join(rootDir, 'src');
const localStyles = new ExtractTextPlugin('local.css', { allChunks: true });
const nodeModules = fs.readdirSync('node_modules')
.filter(dir => !dir.startsWith('.'))
.reduce((acc, prop) => {
acc[prop] = 'commonjs ' + prop;
return acc;
}, {});
const loaders = [
{
test: /\.(js|jsx)$/,
include: srcDir,
exclude: /node_modules/,
loader: 'babel',
query: {
cacheDirectory: true,
},
},
{
test: /\.css$/,
include: srcDir,
loader: localStyles.extract(
'style',
'css?modules&localIdentName=[name]-[local]_[hash:base64:5]'
),
},
{
test: /\.json$/,
loader: 'json',
},
];
module.exports = {
target: 'node',
entry: {
server: ['server/index'],
},
output: {
path: distDir,
filename: '[name].bundle.js',
},
externals: nodeModules,
module: {
loaders,
},
plugins: [
localStyles,
],
};
Another solution (Webpack free) could be to use babel-plugin-css-modules-transform
.

Related

React router throwing Cannot GET /info

I want to render a component using React Router, The component responsibility is just to show the JSON object containing build information (commitHash, branch, version, etc).
The problem is whenever I access http://localhost:3000/info to get the build information, it is treated as a backend API call and throws 404 error (
Cannot GET /info
) ,
I am using the express-actuator package in the server.dev.js file, I am guessing something we have to change in the server.dev.js file because it is treating the /info as a server call instead of rendering the component
Below is a code snippet
require('dotenv-flow').config();
const path = require('path');
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const {createProxyMiddleware} = require('http-proxy-middleware');
const actuator = require('express-actuator');
const app = express(),
DIST_DIR = path.join(__dirname, 'dist'),
HTML_FILE = path.join(DIST_DIR, 'index.html');
const config = require('./webpack.dev.config.js');
const compiler = webpack(config);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", req.headers.origin);
res.header("Access-Control-Allow-Methods", "GET,POST,DELETE,PATCH");
res.header(
"Access-Control-Allow-Headers",
"X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept"
);
next();
});
app.use(
webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
})
);
app.use(
webpackHotMiddleware(compiler, {
publicPath: config.output.publicPath,
})
);
app.use(actuator({ basePath: "/actuator" }));
app.use(express.static(DIST_DIR));
app.get("/", (req, res) => {
res.sendFile(HTML_FILE);
});
const port = process.env.PORT || 9000;
app.listen(port, function (err) {
if (err) {
console.log(`\nError in server setup: ${err}`);
}
console.log(`\nServer started on Port: ${port}...`);
});
and /webpack.dev.config.js fil
const DotenvFlow = require('dotenv-flow-webpack');
const path = require('path');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const { GitRevisionPlugin } = require('git-revision-webpack-plugin');
const gitRevisionPlugin = new GitRevisionPlugin();
module.exports = {
entry: {
main: [
'webpack-hot-middleware/client?reload=true',
'./src/main/index.tsx'
]
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: 'bundle.js',
globalObject: 'this'
},
mode: 'development',
target: 'web',
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
hot: true,
},
module: {
rules: [
{
test: /\.tsx$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}, {
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader'
}
]
}, {
test: /(\.css)$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
}
]
}, {
test: /\.s[ac]ss$/i,
exclude: [
/\.module\.s[ac]ss$/,
/\.libs\.s[ac]ss$/,
],
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag',
}
},
{
loader: 'css-loader',
options: {
modules: false,
}
},
'sass-loader'
],
}, {
test: /\.module\.s[ac]ss$/,
exclude: [
/\.libs\.s[ac]ss$/,
],
use: [
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[local]__[hash:base64:5]',
}
}
},
'sass-loader',
]
}, {
test: /\.libs\.s[ac]ss$/,
use: [
{
loader: 'css-loader',
},
'sass-loader'
]
}, {
test: /\.(png|jpg|jpeg|gif|ico|pdf)$/,
exclude: [
path.resolve(__dirname, './node_modules'),
],
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
}
}
]
}, {
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
}
}
]
}
]
},
resolve: {
extensions: ['.js', '.tsx']
},
plugins: [
new webpack.DefinePlugin({
'_GIT_VERSION_': JSON.stringify(gitRevisionPlugin.version()),
'_GITSHA_': JSON.stringify(gitRevisionPlugin.commithash()),
'_GIT_BRANCH_': JSON.stringify(gitRevisionPlugin.branch()),
'_COMMIT_TIMESTAMP_': JSON.stringify(gitRevisionPlugin.lastcommitdatetime())
}),
new DotenvFlow(),
new WebpackManifestPlugin({ publicPath: "" }),
new webpack.HotModuleReplacementPlugin(),
new webpack.LoaderOptionsPlugin({
debug: true
}),
gitRevisionPlugin,
new HtmlWebPackPlugin({
template: './src/main/index.html',
filename: './index.html'
})
]
};
my App.tsx file
import React from "react";
import HomeComponent from "./components/HomeComponent";
import {Routes , Route } from "react-router-dom"
import BuildInfoPopper from "./components/BuildInfoPopper";
const App = () => {
return (
<div className="App">
<Routes>
<Route path="/info" element={<BuildInfoPopper/>}/>
</Routes>
</div>
);
};
export default App;
and index.tsx file
import React from "react";
import { render } from "react-dom";
import "./index.css";
import App from "./App";
import BuildInfoPopper from "./components/BuildInfoPopper";
import { BrowserRouter } from "react-router-dom";
const root = document.getElementById("root");
const rootElement = (
<div>
<BrowserRouter>
<App />
</BrowserRouter>
</div>
);
render(rootElement, root);
I have tried keeping the wild card character in server.dev.js but it didn't work

deploying officejs fabric react word add in

I have a word add in written in typescript using Officejs and office-ui-fabric-react. Everything works fine with the server running locally. I'd like to deploy into AWS S3 with Cloudfront. I'm building with npm run build, and npm run deploy (using deploy command "aws --profile profile-name s3 sync dist/ s3://bucketname". Static web site hosting is enabled in the S3 bucket. All files from the dist directory are seen in the bucket. After inserting the add in into Word with a manifest.xml file that points to the cloudfront endpoint I'm getting the error "Uncaught ReferenceError: React is not defined". The same error occurs when I point directly to the S3 static web endpoint. To see if I've missed anything I deployed a generic create-react-app using the steps above and it runs fine. I'm assuming that the problem lies with my webpack config so I've included that here (common, and prod). I'd be happy to include anything else that's needed. I'm also open to other deployment options if using AWS is causing the problem.
webpack.common.js:
const webpack = require('webpack');
const path = require('path');
const package = require('../package.json');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
const build = (() => {
const timestamp = new Date().getTime();
return {
name: package.name,
version: package.version,
timestamp: timestamp,
author: package.author
};
})();
const entry = {
vendor: [
'react',
'react-dom',
'core-js',
'office-ui-fabric-react'
],
app: [
'react-hot-loader/patch',
'./index.tsx',
],
'function-file': '../function-file/function-file.ts'
};
const rules = [
{
test: /\.tsx?$/,
use: [
'react-hot-loader/webpack',
'ts-loader'
],
exclude: /node_modules/
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
use: {
loader: 'file-loader',
query: {
name: 'assets/[name].[ext]'
}
}
}
];
const output = {
path: path.resolve('dist'),
publicPath: '/',
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].chunk.js'
};
const WEBPACK_PLUGINS = [
new webpack.NamedModulesPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.BannerPlugin({ banner: `${build.name} v.${build.version} (${build.timestamp}) © ${build.author}` }),
new webpack.DefinePlugin({
ENVIRONMENT: JSON.stringify({
build: build
})
}),
new webpack.LoaderOptionsPlugin({
options: {
postcss: [
autoprefixer({ browsers: ['Safari >= 8', 'last 2 versions'] }),
],
htmlLoader: {
minimize: true
}
}
})
];
module.exports = {
context: path.resolve('./src'),
entry,
output,
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.scss', '.css', '.html']
},
module: {
rules,
},
optimization: {
splitChunks: {
chunks: 'async',
minChunks: Infinity,
name: 'vendor'
}
},
plugins: [
...WEBPACK_PLUGINS,
new ExtractTextPlugin('[name].[hash].css'),
new HtmlWebpackPlugin({
title: 'letterConfig',
filename: 'index.html',
template: './index.html',
chunks: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
title: 'letterConfig',
filename: 'function-file/function-file.html',
template: '../function-file/function-file.html',
chunks: ['function-file']
}),
new CopyWebpackPlugin([
{
from: '../assets',
ignore: ['*.scss'],
to: 'assets',
}
])
]
};
webpack.prod.js:
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const ENV = process.env.NODE_ENV = process.env.ENV = 'development';
module.exports = webpackMerge(commonConfig, {
devtool: 'source-map',
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
},
performance: {
hints: "warning"
},
optimization: {
minimize: true
}
});
index.tsx:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { initializeIcons } from 'office-ui-fabric-react/lib/Icons';
import App from './components/App';
import './styles.less';
import 'office-ui-fabric-react/dist/css/fabric.min.css';
initializeIcons();
let isOfficeInitialized = false;
const title = 'letterConfig';
const render = (Component) => {
ReactDOM.render(
<AppContainer>
<Component title={title} isOfficeInitialized={isOfficeInitialized} />
</AppContainer>,
document.getElementById('container')
);
};
/* Render application after Office initializes */
Office.initialize = () => {
console.log('init');
isOfficeInitialized = true;
render(App);
};
/* Initial render showing a progress bar */
render(App);
if ((module as any).hot) {
(module as any).hot.accept('./components/App', () => {
const NextApp = require('./components/App').default;
render(NextApp);
});
}
It turned out that it was looking for a globally defined "React", and so not resolving via an npm module. In the webpack.prod.js file removing the following solved the problem:
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
},

webpack 3.8.1 facebook react import node module css not working

I am using Facebook react with Webpack and I import node module CSS in my component. It's not working.
webpack.config.js
const path = require("path");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve("dist"),
filename: "index_bundle.js"
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: "babel-loader",
exclude: /node_modules/,
query: {
presets: ["react", "es2015", "stage-0"],
plugins: ["transform-class-properties"]
}
},
{
test: /\.css?$/,
loaders: ExtractTextPlugin.extract(
"style-loader!css-loader?modules=true&localIdentName=[name]_[local]_[hash:base64:5]"
)
}
]
},
plugins: [new ExtractTextPlugin("./public/styles.css")]
};
React component file
I import react-times css file
import React from "react";
import TimePicker from "react-times";
import "react-times/css/material/default.css";
export default class Book extends React.Component {
render() {
return (
<TimePicker />
);
}
}
you can try
// module
{
test : /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader']
})
}
// plugins
new ExtractTextPlugin("styles.css")

Webpack and React BrowserRouter

im working on a project that was made in react with hashrouter, i want to change to browserouter but the project already has a webpack config and im kind of new to it, i know i should make webpack to take all calls to index (since im getting Cannot get on all routes) but i cant find any info on this kind of setup:
This is the current webpack config
const path = require('path');
const webpack = require('webpack');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
module.exports = {
devtool: 'cheap-module-source-map',
entry: {
app: [
'webpack-hot-middleware/client',
'react-hot-loader/patch',
'./src/app'
]
},
resolve: {
modules: ['node_modules'],
extensions: ['.js', '.jsx', '.scss'],
alias: {
'react-native': 'react-native-web'
}
},
output: {
path: path.join(__dirname, 'public/assets'),
publicPath: '/assets/',
filename: '[name].bundle.js'
},
module: {
rules: [{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [{
loader: 'react-hot-loader/webpack'
}, {
loader: 'babel-loader', options: {cacheDirectory: '.babel-cache'}
}]
}, {
// Most react-native libraries include uncompiled ES6 JS.
test: /\.js$/,
include: [
/node_modules\/react-native-/,
/node_modules\/react-router-native/,
/node_modules\/#indec/
],
loader: 'babel-loader',
query: {
presets: ['react-app'],
cacheDirectory: '.babel-cache'
}
}, {
test: /\.scss$/,
loader: [
'css-hot-loader'
].concat(
ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
})
)
}, {
test: /\.css$/,
use: ['style-loader', 'css-loader']
}, {
exclude: [
/\.html$/,
/\.(js|jsx)$/,
/\.json$/,
/\.s?css$/,
/\.(jpg|png)/
],
loader: 'url-loader',
options: {name: '[name].[ext]', limit: 10000}
}, {
test: /\.(jpg|png)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader',
options: {name: '[name].[ext]'}
}]
},
plugins: [
new webpack.DefinePlugin({
VERSION: JSON.stringify(require('./package.json').version),
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
ENDPOINT: JSON.stringify(require('./config.json').endpoint)
}),
new webpack.optimize.CommonsChunkPlugin('vendor'),
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),
new FriendlyErrorsWebpackPlugin(),
new ExtractTextPlugin('[name].bundle.css')
],
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
}
};
app gets initiated on this index.js file
const path = require('path');
const app = require('connect')();
const config = require('./config.json');
const winston = require('winston');
const PORT = process.env.PORT || config.server.port;
process.env.NODE_ENV = config.mode;
app.use(require('morgan')(config.server.morgan));
app.use(require('compression')());
app.use(require('serve-static')(path.join(__dirname, config.server.static)));
if (config.mode === 'development') {
const config = require('./webpack.config');
const compiler = require('webpack')(config);
app.use(require('webpack-dev-middleware')(compiler, {
publicPath: config.output.publicPath,
}));
app.use(require('webpack-hot-middleware')(compiler));
}
require('http').createServer(app).listen(
PORT,
() => winston.info('Server started at port %s', config.server.port)
);
and my app js
import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import Aux from 'react-aux';
import Home from '../Home';
import Admin from '../Admin';
import SignIn from '../SignIn';
import Header from './Header';
import Footer from './Footer';
const App = () => (
<BrowserRouter>
<Aux>
<Header/>
<main>
<Switch>
<Route path="/" component={Home}/>
<Route path="/admin" component={Admin}/>
<Route path="/signIn" component={SignIn}/>
</Switch>
</main>
</Aux>
</BrowserRouter>
);
export default App;
I end up finding a easy solution, just created a express app and handled all 404 to index, didn't find how to do it with connect.
const path = require('path');
const express = require('express');
const app = express();
const config = require('./config.json');
const winston = require('winston');
const PORT = process.env.PORT || config.server.port;
process.env.NODE_ENV = config.mode;
app.use(require('morgan')(config.server.morgan));
app.use(require('compression')());
app.use(require('serve-static')(path.join(__dirname, config.server.static)));
if (config.mode === 'development') {
const config = require('./webpack.config');
const compiler = require('webpack')(config);
app.use(require('webpack-dev-middleware')(compiler, {
publicPath: config.output.publicPath,
}));
app.use(require('webpack-hot-middleware')(compiler));
}
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname, './public/index.html'), function(err) {
if (err) {
res.status(500).send(err);
}
});
});
app.use((req, res, next) => {
const err = new Error('Not Found');
err.status = 404;
next(err);
});
require('http').createServer(app).listen(
PORT,
() => winston.info('Server started at port %s', config.server.port)
);
You can use historyApiFallback: true in your config to do this.
Docs on that are located here

React, Webpack and Babel for Internet Explorer 9

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/

Resources