Hot module replacement - Updating but not re-rendering - javascript

I am running an express server that will act as an API for my React app that is being bundled and served by webpack-dev-server.
I am trying to get hot module replacement to work, and am almost there, when I make changes to my files, I get this in the console:
But the app is never re-rendered, unless manually refreshed. Unaware if this is relevant, but when I update my .scss files, it refreshes without manually doing so, and updates as I would expect.
Versions:
"webpack": "2.1.0-beta.22"
"webpack-dev-server": "2.1.0-beta.8"
"react-hot-loader": "3.0.0-beta.5"
I tried the latest webpack but it gave me validation errors that could not be overcome.
I am running webpack via: "webpack": "webpack-dev-server --port 4000 --env.dev", and my express server is being ran on http://localhost:3000.
Here is my webpack.config.babel.js:
const webpack = require('webpack');
const { resolve, join } = require('path');
const { getIfUtils, removeEmpty } = require('webpack-config-utils')
const getEntry = (ifDev) => {
let entry
if (ifDev) {
entry = {
app: [
'react-hot-loader/patch',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:4000/',
'./js/index.js'
],
vendor: ['react']
}
} else {
entry = {
bundle: './js/index.js',
vendor: ['react']
}
}
return entry
}
const config = env => {
const { ifProd, ifDev } = getIfUtils(env)
return {
entry: getEntry(ifDev),
output: {
path: resolve('./public/dist/'),
publicPath: 'http://localhost:4000/',
filename: '[name].bundle.js',
},
context: resolve(__dirname, 'assets'),
devtool: env.prod ? 'source-map' : 'eval',
devServer: {
contentBase: resolve('./public/dist/'),
headers: { 'Access-Control-Allow-Origin': '*' },
publicPath: 'http://localhost:4000/',
hot: true,
noInfo: true,
inline: true
},
bail: env.prod,
module: {
loaders: [
{ test: /\.scss$/, loaders: [ 'style', 'css', 'sass' ], exclude: /node_modules|lib/ },
{ test: /\.(js|jsx)$/, exclude: /node_modules/, loaders: [ 'babel-loader' ] },
{ test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/, loader: 'file-loader' }
]
},
resolve: {
extensions: ['.js', '.jsx']
},
plugins: removeEmpty([
ifDev(new webpack.NoErrorsPlugin()),
ifDev(new webpack.NamedModulesPlugin()),
ifDev(new webpack.HotModuleReplacementPlugin()),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify((env.prod) ? 'production' : 'development') }
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity,
filename: 'vendor.bundle.js'
}),
ifProd(new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
})),
ifProd(new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false },
output: { comments: false },
sourceMap: false
}))
]),
}
}
module.exports = config
Here is my .babelrc, where I call react-hot-loader
{
"presets": [["es2015", { modules: false }], "stage-0", "react"],
"plugins": ["react-hot-loader/babel"],
"env": {
"test": {
"plugins": ["istanbul"],
"presets": ["es2015", "stage-0", "react"]
}
},
"sourceMaps": "inline"
}

With React Hot Loader v3 and the Babel transform, you want to do this in the root of your component (where you do your rendering, or where you create your Redux provider):
render(
<AppContainer>
<Root
store={ store }
/>
</AppContainer>,
document.getElementById('root')
);
if (module.hot) {
module.hot.accept('./containers/Root', () => {
const RootContainer = require('./containers/Root').default;
render(
<AppContainer>
<RootContainer
store={ store }
/>
</AppContainer>,
document.getElementById('root')
);
});
}
With the new version of Hot Loader, you have to explicitly accept the hot update with module.hot.accept.
In a more complex Redux project (with routing and hot reloading reducers) you could do something like this:
/**
* Starts the React app with the Router, and renders it to the given DOM container
* #param {DOMElement} container
*/
export default function app(container) {
const store = createStore(
combineReducers({
...reducers,
routing: routerReducer,
form: formReducer,
}),
compose(
applyMiddleware(
routerMiddleware(hashHistory),
thunkMiddleware,
promiseMiddleware
),
process.env.NODE_ENV !== 'production' && window.devToolsExtension ? window.devToolsExtension() : (param) => param
)
);
if (module.hot) {
module.hot.accept('./reducers', () => {
const nextReducers = require('./reducers');
const nextRootReducer = combineReducers({
...nextReducers,
routing: routerReducer,
form: formReducer,
});
store.replaceReducer(nextRootReducer);
});
}
const history = syncHistoryWithStore(hashHistory, store);
render({ store, history, container });
store.dispatch(loadEventsWhenLoggedIn());
if (module.hot) {
module.hot.accept('./render', () => {
const newRender = require('./render').default;
newRender({ store, history, container });
});
}
}
(and render.js)
/**
* Starts the React app with the Router, and renders it to the given DOM container
* #param {DOMElement} container
*/
export default function render({ store, history, container }) {
ReactDOM.render(
<Provider store={store}>
<div className='container'>
<Routes history={history} store={store} />
</div>
</Provider>,
container
);
}
For more examples you should have a look at Dan Abramov's Redux devtools example repo, for example this file: https://github.com/gaearon/redux-devtools/blob/master/examples/todomvc/index.js

