Webpack 2: cannot resolve module - javascript

I have a project like this:
root/
webpack-config.js
app/
app.js
js/
dep.js
core/
module.js
Here is the webpack config file:
module.exports = {
entry: './app/app.js',
output: {
path: __dirname,
filename: "[name]-bundle.js"
},
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }
]
},
resolve: {
modulesDirectories: ['core']
}
...
in app.js, I have:
import local_dep from './js/dep';
import myModule from 'module';
This works as expected with webpack 1.x, but the myModule module isn't resolved with webpack 2, I'm getting "Module not found: can't resolve 'module' in ... \app".
It seems the modulesDirectories entry is ignored and the base URL corresponds to the entry's folder.
What can I do to make modules resolve correctly with webpack 2 ?

from: http://moduscreate.com/webpack-2-tree-shaking-configuration/
In Webpack 2, resolvers from root, modulesDirectories, and fallback settings will merge into a single property – modules. Here is how we can resolve file and module locations in Webpack 2:
resolve: {
modules: [
path.resolve('./client'),
'node_modules'
]
},
You can specify a number of directories in modules, but make sure not to forget node_modules or npm package dependencies will fail to load.
So in your case what was before:
resolve: {
modulesDirectories: ['core']
}
now needs to be
resolve: {
modules: ['core'] // also 'node_modules'
}

Edit: As others have noted, for Webpack 2, something like this works:
{
resolve: {
extensions: ['.js', '.jsx'],
modules: ['node_modules', path.resolve(__dirname, 'core')]
},
}
For Webpack 1, I have a setup that has this entry:
config.resolve = {
// Allows us to include js and jsx files without specifying the extension
extensions: ['', '.jsx', '.js'],
root: [path.resolve('./core')]
};

Thanks to Christopher Davies I fixed the problem by adding:
resolveLoader: {
root: path.join(__dirname, 'node_modules')
},
resolve: {
root: ['./core']
}
I had to add resolveLoader line otherwise I was getting an error about babel-loader that could not be loaded.

Related

Webpack "Module not found: Error: Can't resolve './src/'"

I have two HTML pages, each will include it's own bundle. Here is my project structure:
public/
-- dist/
src/
-- firebase/
-- network/
webpack.config.js
Here's my webpack config:
const path = require('path');
const CleanTerminalPlugin = require('clean-terminal-webpack-plugin');
module.exports = {
mode: "development",
entry: {
network: path.resolve(__dirname, 'src') + '/network/index.ts',
firebase: path.resolve(__dirname, 'src') + '/firebase/index.ts'
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
path: path.resolve(__dirname, 'public') + '/dist',
},
plugins: [new CleanTerminalPlugin()]
};
I expect this to create two bundles in public/dist with the names firebase.js and network.js. Instead I get an error:
ERROR in main Module not found: Error: Can't resolve './src/' in 'path/to/project/root'
It also says Field 'browser' doesn't contain a valid alias configuration /path/to/project/root/src/index doesn't exist
And repeats that for .tsx, .ts and .js
I don't know why it's looking for an index.* file in my src/. I didn't specify that as an entry file. If I create a src/index.ts it builds, but only makes one bundle called main which is not my expected behavior.
It ended up being a really stupid issue, but I'll post the answer in case someone needs it.
I was invoking webpack with webpack ./src but webpack without the ./src worked as expected.

Why can't Webpack resolve ‘babel-loader’?

When I configure Webpack for this code base, Webpack complains that it Can't resolve 'babel-loader'. What exactly is failing, and how can I ask Webpack what its complaint is?
The Webpack configuration:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './source/main.jsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
},
resolve: {
modules: [
path.resolve(__dirname, 'source'),
'/usr/share/javascript',
'/usr/lib/nodejs',
],
},
module: {
loaders: [
// Transform JSX with React.
{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react'],
},
},
],
},
};
The entry module:
// source/main.jsx
"use strict";
import Application from './components/Application';
const applicationElement = <Application />;
ReactDOM.render(
applicationElement,
document.getElementById('application'),
);
Is the problem something like a search path, and if so why can't the error tell me what setting I need to correct?
The babel-loader module is definitely installed. (I therefore don't want to install it again – so npm install won't help – I am trying to tell Webpack to use it from the already-installed location.) Its package definition is at /usr/lib/nodejs/babel-loader/package.json.
I've pointed Webpack's resolver there – instead of its default resolver behaviour – using the resolve.modules list of search paths. Correct?
So the resolver should be able to find it there by the specified search path /usr/lib/nodejs and the name babel-loader, no?
(This raises a separate question, about how to convince Webpack to just tell me what it's looking for so it can be diagnosed more easily.)
How can I tell Webpack the specific location it should use to resolve that babel-loader name?
The Webpack configuration setting resolve is for modules that are imported. The loaders are resolved differently; the resolveLoader setting configures how to resolve the loaders specifically.
So, adding resolveLoader to the Webpack configuration works:
// webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './source/main.jsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
},
resolve: {
// Configure how Webpack finds modules imported with `import`.
modules: [
path.resolve(__dirname, 'source'),
'/usr/share/javascript',
'/usr/lib/nodejs',
],
},
resolveLoader: {
// Configure how Webpack finds `loader` modules.
modules: [
'/usr/lib/nodejs',
],
},
module: {
loaders: [
// Transform JSX with React.
{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react'],
},
},
],
},
};
I think that the webpack.config you're looking for is the following:
module: {
loaders: [
{test: /\.js$/, include: path.join(__dirname, 'src'), loaders: ['babel']},
]
}
Hope helps :)

