Webpack 4 file-loader changes svg file content to __webpack_public_path__ - javascript

I have a project that uses Webpack 4. I use file-loader to handle images in html and fonts in the styles. But for the images, file-loader creates the image in dist folder but puts "module.exports = __webpack_public_path__ + "assets/fonts/main-logo.svg";" string in it. So i can see the correct path in the html but i can't see the image. Here is my webpack file:
webpack.common.js
const path = require('path');
module.exports = {
entry: "./src/index.js",
module: {
rules: [
{
test: /\.html$/,
use: ["html-loader"]
},
{
test: /\.(svg|png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
esModule: false,
name: "[name].[ext]",
outputPath: "assets/images"
}
}
},
{
test: /\.(woff(2)?|ttf|eot|svg)([\?]?.*)?$/,
exclude: /node_modules/,
use: {
loader: "file-loader",
options: {
esModule: false,
name: "[name].[ext]",
outputPath: "assets/fonts"
}
}
}
]
}
}
And this is the webpack.dev.js file for development env.
const common = require('./webpack.common');
const merge = require('webpack-merge');
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = merge(common, {
mode: "development",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist")
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/template.html"
})
],
module: {
rules: [
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
]
}
});

You are testing for files with .svg extension in two rules with the same loader.
If your intention is to output SVGs to assets/fonts you should remove the extension from the image files test:
const path = require('path');
module.exports = {
entry: "./src/index.js",
module: {
rules: [
{
test: /\.html$/,
use: ["html-loader"]
},
{
test: /\.(png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
esModule: false,
name: "[name].[ext]",
outputPath: "assets/images"
}
}
},
{
test: /\.(woff(2)?|ttf|eot|svg)([\?]?.*)?$/,
exclude: /node_modules/,
use: {
loader: "file-loader",
options: {
esModule: false,
name: "[name].[ext]",
outputPath: "assets/fonts"
}
}
}
]
}
}
Otherwise, if you want to output SVGs to assets/images, you should remove the extension from the fonts test:
const path = require('path');
module.exports = {
entry: "./src/index.js",
module: {
rules: [
{
test: /\.html$/,
use: ["html-loader"]
},
{
test: /\.(svg|png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
esModule: false,
name: "[name].[ext]",
outputPath: "assets/images"
}
}
},
{
test: /\.(woff(2)?|ttf|eot)([\?]?.*)?$/,
exclude: /node_modules/,
use: {
loader: "file-loader",
options: {
esModule: false,
name: "[name].[ext]",
outputPath: "assets/fonts"
}
}
}
]
}
}

Related

js and css file path are not loaded by webpack5 when used with pug