HMR works automatically for CSS because style-loader supports that out-of-the-box.
With React that's not the case. You need react-hot-loader.
Install it with npm, and change this:
{ test: /\.(js|jsx)$/, exclude: /node_modules/, loaders: [ 'babel-loader' ] },
To:
{ test: /\.(js|jsx)$/, exclude: /node_modules/, loaders: [ 'react-hot-loader', 'babel-loader' ] },
If you want to know more, I recommend to read "Webpack’s HMR & React-Hot-Loader — The Missing Manual".

I was having this problem, added the module.hot.accept() function and it still wasn't working.
hmr [connected]... but no hot replacement.
*deleted node_module, package-lock.json, dist/build folders...
*changed webpack.config.client.production.js --> added
plugins: [
new webpack.ProvidePlugin({
process: "process/browser"
})
],
resolve:{
alias:{
process: "process/browser"
}
}
then npm install --save-dev process,
added import process from 'process' to bundle entry point (main.js for me)
...
npm install
then run it.

Related

HMR not triggering sometimes for components

This has been baffling me for a few hours now & I can't seem to work out why. My project structure is below. Sometimes a change in views/Dashboard/index.jsx will trigger a hot reload & other times it will not. It's weird but when it works, after about an hour or so, it will just suddenly stop working...
index.js
import 'react-hot-loader'
import 'bootstrap/dist/css/bootstrap.min.css'
import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import { library } from '#fortawesome/fontawesome-svg-core'
import { faChartBar, faThList, faCogs, faClipboard, faFilter, faNotEqual } from "#fortawesome/free-solid-svg-icons"
import configureStore, { history } from './redux/store'
import App from './App'
library.add(faChartBar, faThList, faCogs, faClipboard, faFilter, faNotEqual)
let store
function render(Component) {
ReactDOM.render(
<AppContainer>
<Component store={store} />
</AppContainer>,
document.getElementById('root')
)
}
configureStore()
.then(_store => {
store = _store
render(App)
if (module.hot) {
// Reload components
module.hot.accept('./App', () => {
render(App)
})
}
})
.catch(err => {
console.log(err)
})
App.jsx
import { hot } from 'react-hot-loader/root'
import React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter as Router } from 'react-router-dom'
import PropTypes from 'prop-types'
// Routes
import routes from './routes'
const App = ({ store }) => {
return (
<Provider store={store}>
<Router>{routes}</Router>
</Provider>
)
}
App.propTypes = {
history: PropTypes.object,
}
export default hot(module)(App)
routes/index.js
import React from 'react'
import { Route, Switch } from 'react-router'
// Components
import Dashboard from '../views/Dashboard'
// Views
import NoMatch from '../views/NoMatch'
export default (
<Switch>
<Route path="/" component={Dashboard} exact={true} />
<Route component={NoMatch} />
</Switch>
)
views/Dashboard/index.jsx
import React, { Component } from 'react'
export default class Dashboard extends Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
Hello World
</div>
)
}
}
If I make any change to the first 4 files listed (index.js, App.jsx, routes/index.js, containers/Dashboard.js) then the hot reloading works & the page is reloaded. However, if I attempt to make a change to views/Dashboard/index.jsx, for example, change "Hello World" to "Foo Bar" then the hot reloading is not honoured.
However I have now taken out the intermediary step of redux & changed the routers/index.js to use the direct component from views/Dashboard/index.jsx & it still does not reload.
How can this be? If I set the component on the Route to the container listed above, it hot reloads for that file but not this JSX one? Is this to do with the structure inside my main component views/Dashboard/index.jsx? If so, what? As it looks fine to me.
EDIT
My complete webpack config is:
webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const DotenvPlugin = require('dotenv-webpack')
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: 'js/[name].bundle.js',
},
resolve: {
extensions: ['.js', '.jsx'],
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader', // Using Babel to compile JS files
},
{
test: /\.(css|scss|sass)$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.(png|svg|jpg|gif|woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 1000000,
name: 'img/[hash].[ext]',
},
},
],
},
{
test: /\.html$/,
loader: 'html-loader'
}
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public', 'index.html'),
filename: './index.html',
}),
new DotenvPlugin({
systemvars: true,
}),
],
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
}
webpack.dev.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const path = require('path')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'development',
entry: path.resolve(__dirname, 'src', 'index.js'),
// https://github.com/gaearon/react-hot-loader#source-maps
devtool: 'eval',
devServer: {
contentBase: path.join(__dirname, 'dist'),
open: true,
compress: true,
hot: true,
historyApiFallback: true
},
resolve: {
alias: {
'react-dom': '#hot-loader/react-dom'
}
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.EnvironmentPlugin({
NODE_ENV: 'development',
}),
],
optimization: {
usedExports: true,
},
})
.babelrc
{
"presets": [
[
"#babel/preset-env",
{
"useBuiltIns": "entry",
"corejs": "3.0.0",
"targets": {
"esmodules": true
}
}
],
"#babel/preset-react"
],
"plugins": [
"react-hot-loader/babel"
]
}
I have updated the files listed to show what I currently have. This is a very weird error as sometimes the hot reloading will work & other times it will not. Hot reloading always works for files; index.js, App.jsx, & routes/index.jsx but sometimes it will work for views/Dashboard/index.jsx & sometimes it will not.
I was previously following the Getting Started guide but this thread helped me realise this was out of date. I have now just followed the README as is mentioned. I have also attempted to take snippets from this article as well on setting up HMR with Webpack 4.
Versions
webpack: 4.41.6
webpack-dev-server: 3.10.3
babel-loader: 8.0.6
#hot-loader/react-dom: 16.11.0
react: 16.12.0
react-hot-loader: 4.12.19
I have the below response in the console so HMR is clearly enabled
I am trying to replicate exactly what is in the examples as recommended