VueJS with Webpack: imports and exports not working as expected

I started a new Vuetify / Webpack project, and tried to implement vue-router after setting up a project via vue init vuetify/webpack.
I set up the router based on the instructions from this tutorial. After some fiddling, I got it working by changing the way I imported Vue components.
In my router/index.js file:
// works for me
import Main from '../components/Main.vue'
// does NOT work; from the tutorial
import Main from '#/components/Main'
My question is, why do I have to import my Main.vue file relatively and include the .vue extension on the import?
My project structure:
-node_modules/
-public/
-src/
|-components/
||-Main.vue
|-router/
||-index.js
|-App.vue
|main.js
-index.html
-package.json
-webpack.config.js
My webpack.config.js file:
var path = require('path')
var webpack = require('webpack')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
resolve: {
alias: {
'public': path.resolve(__dirname, './public')
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
objectAssign: 'Object.assign'
}
},
{
test: /\.styl$/,
loader: ['style-loader', 'css-loader', 'stylus-loader']
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
devServer: {
historyApiFallback: true,
noInfo: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}
You are attempting to load a file from an alias directory named #. But in your webpack config file, you haven't defined that alias.
Also, you are required to specify the .vue extension because you haven't added it to the resolvable extensions in the resolve property in your config object.
In your webpack.config.js file, add a list of extensions to resolve and an alias called # which maps to your src directory:
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
'#': path.resolve(__dirname, './src'),
...
}
...
}
Edit: #evetterdrake informed me that when using vue-cli to set up a project with Vuetify, the resolve config property is positioned after the module property, which is different than when setting up a normal Webpack project.
Be sure to add these config options to the existing resolve property or it will be overwritten and ignored.

ReactJS test files issue 'cannot find module' because of webpack module resolver

