I'm using style-loader with webpack and react framework. When I run webpack in terminal i'm getting Module not found: Error: Cannot resolve module 'style-loader' in import.js file although i've specified the file path correctly.
import '../css/style.css';
import React from 'react';
import ReactDOM from 'react-dom';
import jQuery from 'jquery';
import TopicsList from '../components/topic-list.jsx';
import Layout from '../components/layout.jsx';
webpack.config.js:
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'build');
var APP_DIR = path.resolve(__dirname, 'build');
module.exports = {
entry: [
// Set up an ES6-ish environment
'babel-polyfill',
// Add your application's scripts below
APP_DIR + '/import.js'
],
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
plugins: ['transform-runtime'],
presets: ['es2015', 'stage-0', 'react']
}
},
{ test: /\.css$/, loader: "style-loader!css-loader" }
],
resolve: {
extensions: ['', '.js', '.jsx', '.css']
}
}
};
Try run script below:
npm install style-loader --save
Modify webpack config, add modulesDirectories field in resolve.
resolve: {
extensions: ['', '.js', '.jsx', '.css'],
modulesDirectories: [
'node_modules'
]
}
Please run this script:
npm install style-loader css-loader --save
Set your module as below:
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
include: path.join(_dirname, 'app')
},
{
test: /\.css$/,
loader: 'style-loader!css-loader'
}
],
resolve: {
extensions: ['', '.js', '.jsx', '.css']
}
}
It's basically reading as for loaders - test jsx using babel-loader and the next test is a css file using style-loader and css-loader, which will recognize the modules. Also, you should exit out of npm start, and run "npm install" and run "npm start". Hopefully, this should take care of the issue.
If you try to import a css file with this line:
import '../css/style.css';
and have added the style-loader in your webpack config.
The error states:
Module not found: Error: Cannot resolve module 'style-loader'
the module named "style-loader" is not resolved.
You need to install that module with:
$ npm install style-loader --save-dev
Or, if you're using yarn:
$ yarn add style-loader -D
Then run webpack again.
I wanted to add on to what David Guan said. In the newer versions of Webpack (V2+) moduleDirectories has been replaced with modules. The updated resolve portion of his answer would look like this:
resolve: {
extensions: ['.js', '.jsx', '.css'], //An empty string is no longer required.
modules: [
'node_modules'
]
}
For more information you can check out their official documentation. Hope this helps someone out there.
Under Webpack 3, with node_module in a non-standard location, I had to use both resolve and resolveLoader configuration objects:
resolve: {
modules: ["build-resource/js/node_modules"]
},
resolveLoader: {
modules: ["build-resource/js/node_modules"]
},
I use Windows and did everything but nothing worked. It appeared console didn't have enough permissions. So, after running in Admin mode I re-entered
npm install
and everything worked. You can see the result by appearing a lot of modules in node_modules directory.
If you're node_modules are on the same dir as your webpack config file you can simply add context: __dirname.
module.exports = {
context: __dirname,
entry: [
...
(works in both webpack 1 and 2)
remove 'style-loader!css-loader', make it ['style-loader','css-loader']
remove empty string '' from extensions array. It will be look like bellow
module:{
rules:[
{test:/\.css$/,use:['style-loader','css-loader']},
]
},
resolve: {
extensions: ['.js', '.jsx', '.css'],
},
it is very simple you have to install the fist syle-loader the css-loader.
Related
Today I observed babel/babel-loader exhibiting some undesirable behavior. I am bundling some assets for usage on nodejs. Post-compile, a bundle is generated with references to #babel/runtime/**/esm/**. Of course, node cannot import such files, and on node bundle.js I get:
Must use import to load ES Module: /my/project/node_modules/#babel/runtime/helpers/esm/defineProperty.js
require() of ES modules is not supported.
Right. Makes sense. But babel-loader injected those imports. In fact, the parent folder in #babel/runtime has all of the non-ESM things, which I actually probably do want imported! My babel config looks as such:
{
presets: [
[
"#babel/preset-env",
{
modules: 'commonjs',
targets: {
node: "current",
esmodules: false,
},
},
],
"#babel/preset-typescript",
]
}
As you can see, I'm attempting to tell babel via targets.esmodules: false and modules: 'commonjs' to use commonjs. I hoped these entries would tell babel to not expect ESM compatibility! None the less, generated bundles still look like:
...
var _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! #babel/runtime/helpers/esm/toConsumableArray */ "#babel/runtime/helpers/esm/toConsumableArray"));
My full webpack config is pretty terse as well:
{
entry: serverFilename,
mode: 'development',
output: {
path: path.dirname(serverBuildFilename),
filename: path.basename(serverBuildFilename)
},
target: "node",
externals: [webpackNodeExternals()],
optimization: {
moduleIds: 'named',
minimize: false
},
resolve: {
extensions: ['.ts', '.tsx', '.wasm', '.mjs', '.js', '.json'],
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: babelConfig.presets // see babel config above
}
}
},
],
},
}
I can't tell if I'm missing configuration, if babel isn't respecting my configuration, or <your ideas here>!
All tips appreciated. Thanks!
It took me a while to figure out the solution and this post helps
https://github.com/webpack/webpack/issues/11696
Copied my solution from the issue here:
I ended up using webpack-node-externals in webpack config to sort of bypass this issue
const nodeExternals = require('webpack-node-externals');
// add these to the webpack config.
externals: [
nodeExternals({
whitelist: [/^#babel\/runtime/],
}),
],
This solution creates duplicated babel/runtime file injections and can also be mitigated by https://webpack.js.org/loaders/babel-loader/#babel-is-injecting-helpers-into-each-file-and-bloating-my-code
I have a multi-package project set up, where I have one JavaScript package that relies on a TypeScript library. Initially I installed Sinopia and was reinstalling the library every time I made changes to it. Then I saw npm link and thought that it would be easier for development. Unfortunately, when I linked the library (using npm link ../typescript-package) and built, it gives an error:
ERROR in ../typescript-package/dist/index.js
Module build failed: Error: No ESLint configuration found.
Since they are separate packages, I'm not quite sure why Webpack is trying to apply eslint to this package. Here is my webpack.common.js file (using merge and the dev vs prod configs shouldn't matter):
// webpack.common.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const babelOptions = {
presets: ['react', 'es2015', 'stage-0'],
sourceMaps: true,
retainLines: true,
};
module.exports = {
entry: {
solver: './source/index.jsx',
},
output: {
path: `${__dirname}/dist`,
filename: '[name].js',
publicPath: '/dist/',
},
resolve: {
modules: ['source', 'node_modules/'],
extensions: ['.js', '.jsx', '/index.jsx', '.json', '.ts', '/index.ts', '.scss', '/index.scss', '.css'],
},
module: {
rules: [
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader',
options: babelOptions,
},
{
loader: 'eslint-loader',
options: {
emitWarnings: true,
},
},
],
exclude: /node_modules/,
}, {
test: /\.js$/,
loader: 'source-map-loader',
enforce: 'pre',
exclude: /node_modules/,
}, {
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {
minimize: true,
localIdentName: '[local]_[hash:base64:5]',
},
}, {
loader: 'sass-loader',
options: {
includePaths: ['source/design'],
},
}],
}),
},
],
},
plugins: [
new ExtractTextPlugin({
filename: '[name].css',
allChunks: true,
}),
],
node: {
global: true,
},
};
I can also provide other config or package.json files if need be.
Way 1 - Webpack recommendation
According to webpack doc : https://webpack.js.org/configuration/module/#rule-conditions
Be careful! The resource is the resolved path of the file, which means symlinked resources are the real path not the symlink location. This is good to remember when using tools that symlink packages (like npm link), common conditions like /node_modules/ may inadvertently miss symlinked files. Note that you can turn off symlink resolving (so that resources are resolved to the symlink path) via resolve.symlinks.
So according to it you can disable symlink : https://webpack.js.org/configuration/resolve/#resolvesymlinks
Way 2 - Fancy hack
But maybe you need symlinks for your project. So, I use my eslint rule like this :
{
test: /\.js$/,
enforce: 'pre',
use: 'eslint-loader',
include: path.resolve(__dirname), // <-- This tell to eslint to look only in your project folder
exclude: /node_modules/
}
Plus obviously your own config of this loader.
I was dealing with this, as well. I'm not exactly sure why ESLint is looking for the config file in the external package (I would expect the local rc file to be adequate) but the symlink created by npm link takes the external package out of ./node_modules/, which otherwise would have been excluded by the loader.
The fix I've come up with is to copy the package into ./node_modules/. It then gets filtered out through the excludes rule in your Webpack config.
I know this is incredibly inelegant, and shouldn't be "good enough", but I've spent some time trying to get around this issue, and this is the best I was able to come up with. Until something better comes along, you can at least get moving on more pressing issues.
You can also add a .eslintignore file and add the real path to the linked module
// Content of .eslintignore
C:/path/to/your/linked/module
This is needed, because webpack resolves the module by its real path and not by the path in the node_modules folder (see webpack docs). Usually eslint ignores node_modules by default, but because of that it does not work here.
About a week ago I ran into a problem while adding HMR to my project, the problem was that it just didn't work, the console showed HMR Enabled and also detected changes on the files, but it didn't re-render the view, the console would log:
[HMR] Updated modules:
[HMR] - ./app/src/components/app.jsx
[HMR] App is up to date.
but nothing would change visually, neither in the code inspector.
After lots of experimenting I found out that the problem was being caused by the babel-loader, it somehow interfered with webpacks HMR motor or something like that. I solved it by excluding the index file in the babel loader, however I don't think that's the best approach since now I can't use some js features in my index.jsx file. I want to know if theres a better way to solve this issue, perhaps something in my configuration or in the way of setting up webpacks hot middleware.
This is my webpack configuration:
module.exports = {
resolve: {
extensions: ['*', '.js', '.jsx']
},
entry: [
'webpack-hot-middleware/client', './app/src/index.jsx'
],
output: {
path: path.resolve(__dirname, 'build/js'),
filename: 'bundle.js',
publicPath: '/public'
},
devtool: 'cheap-module-source-map',
module: {
rules: [{
test: /\.jsx?$/,
exclude: /node_modules/,
include: path.resolve(__dirname, 'app/src/'),
exclude: path.resolve(__dirname, 'app/src/index.jsx'),
use: [{
loader: 'babel-loader',
options: {
presets: [
'react-hmre'
],
plugins: [
'transform-object-rest-spread'
]
}
}],
}]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
}
And this is how I setup the hot middleware and react-hot-loader in my server:
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const webpackConfig = require('./webpack.dev.config')
const compiler = webpack(webpackConfig)
app.use(webpackDevMiddleware(compiler, {
noInfo: true,
publicPath: webpackConfig.output.publicPath
}))
app.use(webpackHotMiddleware(compiler))
Thanks in advance.
So it was the babel configuration as I thought, you need the option modules: false in the env preset so it lets webpack handle the modules, it is a noob mistake but man, it drove me crazy for days.
The correct config for the env preset its like so:
['env', {modules: false}]
I followed this tutorial to setup a react project and I thought I nailed it. After installing everything works as it should.
But I have to create a website that uses foundation as a front-end lib. The tutorial I linked above runs server.js when I run npm start but foundation-cli uses the same command for compiling all foundation sass code to css.
At the moment when I run npm start it only runs react and not foundation. How can I run foundation too? can I make it so that it'll automatically run both?
Since you are already using Webpack, I would suggest you to use one of the loaders for it and compile your CSS with it. This one seems like it can do that for you.
This is not tested, but I assume you can add it to your Webpack config like this:
// be sure to install it with
// npm install sass-loader node-sass --save-dev
const path = require('path');
module.exports = {
context: path.join(__dirname, 'src'),
entry: [
'./main.js',
],
output: {
path: path.join(__dirname, 'www'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
'babel-loader',
],
},
{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}
}
],
},
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
],
},
};
I've been banging my head over this for a while, and am wondering if it's even possible to begin with. Thanks for any help with this!
The npm package
I've got an npm package which is basically a library of React components. This library has embedded stylesheets, which references assets like fonts and images from the CSS. These are then all bundled using webpack into my-package.js.
The config for this looks like:
var path = require('path');
module.exports = {
module: {
loaders: [
{
test: /\.js$/,
loaders: ['babel-loader'],
exclude: /node_modules/
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
loader: 'file-loader'
},
{
test: /\.styl$/,
loader: 'style-loader!css-loader!stylus-loader'
}
]
},
entry: [
'./lib/components/index.js',
'./lib/index.styl'
],
output: {
path: path.join(__dirname, 'build/'),
filename: 'my-package.js'
}
}
With ./lib/components/index.js looking like:
import '../index.styl';
import MyComponent from './my-component.js';
export {
MyComponent
}
So far, so good.
The application
Now in another code base I've got the main application, which install this npm package.
My application root requires this package...
import MyPackage from 'my-package';
And is then itself webpack bundled and loaded onto the browser. All the scripts and style blocks are bundled correctly, however the styles which reference the assets are using the relative url from the npm package itself, therefore giving me 404s from the application.
console errs
Is there any way to tell webpack to resolve these images from node_modules/my-package/build/[webpack-generated-name].jpg ?
My application's webpack config looks like this:
var path = require('path'),
webpack = require('webpack');
module.exports = {
devtool: '#eval-source-map',
entry: [
'my-package',
'webpack/hot/only-dev-server',
'./app/index.js',
],
output: {
path: path.join(__dirname, 'build/static'),
filename: 'bundled.js',
publicPath: '/',
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
resolve: {
extensions: ['', '.js']
},
resolveLoader: {
'fallback': path.join(__dirname, 'node_modules')
},
module: {
loaders: [
{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
exclude: /node_modules/,
include: __dirname
},
{
test: /\.css?$/,
loader: "style-loader!css-loader",
include: __dirname
},
{
test: /\.(jpg|jpeg|ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader'
},
{
test: /\.styl$/,
loader: 'style-loader!css-loader!stylus-loader'
}
]
}
};
Figured out a way around this.
In my application's webpack config I added a plugin (recommended by #Interrobang) which copies the static assets from the node_module/my-package into the app server's public path:
var TransferWebpackPlugin = require('transfer-webpack-plugin');
...
plugins: [
new TransferWebpackPlugin([
{ from: 'node_modules/my-package/assets', to: path.join(__dirname, 'my/public') }
])
]
...
These will then be made accessible by calling the asset name: localhost:XXXX/my-image.jpg. The server here is basically looking at /my/public/my-image.jpg if you've set it up correctly.
I'm using Express, so I just had to define app.use(express.static('my/public')) in my app server.
When bundling your NPM package, you could inline all the static assets into your final bundle. That way, your index.js that Webpack bundles for you would have all the static assets it needs, and simply importing that wherever you need your React components would do the trick.
The best way to inline static assets as of Webpack 5 is by using the "asset/inline" module from Asset Modules, which you can read about here: https://webpack.js.org/guides/asset-modules/
Simply put, your webpack.config.js should have a section as such:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
type: 'asset/inline'
}
]
},
};
What really relates to your question here is the test for png, jpg, and gif files which uses the asset/inline module.
The post here https://stackoverflow.com/a/73417058/14358290 explains it with slightly more detail.
Other plugins that copy such files from your /node_modules to /build directory are hacky and create packages that are not really distributable - everyone else that uses the said package would have to set up their Webpack to do the same copying operation. That approach can be avoided now that Webpack 5 solves this problem for us.