React-hot-loader doesn't work with React-router-dom

So I've finally setup a working project with:
Electron (2.0.2)
React (16.4.0)
React-router-dom (4.2.2)
Webpack (4.11.0)
React-hot-loader (4.2.0)
And just when I started to develop some react components I noticed my project won't hot reload correctly. If I adjust something on the base url (/) it is updated correctly, but if I update something on a secondary url, say /test the webpack compiles, but I get the message Cannot GET /test.
I've tried a lot and I cannot seem to figure out what I am doing wrong. I looked into react-router-dom, since hot-reloading was an issue back in version 3.x, but they say it should be resolved now (in 4.x --> It works here..). Also i've added <base href="/"/> in my index.html so that is not it.
Can anyone tell me what I am doing wrong?
Webpack.common.js (This is merged into Webpack.dev.js)
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
resolve: {
modules: [path.resolve(__dirname), 'node_modules']
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
cacheDirectory: true,
presets: ['env', 'react'],
plugins: ['transform-runtime'],
env: {
development: {
plugins: ['react-hot-loader/babel']
},
production: {
presets: ['react-optimize']
}
}
}
}
]
}
};
Webpack.dev.js
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
entry: {
'app': [
'babel-polyfill',
'react-hot-loader/patch',
path.join(__dirname, 'src', 'index.js')
]
},
plugins: [
new webpack.HotModuleReplacementPlugin() // Enable hot module replacement
]
});
Index.js
import React from "react";
import ReactDOM from "react-dom";
import { AppContainer } from "react-hot-loader";
import { App } from "./app";
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component/>
</AppContainer>,
document.getElementById("root")
);
};
render(App);
if (module.hot) {
module.hot.accept("./app", () => {
render(App);
});
}
App.js (my main entry point for my app, thus where I define my base routing)
import React, { Component } from 'react';
import { BrowserRouter, Route, NavLink } from 'react-router-dom';
import { Test } from './components/test';
import { Test2 } from './components/test2';
export class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<NavLink to="/">Home</NavLink>
<NavLink to="/test">Test</NavLink>
<div>
<Route exact path="/" component={Test}/>
<Route path="/test" component={Test2}/>
</div>
</div>
</BrowserRouter>
);
}
}
And the components 'test' and 'test2' are just plain simple react components with a 'hello world' text.
Anyone who sees anything that I am missing or doing wrong?
Thanks to this tutorial I found a way to adapt my project and get hot loading to work. It even made my code a bit cleaner and my build scripts simpeler.
Webpack.common.js
The first thing I needed to change was the babel-loader. I stole it from some tutorial, and it worked, but I did not know exactly what it did so I got rid of that code. I've also made the compilation of my code faster through the webpack.DllReferencePlugin.
Here is the updated webpack.common.js:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
entry: {
app: [
'babel-polyfill',
'./src/index.js',
],
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
plugins: ['react-hot-loader/babel'],
cacheDirectory: true,
presets: ['env', 'react'],
},
}
],
},
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname),
manifest: require('../dist/vendor-manifest.json'),
}),
new HtmlWebpackPlugin({
title: '<my-app-name>',
filename: 'index.html',
template: './public/index.html',
}),
new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, '../dist/*.dll.js'),
includeSourcemap: false // add this parameter
})
],
};
The AddAssetHtmlPlugin is required since the index.html is dynamically created (by the HtmlWebpackPlugin) for the dev server and you cannot hardcode the correct bundle import for the vendor.dll and the app.bundle (more here).
webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
const path = require('path');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
hot: true,
contentBase: path.resolve(__dirname, 'dist'),
historyApiFallback: true // Allow refreshing of the page
},
plugins: [
new webpack.HotModuleReplacementPlugin(), // Enable hot reloading
]
});
What did I change:
I moved the entry point up to webpack.common.
I Removed the 'react-hot-loader/patch' from the entry
(optional) I've added some config options for the webpack-dev-server.
Index.js
This is the file that caused the hot-reload to fail. Especially the if(module.hot) part caused it to fail. So I've changed it to the following:
import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { App } from './app';
const render = () => {
ReactDOM.render(
<AppContainer>
<App/>
</AppContainer>,
document.getElementById('app'),
);
};
render(App);
if (module.hot) {
module.hot.accept('./app', () => {
const NextApp = require('./app').default; // Get the updated code
render(NextApp);
});
}
The reason it works now is because now I fetch the new app and replace the old one, thus telling the hot-loader there has been a change. I could also just use module.hot.accept(), but that would make the react-hot-loader useless (you make use of the webpack hot-reloader) and this way I would also lose the state within my components every time I updated some code.
So there you go. I hope this will help anyone (other then myself).