i'm developing an application with react.js. My application is growing up. So i had little trouble with imports. For example i have a component named foo i'm using it in many places.
import foo from '../../components/foo';
import foo from '../components/foo';
import foo from '../../../components/foo';
As you can see its dirty, not good. So i searched to fix it and i found a solution with webpack. Also i read that title (Configure Webpack’s modules resolution to avoid nested imports) in this article
I added this code into my webpack.config.js file
modules: [
'node_modules',
path.resolve(__dirname, 'src')
]
So my resolve object looks like this
export default {
resolve: {
modules: [
'node_modules',
path.resolve(__dirname, 'src')
],
extensions: ['*', '.js', '.jsx', '.json']
},
...
After that i am able to use import my foo component in anywhere like this.
import foo from 'components/foo';
Everything is okay so far. But problem shows up in test files.
When i try to test foo component it says
Cannot find module 'components/foo' from 'foo.js'
Example test file.
foo.spec.js
import React from 'react';
import foo from 'components/foo';
describe('(Component) foo', () => {
it('should render foo', () => {
expect(true).toBe(true);
});
});
Here is the first problem. I can not import foo like this.
Note: My test file is not in src folder it is in the test folder.
So i changed the path like this then it worked.
import foo from '../../../src/components/foo';
Tes passed everything is looks fine. But we still have the path problem in test files.
Lets try to import another component in foo component.
foo.js
import bar from 'components/admin/bar';
Here is the second problem. Test file FAILED error message is
Cannot find module 'components/admin/bar' from 'foo.js'
I moved my test file in to my foo.js file. But didn't worked.
Here is my whole webpack.config.js
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import autoprefixer from 'autoprefixer';
import path from 'path';
export default {
resolve: {
modules: [
'node_modules',
path.resolve(__dirname, 'src')
],
extensions: ['*', '.js', '.jsx', '.json']
},
devtool: 'inline-source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
entry: [
// must be first entry to properly set public path
'./src/webpack-public-path',
'webpack-hot-middleware/client?reload=true',
path.resolve(__dirname, 'src/index.js') // Defining path seems necessary for this to work consistently on Windows machines.
],
target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
output: {
path: path.resolve(__dirname, 'dist'), // Note: Physical files are only output by the production build task `npm run build`.
publicPath: '/',
filename: 'bundle.js'
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'), // Tells React to build in either dev or prod modes. https://facebook.github.io/react/downloads.html (See bottom)
__DEV__: true,
//'API_URL': API_URL.dev
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({ // Create HTML file that includes references to bundled CSS and JS.
template: 'src/index.ejs',
minify: {
removeComments: true,
collapseWhitespace: true
},
inject: true
}),
new webpack.LoaderOptionsPlugin({
minimize: false,
debug: true,
noInfo: true, // set to false to see a list of every file being bundled.
options: {
sassLoader: {
includePaths: [path.resolve(__dirname, 'src', 'scss')]
},
context: '/',
postcss: () => [autoprefixer],
}
})
],
module: {
rules: [
{test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel-loader']},
{test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader'},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader?limit=10000&mimetype=application/font-woff'
},
{test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=application/octet-stream'},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url-loader?limit=10000&mimetype=image/svg+xml'},
{test: /\.(jpe?g|png|gif)$/i, loader: 'file-loader?name=[name].[ext]'},
{test: /\.ico$/, loader: 'file-loader?name=[name].[ext]'},
{
test: /(\.css|\.scss|\.sass)$/,
loaders: ['style-loader', 'css-loader?sourceMap', 'postcss-loader', 'sass-loader?sourceMap']
}
]
}
};
How can i solve?
Thanks for your help.
Webpack is not used during test execution. Since you are using babel the babel-plugin-module-resolver https://github.com/tleunen/babel-plugin-module-resolver should solve the issue:
in your .babelrc file
{
"plugins": [
["module-resolver", {
"root": ["./src"]
}]
]
}
A more cleaner approach would be to create an alias in your .babelrc file and then import from that alias, for instance:
{
"plugins": [
["module-resolver", {
"alias": {
"#app": "./src"
}
}]
]
}
And in your file:
import foo from '#app/components/foo'
That way you have no naming conflicts and your paths are nice and short.
Problem solved after i changed this jest object in package.json file.
"jest": {
"moduleDirectories": [
"node_modules",
"src"
]
...

Webpack multiple entry point confusion

From my initial understanding of webpack's multiple entry point such as
entry: {
a: "./a",
b: "./b",
c: ["./c", "./d"]
},
output: {
path: path.join(__dirname, "dist"),
filename: "[name].entry.js"
}
It will bundle them as a.entry.js, b.entry.js and c.entry.js. There is no d.entry.js since it's part of c.
However at work, these values are confusing me so much. Why is the value an http link and not a file?
app: [
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:21200',
'./lib/index.js'
],
test: [
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:21200',
'./test/test.js'
]
As already stated in a comment on the question, the HTTP URLs are used for webpack-dev-server and its hotloading module. However, you want to ommit those modules for the production version of your bundle, since you don't need the hotloading and it makes your bundle easily over 10.000 lines of code (additionally!).
For the personal interest of the poster, here is an example production config (minimalistic), for a project of mine (called dragJs).
// file: webpack.production.babel.js
import webpack from 'webpack';
import path from 'path';
const ROOT_PATH = path.resolve('./');
export default {
entry: [
path.resolve(ROOT_PATH, "src/drag")
],
resolve: {
extensions: ["", ".js", ".scss"]
},
output: {
path: path.resolve(ROOT_PATH, "build"),
filename: "drag.min.js"
},
devtool: 'source-map',
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
include: path.resolve(ROOT_PATH, 'src')
},
{
test: /\.scss$/,
loader: 'style!css!sass'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
};
A few things:
I only use one entry point, but you could use multiple, just as you do in your example
The entry point only refers to my js file - no webpack-dev-server for production
The config file is written using ECMAScript2015 (thus the name *.babel.js)
It uses sourcemaps and an uglify optimization plugin
The presets for the babel-loader are specified in my .babelrc file
Run webpack with this config via webpack -p --config ./webpack.production.babel.js
If there are any further questions, I would be grateful to answer them in the comments.

Categories

Resources