I'm using pug and scss with webpack 5. I have kept main.js and main.css both bundled by webpack but still the path is not resolved tried specific js path in src folder but same thing, they are not loading.
structure is like:
src:
index.js
style:
index.scss
views:
pages:
home.pug
base.pug
Please help it out
error picture
webpack.config.js:-
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCSSExtractPlugin = require('mini-css-extract-plugin')
const path = require('path')
const IS_DEVELOPMENT = 'dev'
module.exports = {
entry: [
path.resolve(__dirname, 'src/index.js'),
path.join(__dirname, 'styles/index.scss')
],
output:
{
filename: 'bundle.[contenthash].js',
path: path.resolve(__dirname, 'dist')
},
devtool: 'source-map',
plugins:
[
new CopyWebpackPlugin({
patterns: [
{ from: path.resolve(__dirname, 'static') }
]
}),
new HtmlWebpackPlugin({
filename: 'index.html',
template: path.resolve(__dirname, './views/pages/home.pug'),
minify: true
}),
new MiniCSSExtractPlugin({
filename: IS_DEVELOPMENT ? '[name].css' : '[name].[contenthash].css',
chunkFilename: IS_DEVELOPMENT ? '[id].css' : '[id].[contenthash].css',
})
],
module:
{
rules:
[
{
test: /\.(html)$/,
use: ['html-loader']
},
{
test: /\.(pug)$/,
use: ['html-loader', 'pug-html-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
use:
[
'babel-loader'
]
},
{
test: /\.css$/,
use:
[
MiniCSSExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.scss$/,
use:
[
{
loader: MiniCSSExtractPlugin.loader,
options: {
publicPath: ''
}
},
{
loader: 'css-loader'
}, {
loader: 'resolve-url-loader'
}, {
loader: 'sass-loader'
}
]
},
{
test: /\.(gltf|glb)$/,
use:
[
{
loader: 'file-loader',
options:
{
outputPath: 'assets/models/'
}
}
]
},
{
test: /\.(jpg|png|gif|svg)$/,
use:
[
{
loader: 'file-loader',
options:
{
outputPath: 'assets/images/'
}
}
]
},
{
test: /\.(ttf|eot|woff|woff2)$/,
use:
[
{
loader: 'file-loader',
options:
{
outputPath: 'assets/fonts/',
name: 'fonts/[name].[ext]',
mimetype: 'application/font-woff',
publicPath: '../'
}
}
]
},
{
test: /\.(glsl|vs|fs|vert|frag)$/,
exclude: /node_modules/,
use: [
'raw-loader',
'glslify-loader'
]
}
]
}
}

Need help injecting assets into a compiled index.html file

I'm trying to replace Gulp with WebPAck. I have this WebPack configuration that compiles a Nunjucks template and bundles js code and css code.
Instead of bundling, I'm trying to configure webpack to inject the vendor assets into the index.html header and body.
I looked into a few webpack plugins but it appears none of the work correctly. This is what I have now :
The nunjucks compilation breaks and the individual vendor assets dont get injected.
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const NunjucksWebpackPlugin = require('nunjucks-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');
const nunjuckspages = require('./nunjuckspages');
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = env => {
const devMode = !env || !env.production;
return {
mode: devMode ? 'development' : 'production',
entry: {
main: './src/index.js',
typescript_demo: './src/typescript_demo.ts',
vendor: './src/vendor.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'assets/js/[name].js',
library: 'MainModule',
},
module: {
rules: [
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader'},
{ loader: 'postcss-loader', options: { sourceMap: true } },
'resolve-url-loader',
{ loader: 'sass-loader', options: { sourceMap: true } }
]
},
{
test: /\.ts(x?)$/,
enforce: 'pre',
exclude: /node_modules/,
use: [
{
loader: 'tslint-loader',
options: { /* Loader options go here */ }
}
]
},
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
query: {
presets: [
'#babel/preset-env'
]
}
},
{
loader: 'ts-loader'
}
]
},
{
enforce: 'pre',
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: [
'#babel/preset-env'
]
}
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: '/assets/fonts/'
}
}]
}
]
},
stats: {
colors: true
},
devtool: 'source-map',
plugins: [
new NunjucksWebpackPlugin({
templates: nunjuckspages
}),
new MiniCssExtractPlugin({
filename: 'assets/css/[name].css'
}),
/// new StyleLintPlugin(),
new BrowserSyncPlugin({
host: 'localhost',
port: 3000,
server: { baseDir: ['dist'] }
}),
new ExtraWatchWebpackPlugin({
dirs: ['templates']
}),
new CopyWebpackPlugin([
// copyUmodified is true because of https://github.com/webpack-contrib/copy-webpack-plugin/pull/360
{ from: 'assets/**/*', to: '.' },
{ from: 'img/*', to: './img' },
], { copyUnmodified: true }),
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
inject: true,
hash: true,
publicPath: '/',
title: 'TEST1',
template: 'templates/_layouts/layout.html',
showErrors: true
}),
]
};
};

webpack 4 gives background: url([object Module]) as bg image

I'm having issues with setting up web-pack 4 and svg-sprite-loader to render svg icons as background images. I was following these instructions from official docs for svg-sprite-loader (https://github.com/kisenka/svg-sprite-loader/tree/master/examples/extract-mode).
I have successfully managed to create sprite.svg file in my dist folder and use it as reference for my use tags inside of html. However, i was also trying to use svg icons from my src/images/icons folder for a background image like this:
background: url('../images/icons/upload_icon.svg') 10% 50% no-repeat;
when doing this, webpack compiles correctly, but creates this in dist css file:
background: url([object Module]) 10% 50% no-repeat;
Any help would be great.
here is my webpack config file:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const SpriteLoaderPlugin = require("svg-sprite-loader/plugin");
module.exports = {
mode: "development",
devtool: "source-map",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
sourceMap: true
}
}
},
{
// scss configuration
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader"
},
{
loader: "postcss-loader"
},
{
loader: "sass-loader",
options: {
sourceMap: true
}
}
]
},
{
// html configuration
test: /\.html$/,
use: {
loader: "html-loader"
}
},
{
// images configuration
test: /\.(jpg|jpeg|gif|png|woff|woff2)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name].[ext]"
}
}
]
},
{
test: /\.svg$/,
use: [
{
loader: "svg-sprite-loader",
options: {
extract: true,
spriteFilename: "sprite.svg"
}
}
]
}
]
},
plugins: [
// all plugins used for compiling by webpack
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "Style Guide",
template: path.resolve(__dirname, "src", "index.html")
}),
new MiniCssExtractPlugin({
filename: "app.css"
}),
new SpriteLoaderPlugin()
]
};
Adding esModule: false to the file-loader options did the trick for me.
{
test: /\.(jpg|png|gif|svg)$/,
use: {
loader: 'file-loader',
options: {
name: "[name].[ext]",
outputPath: "img",
esModule: false
}
},
You have to pass esModule: false for svg-sprite-loader options.
By the way (it is not related to esModule): With MiniCssExtractPlugin you can not to extract svg sprite. I've faced this problem one hour ago..
After a few hours, I have managed to make this thing to work, thanks to #WimmDeveloper for pointing me in right direction. Main change from prior webpack config file is that I have added esModule: false in svg-sprite-loader options and replaced MiniCssExtractPlugin with extract-text-webpack-plugin. Mind you that this solution is not ideal since this webpack plugin is deprecated.
here is my full webpack config file:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const SpriteLoaderPlugin = require("svg-sprite-loader/plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
mode: "development",
devtool: "source-map",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
sourceMap: true
}
}
},
{
test: /\.(s*)css$/,
use: ExtractTextPlugin.extract({
use: ["css-loader", "postcss-loader", "sass-loader"]
})
},
{
// html configuration
test: /\.html$/,
use: {
loader: "html-loader"
}
},
{
test: /\.svg$/,
use: [
{
loader: "svg-sprite-loader",
options: {
esModule: false,
extract: true,
spriteFilename: "sprite.svg"
}
}
]
},
{
// files configuration
test: /\.(jpg|jpeg|gif|png|woff|woff2)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name].[ext]"
}
}
]
}
]
},
plugins: [
// all plugins used for compiling by webpack
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: "Style Guide",
template: path.resolve(__dirname, "src", "index.html")
}),
new ExtractTextPlugin({ filename: "app.css" }),
new SpriteLoaderPlugin()
]
};