React Route not displaying component on production

I am developing a React Webapp and I am using webpack for automating some tasks. The development mode works fine, I can see all components showing up, but when I open index.html from /dist folder where I have bundle.js and bundle.css same directory the webapp does not show the components.
I tried to upload on a apache web server whole /dist folder and tried to access like localhost/dist still I cannot see the comopnents.
Any idea how to make it so the files within dist folder I can use, in fact that's why I am using webpack to automate tasks so I can use this folder for production.
Webpack:
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
const path = require('path');
module.exports = (env, argv) => {
console.log("ENV DETECTED: " + argv.mode);
return {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
//publicPath: '/', // Remove this when running in production
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: {
minimize: true
}
}
]
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
// 'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
minimize: true
}
},
{
loader: 'postcss-loader',
options: {
config: {
path: './postcss.config.js'
}
}
}
]
},
{
test: /\.scss$/,
use: [
argv.mode !== 'production' ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1,
minimize: true
}
},
{
loader: 'postcss-loader',
options: {
config: {
path: './postcss.config.js'
}
}
},
"sass-loader"
]
}
],
},
devServer: {
historyApiFallback: true,
},
plugins: [
new CleanWebpackPlugin('dist', {}),
new HtmlWebPackPlugin({
template: "src/index.html",
filename: "./index.html"
}),
new MiniCssExtractPlugin({
filename: "bundle.css",
chunkFilename: "bundle.css"
}),
require('autoprefixer'),
]
}
};
Routes:
import React from "react";
import { Switch, Route } from 'react-router-dom';
import Helloworld from './components/helloworld/helloworld.component';
import SecondView from './components/secondview/secondview.component';
import ThirdView from "./components/thirdview/thirdview.component";
const AppRoutes = () => (
<main>
<Switch>
<Route exact path='/' component={Helloworld}/>
<Route path='/secondview' component={SecondView}/>
<Route path='/thirdview' component={ThirdView}/>
<Route path='/thirdview/:number' component={ThirdView}/>
</Switch>
</main>
);
export default AppRoutes;
Helloworld component:
import React from 'react';
import HelloworldApi from './helloworld.api';
import { Link , withRouter } from 'react-router-dom';
require('./helloworld.style.scss');
class Helloworld extends React.Component {
constructor(props) {
super(props);
this.state = {
persons: [],
};
}
componentDidMount() {
console.log("I am being called helloworld component...");
HelloworldApi.getAll().then(response => {
if (response.data) {
console.log(response.data);
const persons = response.data;
this.setState({persons});
} else {
console.log(response);
}
});
}
render() {
return (
<div className={"boxDiv"}>
<p>Helloworld components</p>
<h1>Hello World</h1>
<h3>Web pack and React aree awesome together!!! test</h3>
{this.state.persons.map(person => <li>{person.name}</li>)}
<Link to='/secondview'>go to secondview</Link>
</div>
);
}
}
export default withRouter(Helloworld);

