Webpack 2 svg files give 404 error - javascript

Started working with webpack. In one of my css files I have an url to an svg file, but by using webpack I get 404 error when trying to load this file, tried few loaders first, second and last. Have no idea why its not working, can some one help me or give some info?
EDIT
entry: [
'./src\\main\\resources\\static\\webpack-js\\header.js'
],
output: {
path: path.join(__dirname, 'src/main/resources/static/dist'),
publicPath: '/src/main/resources/static/dist/',
filename: 'bundle.js',
libraryTarget: 'var',
library: 'EntryPoint',
},
module: {
loaders: [
{
test: /\.css$/,
loader: 'style-loader!css-loader'
},
{
test: /\.(jpe?g|png|gif|svg)$/,
loader: 'url-loader'
},
{
test: /\.js$/,
loader: ['buble-loader'],
exclude: '/node_modules/'
}
],
}
This is my module from webpack.config.js. I am using css file that is required in header.js (entry file). Now in the css file I have lines like this
.vismaicon-menu.vismaicon-info:before {
background-image: url(/static/css/img/vismaicons/top_menu/menu_info.svg);
}
As I mentioned I tried few things to load svg files but I'm getting 404 error. And yes url is correct and files are there, it works without webpack. Everything other than svg works in css files and I get things from it.

Changed my Loaders for svg to this one and giving bigger limit solved my problem.
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: "url-loader?limit=1000000&mimetype=image/svg+xml"
},

Related

Error: Can't resolve './images/sample.png' React Webpack

Been trying to build a MERN app with Webpack, and can't seem to load any images in React.
React component render method:
const logo = require('./images/sample.png');
<img src={logo}'/>
Webpack
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loaders: ['babel-loader'] },
{ test: /\.css$/, use: ['style-loader','css-loader']},
{test: /\.(jpg|png|svg)$/, loader: 'url-loader'}
] }
ouputs bundle.js into src folder, file structure below
File structure
app
|......src
.........|components
....................|component.js
.........|images
....................|sample.png
It doesn't matter how I change the path in require, and even if I put the sample.png image in the same folder as component.js I get the error that it can't be resolved. I'm thinking it must be a webpack error, but no matter how many tutorials and forums I read I can't fix it.
Ideally I would dynamically load images rather than declaring specific requires like this, so if theres a better way please tell me.
UPDATE:
I changed src={logo} to src={require("${logo}")}, and no longer get a server-side error. Instead, I get an error in the developer console (using Chrome) that seems to be returning the img URI (react problem?):
Uncaught Error: Cannot find module 'data:image/png;base64...'
In your web.config.js you need
const imageLoaderConfiguration = {
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]',
},
},
};
and add it here
module: {
rules: [
...
imageLoaderConfiguration,
...
],
},

Webpack gives eslint errors while using npm link

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.

Webpack loader order misbehaved

I have used webpack ^2.2.1. I have added some loaders In my webpack.config.js file.
But my loader have not call in an order.
I used babel-loader for transform react-es6 codes to react-es5 codes. My custom-loader need react-es6 code. So I put my loader to first. I have print source content in each loaders. But every time first printing babel-loader info. After printing my info.
Is my loader order correct?
Help me! Thanks in advance!
// webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './build')
}
module: {
loaders: [
{
test: /\.js$/,
use: 'my-custom-loader'
},
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['babel-preset-es2015', 'babel-preset-react']
}
}
]
}
]
}
}
Loaders in Webpack are used in order "right to left" so the last loader in your array is used first. Therefore babel is translating everything and your loader is second in line.
See: What is the loader order for webpack?
Try switching the order of your loaders (and of course use module.rules instead of module.loaders, so that you are using the new Pattern in Webpack 2)

Include assets from webpack bundled npm package

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.

Load javascript in webpack

I am new to javascript dev in general and webpack in particular. I want to use this chess board module (https://github.com/oakmac/chessboardjs/) in my project. It sees to be exporting ChessBoard object. My project is using ES6, so I would love to be able to
import { ChessBoard } from 'chessboard'
or
import ChessBoard from 'chessboard'
I understand that I need some sort of loader for this. I have tried to add expose loader in the same way I use it for jQuery
{test: require.resolve("jquery"), loader: "expose?$!expose?jQuery"},
{test: require.resolve("chessboard"), loader: "expose?ChessBoard!./vendor/chessboard/js/chessboard-0.3.0.min.js"}
But I get "Error: Cannot find module 'chessboard'" error. Same if I replace ChessBoard with $. Not sure what I am doing wrong. Is expose even the right loader for what I am trying to do?
Here is my webpack config for reference (without the broken chessboard expose test)
var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'app/main.js')],
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js',
},
module: {
loaders: [
{test: require.resolve("jquery"), loader: "expose?$!expose?jQuery"},
{test: /\.jsx?$/, exclude: /(node_modules|bower_components)/, loader: 'babel', query: {presets: ['react', 'es2015']} },
/* CSS loaders */
{test: /\.css$/, loader: 'style!css'},
{test: /\.less$/, loader: 'style!css!less'},
/* font loaders for bootstrap */
{test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff'},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
{test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'},
],
},
plugins: [
new HtmlWebpackPlugin({
title: 'Test',
inject: false,
template: 'node_modules/html-webpack-template/index.ejs',
appMountId: 'app',
devServer: 'http://localhost:8080',
})
]
};
The problem seems to be that the chessboard.js is just a anonymous function and not a AMD or CommonJS module, and you may have to look at adding shims using webpack.
Not all JS files can be used directly with webpack. The file might be
in an unsupported module format, or not even in any module format.
https://github.com/webpack/docs/wiki/shimming-modules
Without seeing your entire webpack.config.js file it's tricky to say what the issue is. Basically you need to tell webpack to include `/node_modules/' into the list of paths it looks in for js modules.
You will need to add something like this to the resolve section of webpack.config.js.
modulesDirectories: ["node_modules"]
I guess you will need something like this in your webpack.config.js:
...
resolve: {
modules: [
'node_modules',
path.join( __dirname, 'node_modules' ),
path.resolve( './src' ),
...
You have to do two things:
1.) under plugins add:
new webpack.ProvidePlugin({
"window['jQuery']": "jquery"
})
2.) Install the script-loader plugin and import the script like this:
import 'script-loader!./chessboard.js';

Categories

Resources