Webpack doesn't resolve json file correctly

I have defined following method in a Vue page:
getIsoCountryCode: function(country){
console.log(countries);
return "flag-icon-" + countries.getAlpha2Code(country, 'en');
}
The function returns flag-icon-undefined, even though it works when I test it outside the Vue/Webpack environment.
Webpack config:
const { VueLoaderPlugin } = require("vue-loader");
const path = require("path");
module.exports = {
entry: "./lib/team-page/team.js",
devtool: "source-map",
watch: true,
resolve: {
alias: {
flag_icon_css: __dirname + "/node_modules/flag-icon-css/css/flag-icon.css"
}
},
output: {
path: path.resolve(__dirname, "public/lib"),
filename: "team.js"
},
mode: "development",
module: {
rules: [{
type: 'javascript/auto',
test: /\.(json|html)/,
exclude: /(node_modules|bower_components)/,
use: [{
loader: 'file-loader',
options: { name: '[name].[ext]' },
}]
},
{
test: /\.vue$/,
loader: "vue-loader"
},
{
test: /\.scss$/,
use: [
{loader: "style-loader"},
{
loader: "css-loader"
},
{
loader: "sass-loader"
}
]
},
{
test: /\.css$/,
use: [
{loader: "style-loader"},
{
loader: "css-loader"
}
]
},
{
test: /\.js$/,
loader: "babel-loader"
},
{
test: /\.svg$/,
loader: 'file-loader',
options: {
name: '../assets/flags/[name].[ext]'
}
}
]
},
plugins: [new VueLoaderPlugin()]
};
I checked in the debugger, and found this piece of code in the Webpack-compiled file:
var codes = __webpack_require__(/*! ./codes.json */ "./node_modules/i18n-iso-countries/codes.json");
It still points to the node_modules folder, even though I would have expected it to be in the bundle. (Edit: this doesn't seem to matter, axios is defined in the same way and that works as expected.)
I added the rule suggested here to my config file, but it still doesn't work.
Edit: to get it to work, you have to register the locale first. For English: countries.registerLocale(require("i18n-iso-countries/langs/en.json"));

Not a webpack file pug compiler?

When running webpack-dev-server produces an error
Module build failed: TypeError: text.forEach is not a function
enter image description here
'use strict';
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var path = require('path');
module.exports = {
entry: {
app: ['./client/main.js'],
index: ['./server/index.pug']
},
output: {
path: path.resolve(__dirname, "..", "public",'js'),
publicPath: "/js/",
filename: '[name].js'
},
module: {
rules: [
{
test: /\.pug$/,
loader: ExtractTextPlugin.extract( 'pug-loader')
},
{
test: /\.js$/,
loader: "babel-loader",
exclude: /node_modules/,
query: {
presets: ['es2015']
}
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [{
loader: "css-loader"
}, {
loader: "postcss-loader"
}, {
loader: "sass-loader"
}]
})
},
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
resolve: {
extensions: [".vue", ".js", ".json",".pug",".html"],
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
plugins: [
new ExtractTextPlugin("[name].html"),
new ExtractTextPlugin("[name].css"),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: "main",
minChunks: 2
})
],
}
Before that, I tried to do it through HtmlWebpackPlugin but there it returned plain text!

Categories

Resources