React HMR cannot find update - refreshes entire page on change

I'm having an issue that I've seen reported elsewhere (but not really and valid solutions) where when attempting to use react hot module reload, when content in a render method changes, the entire page is refreshed.
client.js
import React from 'react'
import { render } from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import Root from './Root'
ReactDOM.render(
<Root />
, document.getElementById('root'))
// Hot Module Replacement API
if (module.hot) {
module.hot.accept()
}
Root.js
//imports: react, {provider} from react-redux, {AppContainer} from react-hot-loader, other components
const Root = React.createClass({
render () {
return (
<AppContainer>
<Provider store={this.props.store}>
<MainComponent>
{/* bunch of other components */}
</MainComponent>
</Provider>
</AppContainer>
)
}
})
package.json script: yarn run dev
"dev": "webpack-dev-server --env.development"
webpack.config.js
let isProd
module.exports = env => {
isProd = env.production === true
isDev = !isProd
return {
context: __dirname,
entry: {
app: [
'react-hot-loader/patch',
'./js/client.js'
]
},
devtool: env.production ? 'source-map' : 'eval',
// devtool: 'source-map',
output: {
path: path.join(__dirname, 'dist', 'js'),
filename: 'bundle.js',
// publicPath: '/dist/js',
pathinfo: isDev
},
devServer: {
publicPath: '/public/',
historyApiFallback: true,
hot: true,
inline: true,
port: 5888,
proxy: {
'/api': {
target: 'http://localhost:6500'
}
}
},
resolve: {
extensions: ['.js', '.json']
// alias: {
// 'google': path.resolve(__dirname, 'vendor', 'google.js')
// }
},
stats: {
colors: true,
reasons: true,
chunks: true
},
module: {
rules: [
{
enforce: 'pre',
test: /\.js$/,
loader: 'eslint-loader',
exclude: /node_modules/
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
}
}
Versions
"webpack": "^2.6.1",
"webpack-dev-server": "^2.4.5"
On initial load in the console I see [HMR] Waiting for update signal from WDS...
Then when saving a change, the page refreshed and in then console I get
[HMR] Cannot find update. Need to do a full reload!
[HMR] (Probably because of restarting the webpack-dev-server)
How can I get HMR to inject the JS and not reload the page?

Webpack resolve extension "Module not found"

Warning: I'm pretty new to webpack, please be gentle
Okay so I'm trying to set up webpack, and I got everything working fine with es2015 and imports with webpack. I'm running into an issue where now I'm trying to add the extensions to resolve so that I don't have to declare the file extension, but it always says that it can't find the file or module. Any idea why this could be? Here's my index.jsx and my webpack.config.js
// index.jsx
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import App from './components/App'
import configureStore from './store/configureStore.js'
const store = configureStore()
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('app')
)
Here's the webpack.config:
// webpack.config
var path = require('path')
var webpack = require('webpack')
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./src/javascripts/index.jsx'
],
output: {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js',
publicPath: '/public/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
__DEV__: process.env.NODE_ENV !== 'production'
})
],
module: {
loaders: [
{
test: /\.jsx?$/,
loaders: [ 'react-hot', 'babel-loader' ],
include: path.join(__dirname, '/src')
},
{
test: /\.scss$/,
loader: [ 'style', 'css', 'sass' ]
},
{
test: /\.json$/,
loader: 'json'
}
],
preLoaders: [
{ test: /\.js$/, loader: 'source-map-loader' }
],
resolve: {
root: [
path.resolve(path.join(__dirname, 'src', 'stylesheets')),
path.resolve(path.join(__dirname, 'src', 'javascripts'))
],
alias: {
'#style': path.resolve(path.join(__dirname, 'src', 'stylesheets')),
'#script': path.resolve(path.join(__dirname, 'src', 'javascripts'))
},
extensions: [
'',
'.webpack.js',
'.web.js',
'.jsx',
'.js',
'.scss'
]
}
}
};
As I said, if I change line 5 in index.jsx from import App from './components/App' to import App from './components/App.jsx', it works and I have no idea why. Any thoughts?
Your module is wrapping around your resolve, which is ruining the config file. If the resolve isn't there then Webpack can't resolve your extension, forcing you to add the extension. You should always indent uniformly to keep track of and prevent these types of errors.
When you import it without an extension, Webpack doesn't know how to resolve the extension so it can't correctly load it. You have to specify .jsx so then Babel comes in and imports it as a .jsx explicitly.

Categories

Resources