Webpack resolve extension "Module not found" - javascript

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.

Related

Cannot import react js component

I trying to import a react component to jsx file but it throws this exception:
This is my main code:
import React, { Component } from "react";
import Sidebar from "./Sidebar";
class App extends Component{
render(){
return (
<Sidebar/>
);
}
}
ReactDOM.render(
<App />,
document.getElementById("root")
);
and this is my Sidebar component:
import React, { Component } from "react";
export default class Sidebar extends Component{
render(){
return (
<h1>Hello Sidebar</h1>
);
}
}
My folders structure:
I post simpler version which I know does work:
./index.js :
import React from 'react';
import ReactDOM from 'react-dom';
import Application from './components/Application'
ReactDOM.render(<Application />, document.getElementById('root'));
./components/Application :
import React from 'react';
class Application extends React.Component {
render() {
return (
<div className="App">
My Application!
</div>
);
}
}
export default Application;
This should be everything needed to make it work.
If you want to shorten the above even more, by removing the export line at the bottom, a less traditional approach would be defining the class like this...
export default class Application extends React.Component {...}
Looks like you haven't added rule for .jsx file in webpack.config.js.
Since you have both .js and .jsx files you need to tell webpack to load files with extension .js and .jsx. Add below config to webpack.config.js in rules section
{
//tell webpack to use jsx-loader for all *.jsx files
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader"
}
And add extensions like
resolve: {
modules: [
path.resolve("./src"),
path.resolve("./node_modules")
],
extensions: [".js", ".jsx"]
}
Below is the working webpack.config.js file for your ref
module.exports = {
target: "web",
entry: [
"whatwg-fetch",
'webpack-dev-server/client',
'webpack/hot/only-dev-server',
'babel-polyfill',
"./src/index.js"
],
output: {
path: __dirname + 'build',
publicPath: '/',
filename: "bundle.js"
},
plugins: [new HtmlWebpackPlugin({
template: "index.html"
}),
new CompressionPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.jsx$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8
}),
new webpack.HotModuleReplacementPlugin(),
// enable HMR globally
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{
//tell webpack to use jsx-loader for all *.jsx files
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
},
{
test: /\.(eot|ttf)$/,
loader: "file-loader",
},
{
test: /\.scss$/,
loaders: ["style-loader", "css-loader", "sass-loader"]
}
]
},
resolve: {
modules: [
path.resolve("./src"),
path.resolve("./node_modules")
],
extensions: [".js", ".jsx"]
},
devServer: {
watchOptions: {
// Needed for Windows Subsystem for Linux dev environment:
poll: true
},
contentBase: './build'
},
devtool: "cheap-module-eval-source-map",
node: {
child_process : "empty",
fs: "empty"
}
};

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 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?

“You may need an appropriate loader to handle this file type” with Webpack and Babel

I'm upgrading from an arcane version of webpack to webpack 2 and I'm getting an error:
ERROR in ./scripts/app.js
Module parse failed: /Users/zackshapiro/dev/glimpse-electron/node_modules/eslint-loader/index.js!/Users/zackshapiro/dev/glimpse-electron/scripts/app.js Unexpected token (32:4)
You may need an appropriate loader to handle this file type.
|
| render((
| <Provider store={store}>
| <Home />
| </Provider>
# multi (webpack)-dev-server/client?http://localhost:8081 webpack/hot/dev-server ./scripts/app.js
My webpack.config.js looks like this:
const webpack = require('webpack');
const path = require('path');
console.log(path.resolve(__dirname, 'public/built'));
console.log("we here");
module.exports = {
entry: {
app: ['webpack/hot/dev-server', './scripts/app.js']
},
output: {
// path: './public/built',
path: path.resolve(__dirname, 'public/built'),
filename: 'bundle.js',
publicPath: 'http://localhost:8080/built/'
},
devServer: {
contentBase: './public',
publicPath: 'http://localhost:8080/built/'
},
module: {
rules: [
{
test: /\.jsx?$/,
enforce: "pre",
loader: "eslint-loader",
exclude: /node_modules/
},
],
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['react', 'es2015', 'stage-3']
}
},
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.scss$/, loader: 'style-loader!css-loader!sass-loader'},
{ test: /\.(ttf|eot|otf|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" }
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.IgnorePlugin(new RegExp("^(fs|ipc)$")),
new webpack.LoaderOptionsPlugin({
options: {
eslint: {
failOnWarning: false,
failOnError: true
}
}
})
]
}
And my app.js looks like this:
require('../styles/main.scss');
require('../styles/menubar.scss');
require('../styles/panel.scss');
require('../styles/sky.scss');
require('../styles/dock.scss');
require('../styles/sector.scss');
require('../styles/slot.scss');
require('../styles/element_builder.scss');
'use strict';
import 'babel-polyfill';
import React from 'react';
import {render} from 'react-dom';
import {Provider} from 'react-redux';
import {compose, createStore, applyMiddleware} from 'redux';
import createSagaMiddleware from 'redux-saga';
import reducer from './entities/reducers';
import sagas from './entities/sagas';
import Home from './containers/home';
const sagaMiddleware = createSagaMiddleware();
const composedCreateStore = compose(applyMiddleware(sagaMiddleware))(createStore);
const store = composedCreateStore(reducer, {});
sagaMiddleware.run(sagas);
render((
<Provider store={store}>
<Home />
</Provider>
), document.getElementById('content'));
I don't have a .babelrc file in my root directory because I have that object in my loaders in webpack.config.js
Any suggestions on how to fix this would be very welcome. Thanks!
module.rules replaces module.loaders in Webpack 2, so it's possible that by providing both Webpack isn't using module.loaders (which is there for backwards-compatibility) at all - try moving the rules you currently have in module.loaders into module.rules instead.
Edit: peeking inside the current version of Webpack's NormalModuleFactory, this is what it's doing:
this.ruleSet = new RuleSet(options.rules || options.loaders);

Uncaught ReferenceError: Link is not defined React

I am using react 0.14.7 with webpack 1.12.13 and I get the following error:
Uncaught ReferenceError: Link is not defined
This error is happening in the browser and everything compiles without error.
import React from 'react'
import { Link } from 'react-router'
export default React.createClass({
render() {
return <Link {...this.props} activeClassName="active"/>
}
})
webpack.config
var webpack = require('webpack')
module.exports = {
entry: './src/client/js/index.js',
output: {
path: 'public',
filename: 'bundle.js',
publicPath: '/'
},
resolve: {
extensions: ['', '.js', '.jsx']
},
plugins: process.env.NODE_ENV === 'production' ? [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin()
] : [],
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015&presets[]=react' },
{ test: /\.scss$/, loaders: ['style', 'css', 'sass']}
]
},
}
A little more, to add to the confusion I have consoled react-router and there is nothing there:
import router from 'react-router'
console.info(router); //undefined
Use react-router-dom instead.
import { Link } from 'react-router-dom'
...
See react-router-dom on npm.

Categories

Resources